From bf22e90c6587c163dec5dff811bf85b7cfb7effe Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Fri, 25 Oct 2024 12:13:22 +0100 Subject: [PATCH 01/15] PCH Refactor: Refactor Internal API and External Services (#2889) * Add new Rest API base classes * Implement the Content Helper API namespace * Add tests for the new REST API classes * Update UI providers to use the new API endpoints * Remove unused code and initializations * Fix sonarcloud issues * Refactor to avoid consts and use getters instead * Fix minor docblock issues per code review * Apply code review suggestions by @acicovic * Rename API parameter `content` to `text` * Add `stats` endpoint * Update the UI to use the new API endpoints * Delete the old endpoints * Add tests * Apply code review suggestions by @acicovic * Add `stats` endpoint * Update the UI to use the new API endpoints * Delete the old endpoints * Add tests * Fix E2E test * Add `settings` endpoints * Update UI to use the new settings API * Add tests * Remove old code * Improve comments and whitespace * class-base-endpoint.php: Fix incorrect whitespace * Endpoints/class-base-endpoint.php: Fix incorrect whitespace * Improve comments and whitespace * Improve comments and whitespace * REST API Refactor: Apply fixes/suggestions from the other PRs (#2812) * Apply suggestions from #2731 * Apply suggestions from #2735 * Add dynamic settings endpoint calls * PCH Refactor: Refactor the external services (#2873) * Implement the new Content API service, and remove old RemoteAPI code * Implement caching mechanism for service endpoints * Implement the Suggestions API service * Address PHPCS & PHPStan errors and warnings * Fix post-merge issues and namespaces * Add condition when validate api credentials returns false. * Address code review feedback * Adjust some DocBlocks and whitespace * Make the services base URL static, and remove the old consts * Fix PHPStan (not including tests) * Fix misplaced `@since` tag --------- Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> * PCH Refactor: Update integration tests (#2885) * Implement and update integration tests * Adjust some DocBlocks and whitespace * Adjust some DocBlocks and whitespace * Fix tests * Fix leaking tests * Apply code review suggestions * Remove backticks from function summary * Improve code formatting consistency between 2 tests --------- Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> * Rebuild assets --------- Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> --- .phpcs.xml.dist | 4 +- build/blocks/recommendations/edit.asset.php | 2 +- build/blocks/recommendations/edit.js | 2 +- build/blocks/recommendations/view.asset.php | 2 +- build/blocks/recommendations/view.js | 2 +- .../content-helper/dashboard-widget.asset.php | 2 +- build/content-helper/dashboard-widget.js | 2 +- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.js | 18 +- .../excerpt-generator.asset.php | 2 +- build/content-helper/excerpt-generator.js | 2 +- phpstan.neon | 2 +- .../class-analytics-post-detail-api-proxy.php | 48 -- .../class-analytics-posts-api-proxy.php | 48 -- src/Endpoints/class-base-api-proxy.php | 281 -------- src/Endpoints/class-base-endpoint.php | 194 ------ .../class-referrers-post-detail-api-proxy.php | 259 ------- src/Endpoints/class-related-api-proxy.php | 61 -- .../class-suggest-brief-api-proxy.php | 152 ---- .../class-suggest-headline-api-proxy.php | 123 ---- ...ass-suggest-linked-reference-api-proxy.php | 162 ----- src/Models/class-smart-link.php | 4 +- .../class-analytics-post-detail-api.php | 45 -- src/RemoteAPI/class-analytics-posts-api.php | 107 --- src/RemoteAPI/class-base-endpoint-remote.php | 149 ---- .../class-referrers-post-detail-api.php | 45 -- src/RemoteAPI/class-related-api.php | 39 -- src/RemoteAPI/class-remote-api-cache.php | 91 --- src/RemoteAPI/class-validate-api.php | 124 ---- src/RemoteAPI/class-wordpress-cache.php | 52 -- .../class-content-suggestions-base-api.php | 208 ------ .../class-suggest-brief-api.php | 73 -- .../class-suggest-headline-api.php | 69 -- .../class-suggest-linked-reference-api.php | 88 --- src/RemoteAPI/interface-cache.php | 46 -- src/RemoteAPI/interface-remote-api.php | 41 -- src/UI/class-recommended-widget.php | 4 +- src/UI/class-settings-page.php | 7 +- .../parsely-recommendations-fetcher.tsx | 2 +- .../components/parsely-recommendations.tsx | 2 +- .../recommendations/recommendations-store.tsx | 4 +- src/class-parsely.php | 106 ++- src/class-validator.php | 15 +- .../common/class-content-helper-feature.php | 8 +- .../common/settings/provider.tsx | 3 +- .../class-dashboard-widget.php | 13 +- .../dashboard-widget/dashboard-widget.tsx | 2 +- .../dashboard-widget/provider.ts | 2 +- .../editor-sidebar/class-editor-sidebar.php | 10 +- .../editor-sidebar/editor-sidebar.tsx | 4 +- .../performance-stats/provider.ts | 40 +- .../editor-sidebar/related-posts/provider.ts | 2 +- .../editor-sidebar/smart-linking/provider.ts | 12 +- .../smart-linking/smart-linking.tsx | 2 +- .../title-suggestions/provider.ts | 4 +- .../excerpt-generator/provider.ts | 4 +- .../post-list-stats/class-post-list-stats.php | 61 +- src/rest-api/class-base-api-controller.php | 204 ++++++ src/rest-api/class-base-endpoint.php | 307 +++++++++ src/rest-api/class-rest-api-controller.php | 127 ++++ .../class-content-helper-controller.php | 49 ++ .../class-endpoint-excerpt-generator.php | 198 ++++++ .../class-endpoint-smart-linking.php} | 359 ++++++---- .../class-endpoint-title-suggestions.php | 173 +++++ .../trait-content-helper-feature.php | 68 ++ .../class-base-settings-endpoint.php} | 222 +++--- ...ss-endpoint-dashboard-widget-settings.php} | 26 +- ...lass-endpoint-editor-sidebar-settings.php} | 28 +- .../settings/class-settings-controller.php | 47 ++ src/rest-api/stats/class-endpoint-post.php | 499 ++++++++++++++ src/rest-api/stats/class-endpoint-posts.php | 280 ++++++++ src/rest-api/stats/class-endpoint-related.php | 121 ++++ src/rest-api/stats/class-stats-controller.php | 48 ++ src/rest-api/stats/trait-post-data.php | 146 ++++ src/rest-api/stats/trait-related-posts.php | 155 +++++ src/rest-api/trait-use-post-id-parameter.php | 89 +++ src/services/class-base-api-service.php | 133 ++++ src/services/class-base-service-endpoint.php | 260 +++++++ .../class-cached-service-endpoint.php | 165 +++++ .../content-api/class-content-api-service.php | 234 +++++++ .../class-content-api-base-endpoint.php | 89 +++ .../class-endpoint-analytics-post-details.php | 54 ++ .../class-endpoint-analytics-posts.php | 182 +++++ .../class-endpoint-referrers-post-detail.php | 54 ++ .../endpoints/class-endpoint-related.php | 53 ++ .../endpoints/class-endpoint-validate.php | 112 +++ .../class-suggestions-api-service.php | 115 +++ .../class-endpoint-suggest-brief.php | 93 +++ .../class-endpoint-suggest-headline.php | 96 +++ ...lass-endpoint-suggest-linked-reference.php | 117 ++++ .../class-suggestions-api-base-endpoint.php | 123 ++++ .../ContentHelperDashboardWidgetTest.php | 45 +- .../ContentHelperFeatureTest.php | 44 +- .../ContentHelperPostListStatsTest.php | 52 +- .../Proxy/AnalyticsPostsProxyEndpointTest.php | 264 ------- .../Endpoints/Proxy/BaseProxyEndpointTest.php | 245 ------- .../ReferrersPostDetailProxyEndpointTest.php | 305 -------- .../Proxy/RelatedProxyEndpointTest.php | 162 ----- .../StatsPostDetailProxyEndpointTest.php | 206 ------ .../Endpoints/RestMetadataTest.php | 1 - .../UserMeta/BaseUserMetaEndpointTest.php | 169 ----- .../DashboardWidgetSettingsEndpointTest.php | 204 ------ .../EditorSidebarSettingsEndpointTest.php | 309 --------- .../RemoteAPI/AnalyticsPostsRemoteAPITest.php | 128 ---- .../RemoteAPI/BaseRemoteAPITest.php | 163 ----- .../BaseContentSuggestionsAPITest.php | 129 ---- .../SuggestBriefAPITest.php | 137 ---- .../RemoteAPI/RelatedRemoteAPITest.php | 94 --- .../RestAPI/BaseAPIControllerTest.php | 270 ++++++++ .../Integration/RestAPI/BaseEndpointTest.php | 447 ++++++++++++ .../ContentHelperControllerTest.php | 106 +++ .../ContentHelperFeatureTestTrait.php | 289 ++++++++ .../EndpointExcerptGeneratorTest.php | 203 ++++++ .../EndpointSmartLinkingTest.php | 429 ++++++++++++ .../EndpointTitleSuggestionsTest.php | 180 +++++ .../RestAPI/RestAPIControllerTest.php | 57 ++ .../Settings/BaseSettingsEndpointTest.php | 221 ++++++ .../EndpointDashboardWidgetSettingsTest.php | 204 ++++++ .../EndpointEditorSidebarSettingsTest.php | 312 +++++++++ .../RestAPI/Stats/EndpointPostTest.php | 652 ++++++++++++++++++ .../RestAPI/Stats/EndpointPostsTest.php | 335 +++++++++ .../RestAPI/Stats/EndpointRelatedTest.php | 304 ++++++++ .../RestAPI/Stats/StatsControllerTest.php | 61 ++ tests/Integration/ScriptsTest.php | 10 +- .../Services/BaseAPIServiceTestCase.php | 57 ++ .../Services/BaseServiceEndpointTestCase.php | 136 ++++ .../ContentAPI/ContentApiServiceTestCase.php | 133 ++++ .../ContentAPIBaseEndpointTestCase.php | 129 ++++ .../Endpoints/EndpointAnalyticsPostsTest.php | 48 ++ .../Endpoints/EndpointRelatedTest.php | 54 ++ .../Endpoints/EndpointSuggestBriefTest.php | 132 ++++ .../EndpointSuggestHeadlineTest.php} | 64 +- .../EndpointSuggestLinkedReferenceTest.php} | 81 ++- .../SuggestionsAPIBaseEndpointTestCase.php | 131 ++++ .../SuggestionsApiServiceTestCase.php | 115 +++ tests/Integration/TestCase.php | 12 +- tests/Traits/TestsReflection.php | 67 +- wp-parsely.php | 111 +-- 138 files changed, 10209 insertions(+), 5682 deletions(-) delete mode 100644 src/Endpoints/class-analytics-post-detail-api-proxy.php delete mode 100644 src/Endpoints/class-analytics-posts-api-proxy.php delete mode 100644 src/Endpoints/class-base-api-proxy.php delete mode 100644 src/Endpoints/class-base-endpoint.php delete mode 100644 src/Endpoints/class-referrers-post-detail-api-proxy.php delete mode 100644 src/Endpoints/class-related-api-proxy.php delete mode 100644 src/Endpoints/content-suggestions/class-suggest-brief-api-proxy.php delete mode 100644 src/Endpoints/content-suggestions/class-suggest-headline-api-proxy.php delete mode 100644 src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php delete mode 100644 src/RemoteAPI/class-analytics-post-detail-api.php delete mode 100644 src/RemoteAPI/class-analytics-posts-api.php delete mode 100644 src/RemoteAPI/class-base-endpoint-remote.php delete mode 100644 src/RemoteAPI/class-referrers-post-detail-api.php delete mode 100644 src/RemoteAPI/class-related-api.php delete mode 100644 src/RemoteAPI/class-remote-api-cache.php delete mode 100644 src/RemoteAPI/class-validate-api.php delete mode 100644 src/RemoteAPI/class-wordpress-cache.php delete mode 100644 src/RemoteAPI/content-suggestions/class-content-suggestions-base-api.php delete mode 100644 src/RemoteAPI/content-suggestions/class-suggest-brief-api.php delete mode 100644 src/RemoteAPI/content-suggestions/class-suggest-headline-api.php delete mode 100644 src/RemoteAPI/content-suggestions/class-suggest-linked-reference-api.php delete mode 100644 src/RemoteAPI/interface-cache.php delete mode 100644 src/RemoteAPI/interface-remote-api.php create mode 100644 src/rest-api/class-base-api-controller.php create mode 100644 src/rest-api/class-base-endpoint.php create mode 100644 src/rest-api/class-rest-api-controller.php create mode 100644 src/rest-api/content-helper/class-content-helper-controller.php create mode 100644 src/rest-api/content-helper/class-endpoint-excerpt-generator.php rename src/{Endpoints/content-helper/class-smart-linking-endpoint.php => rest-api/content-helper/class-endpoint-smart-linking.php} (68%) create mode 100644 src/rest-api/content-helper/class-endpoint-title-suggestions.php create mode 100644 src/rest-api/content-helper/trait-content-helper-feature.php rename src/{Endpoints/user-meta/class-base-endpoint-user-meta.php => rest-api/settings/class-base-settings-endpoint.php} (64%) rename src/{Endpoints/user-meta/class-dashboard-widget-settings-endpoint.php => rest-api/settings/class-endpoint-dashboard-widget-settings.php} (59%) rename src/{Endpoints/user-meta/class-editor-sidebar-settings-endpoint.php => rest-api/settings/class-endpoint-editor-sidebar-settings.php} (78%) create mode 100644 src/rest-api/settings/class-settings-controller.php create mode 100644 src/rest-api/stats/class-endpoint-post.php create mode 100644 src/rest-api/stats/class-endpoint-posts.php create mode 100644 src/rest-api/stats/class-endpoint-related.php create mode 100644 src/rest-api/stats/class-stats-controller.php create mode 100644 src/rest-api/stats/trait-post-data.php create mode 100644 src/rest-api/stats/trait-related-posts.php create mode 100644 src/rest-api/trait-use-post-id-parameter.php create mode 100644 src/services/class-base-api-service.php create mode 100644 src/services/class-base-service-endpoint.php create mode 100644 src/services/class-cached-service-endpoint.php create mode 100644 src/services/content-api/class-content-api-service.php create mode 100644 src/services/content-api/endpoints/class-content-api-base-endpoint.php create mode 100644 src/services/content-api/endpoints/class-endpoint-analytics-post-details.php create mode 100644 src/services/content-api/endpoints/class-endpoint-analytics-posts.php create mode 100644 src/services/content-api/endpoints/class-endpoint-referrers-post-detail.php create mode 100644 src/services/content-api/endpoints/class-endpoint-related.php create mode 100644 src/services/content-api/endpoints/class-endpoint-validate.php create mode 100644 src/services/suggestions-api/class-suggestions-api-service.php create mode 100644 src/services/suggestions-api/endpoints/class-endpoint-suggest-brief.php create mode 100644 src/services/suggestions-api/endpoints/class-endpoint-suggest-headline.php create mode 100644 src/services/suggestions-api/endpoints/class-endpoint-suggest-linked-reference.php create mode 100644 src/services/suggestions-api/endpoints/class-suggestions-api-base-endpoint.php delete mode 100644 tests/Integration/Endpoints/Proxy/AnalyticsPostsProxyEndpointTest.php delete mode 100644 tests/Integration/Endpoints/Proxy/BaseProxyEndpointTest.php delete mode 100644 tests/Integration/Endpoints/Proxy/ReferrersPostDetailProxyEndpointTest.php delete mode 100644 tests/Integration/Endpoints/Proxy/RelatedProxyEndpointTest.php delete mode 100644 tests/Integration/Endpoints/Proxy/StatsPostDetailProxyEndpointTest.php delete mode 100644 tests/Integration/Endpoints/UserMeta/BaseUserMetaEndpointTest.php delete mode 100644 tests/Integration/Endpoints/UserMeta/DashboardWidgetSettingsEndpointTest.php delete mode 100644 tests/Integration/Endpoints/UserMeta/EditorSidebarSettingsEndpointTest.php delete mode 100644 tests/Integration/RemoteAPI/AnalyticsPostsRemoteAPITest.php delete mode 100644 tests/Integration/RemoteAPI/BaseRemoteAPITest.php delete mode 100644 tests/Integration/RemoteAPI/ContentSuggestions/BaseContentSuggestionsAPITest.php delete mode 100644 tests/Integration/RemoteAPI/ContentSuggestions/SuggestBriefAPITest.php delete mode 100644 tests/Integration/RemoteAPI/RelatedRemoteAPITest.php create mode 100644 tests/Integration/RestAPI/BaseAPIControllerTest.php create mode 100644 tests/Integration/RestAPI/BaseEndpointTest.php create mode 100644 tests/Integration/RestAPI/ContentHelper/ContentHelperControllerTest.php create mode 100644 tests/Integration/RestAPI/ContentHelper/ContentHelperFeatureTestTrait.php create mode 100644 tests/Integration/RestAPI/ContentHelper/EndpointExcerptGeneratorTest.php create mode 100644 tests/Integration/RestAPI/ContentHelper/EndpointSmartLinkingTest.php create mode 100644 tests/Integration/RestAPI/ContentHelper/EndpointTitleSuggestionsTest.php create mode 100644 tests/Integration/RestAPI/RestAPIControllerTest.php create mode 100644 tests/Integration/RestAPI/Settings/BaseSettingsEndpointTest.php create mode 100644 tests/Integration/RestAPI/Settings/EndpointDashboardWidgetSettingsTest.php create mode 100644 tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php create mode 100644 tests/Integration/RestAPI/Stats/EndpointPostTest.php create mode 100644 tests/Integration/RestAPI/Stats/EndpointPostsTest.php create mode 100644 tests/Integration/RestAPI/Stats/EndpointRelatedTest.php create mode 100644 tests/Integration/RestAPI/Stats/StatsControllerTest.php create mode 100644 tests/Integration/Services/BaseAPIServiceTestCase.php create mode 100644 tests/Integration/Services/BaseServiceEndpointTestCase.php create mode 100644 tests/Integration/Services/ContentAPI/ContentApiServiceTestCase.php create mode 100644 tests/Integration/Services/ContentAPI/Endpoints/ContentAPIBaseEndpointTestCase.php create mode 100644 tests/Integration/Services/ContentAPI/Endpoints/EndpointAnalyticsPostsTest.php create mode 100644 tests/Integration/Services/ContentAPI/Endpoints/EndpointRelatedTest.php create mode 100644 tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestBriefTest.php rename tests/Integration/{RemoteAPI/ContentSuggestions/SuggestHeadlineAPITest.php => Services/SuggestionsAPI/Endpoints/EndpointSuggestHeadlineTest.php} (57%) rename tests/Integration/{RemoteAPI/ContentSuggestions/SuggestLinkedReferenceAPITest.php => Services/SuggestionsAPI/Endpoints/EndpointSuggestLinkedReferenceTest.php} (57%) create mode 100644 tests/Integration/Services/SuggestionsAPI/Endpoints/SuggestionsAPIBaseEndpointTestCase.php create mode 100644 tests/Integration/Services/SuggestionsAPI/SuggestionsApiServiceTestCase.php diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist index f863936f2..7aa088a3b 100644 --- a/.phpcs.xml.dist +++ b/.phpcs.xml.dist @@ -79,9 +79,9 @@ - + - /tests/ + / diff --git a/build/blocks/recommendations/edit.asset.php b/build/blocks/recommendations/edit.asset.php index 46911d454..5ab57ae0f 100644 --- a/build/blocks/recommendations/edit.asset.php +++ b/build/blocks/recommendations/edit.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '985cd7ad36a37322fb62'); + array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => 'f73735ea0f420620d3aa'); diff --git a/build/blocks/recommendations/edit.js b/build/blocks/recommendations/edit.js index 4b065685c..aef6a829b 100644 --- a/build/blocks/recommendations/edit.js +++ b/build/blocks/recommendations/edit.js @@ -1 +1 @@ -!function(){"use strict";var e,n={271:function(e,n,r){var t,o,a=r(848),i=window.wp.blockEditor,l=window.wp.blocks,s=window.wp.i18n,c=window.wp.components,u=JSON.parse('{"UU":"wp-parsely/recommendations","uK":{"imagestyle":{"type":"string","default":"original"},"limit":{"type":"number","default":3},"openlinksinnewtab":{"type":"boolean","default":false},"showimages":{"type":"boolean","default":true},"sort":{"type":"string","default":"score"},"title":{"type":"string","default":"Related Content"}}}'),d=window.wp.element;(o=t||(t={}))[o.Error=0]="Error",o[o.Loaded=1]="Loaded",o[o.Recommendations=2]="Recommendations";var p=function(){return p=Object.assign||function(e){for(var n,r=1,t=arguments.length;r0&&o[o.length-1])||6!==l[0]&&2!==l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]=a)&&Object.keys(t.O).every((function(e){return t.O[e](r[s])}))?r.splice(s--,1):(l=!1,a0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[r,o,a]},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,{a:n}),n},t.d=function(e,n){for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},function(){var e={335:0,203:0};t.O.j=function(n){return 0===e[n]};var n=function(n,r){var o,a,i=r[0],l=r[1],s=r[2],c=0;if(i.some((function(n){return 0!==e[n]}))){for(o in l)t.o(l,o)&&(t.m[o]=l[o]);if(s)var u=s(t)}for(n&&n(r);c0&&o[o.length-1])||6!==l[0]&&2!==l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]=a)&&Object.keys(t.O).every((function(e){return t.O[e](r[s])}))?r.splice(s--,1):(l=!1,a0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[r,o,a]},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,{a:n}),n},t.d=function(e,n){for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},function(){var e={335:0,203:0};t.O.j=function(n){return 0===e[n]};var n=function(n,r){var o,a,i=r[0],l=r[1],s=r[2],c=0;if(i.some((function(n){return 0!==e[n]}))){for(o in l)t.o(l,o)&&(t.m[o]=l[o]);if(s)var u=s(t)}for(n&&n(r);c array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '816c6be0377185053443'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => 'db27a5e749f0f3888bee'); diff --git a/build/blocks/recommendations/view.js b/build/blocks/recommendations/view.js index 6e83362dc..4afeebc4c 100644 --- a/build/blocks/recommendations/view.js +++ b/build/blocks/recommendations/view.js @@ -1 +1 @@ -!function(){"use strict";var e={20:function(e,r,n){var t=n(609),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,s=t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,r,n){var t,a={},c=null,u=null;for(t in void 0!==n&&(c=""+n),void 0!==r.key&&(c=""+r.key),void 0!==r.ref&&(u=r.ref),r)i.call(r,t)&&!l.hasOwnProperty(t)&&(a[t]=r[t]);if(e&&e.defaultProps)for(t in r=e.defaultProps)void 0===a[t]&&(a[t]=r[t]);return{$$typeof:o,type:e,key:c,ref:u,props:a,_owner:s.current}}r.Fragment=a,r.jsx=c,r.jsxs=c},848:function(e,r,n){e.exports=n(20)},609:function(e){e.exports=window.React}},r={};function n(t){var o=r[t];if(void 0!==o)return o.exports;var a=r[t]={exports:{}};return e[t](a,a.exports,n),a.exports}n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,{a:r}),r},n.d=function(e,r){for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)};var t,o,a=n(848),i=n(609),s=window.wp.domReady,l=n.n(s),c=window.wp.element,u=window.wp.i18n;(o=t||(t={}))[o.Error=0]="Error",o[o.Loaded=1]="Loaded",o[o.Recommendations=2]="Recommendations";var d=function(){return d=Object.assign||function(e){for(var r,n=1,t=arguments.length;n0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1] array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '86a5430e052e357f1b96'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '3a7734d69011884c8267'); diff --git a/build/content-helper/dashboard-widget.js b/build/content-helper/dashboard-widget.js index 87e3d6eda..c2b0d9057 100644 --- a/build/content-helper/dashboard-widget.js +++ b/build/content-helper/dashboard-widget.js @@ -1 +1 @@ -!function(){"use strict";var e={20:function(e,t,r){var n=r(609),a=Symbol.for("react.element"),s=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,i=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,s={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)o.call(t,n)&&!l.hasOwnProperty(n)&&(s[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===s[n]&&(s[n]=t[n]);return{$$typeof:a,type:e,key:c,ref:u,props:s,_owner:i.current}}t.Fragment=s,t.jsx=c,t.jsxs=c},848:function(e,t,r){e.exports=r(20)},609:function(e){e.exports=window.React}},t={};function r(n){var a=t[n];if(void 0!==a)return a.exports;var s=t[n]={exports:{}};return e[n](s,s.exports,r),s.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e,t,n,a=r(848),s=window.wp.element,o=window.wp.i18n,i=function(e){void 0===e&&(e=null);var t="";(null==e?void 0:e.children)&&(t=e.children);var r="content-helper-error-message";return(null==e?void 0:e.className)&&(r+=" "+e.className),(0,a.jsx)("div",{className:r,"data-testid":null==e?void 0:e.testId,dangerouslySetInnerHTML:{__html:t}})},l=function(e){var t;return void 0===e&&(e=null),(0,a.jsx)(i,{className:null==e?void 0:e.className,testId:"empty-credentials-message",children:null!==(t=window.wpParselyEmptyCredentialsMessage)&&void 0!==t?t:(0,o.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})},c=function(){return c=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]=1e4&&(clearInterval(s),r("Telemetry library not loaded"))}),100);else r("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,r){var n;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(r=this.prepareProperties(r),null===(n=this._tkq)||void 0===n||n.push(["recordEvent",t,r])):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,r={};return Object.keys(e).forEach((function(n){t.isProprietyValid(n)&&(r[n]=e[n])})),r},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),h=(d.trackEvent,function(e){var t=e.defaultValue,r=e.items,n=e.onChange;return(0,a.jsx)("select",{onChange:n,value:t,children:r.map((function(e){return(0,a.jsx)("option",{value:e[0],children:e[1]},e[0])}))})}),f=window.wp.data,y=function(){return y=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0?"".concat(a," ").concat(r):r)||this).hint=null,s.name=s.constructor.name,s.code=n;var i=[T.AccessToFeatureDisabled,T.ParselyApiForbidden,T.ParselyApiResponseContainsError,T.ParselyApiReturnedNoData,T.ParselyApiReturnedTooManyResults,T.PluginCredentialsNotSetMessageDetected,T.PluginSettingsApiSecretNotSet,T.PluginSettingsSiteIdNotSet,T.PostIsNotPublished,T.UnknownError,T.ParselySuggestionsApiAuthUnavailable,T.ParselySuggestionsApiNoAuthentication,T.ParselySuggestionsApiNoAuthorization,T.ParselySuggestionsApiNoData,T.ParselySuggestionsApiSchemaError];return s.retryFetch=!i.includes(s.code),Object.setPrototypeOf(s,t.prototype),s.code===T.AccessToFeatureDisabled?s.message=(0,o.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):s.code===T.ParselySuggestionsApiNoAuthorization?s.message=(0,o.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):s.code===T.ParselySuggestionsApiOpenAiError||s.code===T.ParselySuggestionsApiOpenAiUnavailable?s.message=(0,o.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):s.code===T.HttpRequestFailed&&s.message.includes("cURL error 28")?s.message=(0,o.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):s.code===T.ParselySuggestionsApiSchemaError?s.message=(0,o.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):s.code===T.ParselySuggestionsApiNoData?s.message=(0,o.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):s.code===T.ParselySuggestionsApiOpenAiSchema?s.message=(0,o.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):s.code===T.ParselySuggestionsApiAuthUnavailable&&(s.message=(0,o.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),s}return O(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[T.PluginCredentialsNotSetMessageDetected,T.PluginSettingsSiteIdNotSet,T.PluginSettingsApiSecretNotSet].includes(this.code)?l(e):(this.code===T.FetchError&&(this.hint=this.Hint((0,o.__)("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!==T.ParselyApiForbidden&&this.code!==T.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,o.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===T.HttpRequestFailed&&(this.hint=this.Hint((0,o.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,a.jsx)(i,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,o.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,f.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),C=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,r=Array.from(this.abortControllers.keys()).pop();r&&(t=this.abortControllers.get(r))&&(t.abort(),this.abortControllers.delete(r))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),r=new AbortController;return this.abortControllers.set(t,r),{abortController:r,abortId:t}},e.prototype.fetch=function(e,t){return r=this,n=void 0,s=function(){var r,n,a,s,i,l;return function(e,t){var r,n,a,s={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},o=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return o.next=i(0),o.throw=i(1),o.return=i(2),"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(i){return function(l){return function(i){if(r)throw new TypeError("Generator is already executing.");for(;o&&(o=0,i[0]&&(s=0)),s;)try{if(r=1,n&&(a=2&i[0]?n.return:i[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,i[1])).done)return a;switch(n=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,n=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((a=(a=s.trys).length>0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]=c){var u=t;(a=n/c)%1>1/i&&(u=a>10?1:2),u=parseFloat(a.toFixed(2))===parseFloat(a.toFixed(0))?0:u,s=a.toFixed(u),o=l}i=c})),s+r+o}function z(e){var t=e.metric,r=e.post,n=e.avgEngagedIcon,s=e.viewsIcon;return"views"===t?(0,a.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Number of Views","wp-parsely")}),s,$(r.views.toString())]}):"avg_engaged"===t?(0,a.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Average Time","wp-parsely")}),n,r.avgEngaged]}):(0,a.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}function X(e){var t,r=e.metric,n=e.post;return(0,a.jsx)("li",{className:"parsely-top-post",children:(0,a.jsxs)("div",{className:"parsely-top-post-content",children:[(0,a.jsx)(B,{post:n}),(0,a.jsxs)("div",{className:"parsely-top-post-data",children:[(0,a.jsx)(z,{metric:r,post:n}),(0,a.jsx)(Z,{post:n}),(0,a.jsxs)("a",{className:"parsely-top-post-icon-link",href:n.url,target:"_blank",rel:"noreferrer",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("View Post (opens in new tab)","wp-parsely")}),(0,a.jsx)(q,{})]}),0!==n.postId&&(0,a.jsxs)("a",{className:"parsely-top-post-icon-link",href:(t=n.postId,"/wp-admin/post.php?post=".concat(t,"&action=edit")),target:"_blank",rel:"noreferrer",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Edit Post (opens in new tab)","wp-parsely")}),(0,a.jsx)(G,{})]}),(0,a.jsxs)("div",{className:"parsely-top-post-metadata",children:[(0,a.jsxs)("span",{className:"parsely-top-post-date",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Date","wp-parsely")}),M(new Date(n.date))]}),(0,a.jsxs)("span",{className:"parsely-top-post-author",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Author","wp-parsely")}),n.author]})]})]})]})},n.id)}function B(e){var t=e.post;return t.thumbnailUrl?(0,a.jsxs)("div",{className:"parsely-top-post-thumbnail",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Thumbnail","wp-parsely")}),(0,a.jsx)("img",{src:t.thumbnailUrl,alt:(0,o.__)("Post thumbnail","wp-parsely")})]}):(0,a.jsx)("div",{className:"parsely-top-post-thumbnail",children:(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Post thumbnail not available","wp-parsely")})})}function Z(e){var t=e.post;return(0,a.jsxs)("a",{className:"parsely-top-post-title",href:t.dashUrl,target:"_blank",rel:"noreferrer",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("View in Parse.ly (opens in new tab)","wp-parsely")}),t.title]})}var W=function(){return W=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,t(n-1)];case 2:return r.sent(),[3,4];case 3:f(!1),v(e),r.label=4;case 4:return[2]}}))}))})),[2]}))}))};return f(!0),t(1),function(){f(!1),b([]),v(void 0)}}),[i,S]);var T=function(e,t){d.trackEvent("dash_widget_filter_changed",W({filter:e},t))},N=(0,a.jsxs)("div",{className:"parsely-top-posts-filters",children:[(0,a.jsx)(h,{defaultValue:i.Period,items:Object.values(e).map((function(e){return[e,A(e)]})),onChange:function(t){x(t.target.value,e)&&(l({Period:t.target.value}),T("period",{period:t.target.value}),E(1))}}),(0,a.jsx)(h,{defaultValue:i.Metric,items:Object.values(t).map((function(e){return[e,j(e)]})),onChange:function(e){x(e.target.value,t)&&(l({Metric:e.target.value}),T("metric",{metric:e.target.value}),E(1))}})]}),O=(0,a.jsxs)("div",{className:"parsely-top-posts-navigation",children:[(0,a.jsx)("button",{className:"parsely-top-posts-navigation-prev",disabled:S<=1,"aria-label":(0,o.__)("Previous page","wp-parsely"),onClick:function(){E(S-1),d.trackEvent("dash_widget_navigation",{navigation:"previous",to_page:S-1})},children:(0,o.__)("<< Previous","wp-parsely")}),(0,o.sprintf)(/* translators: 1: Current page */ /* translators: 1: Current page */(0,o.__)("Page %1$d","wp-parsely"),S),(0,a.jsx)("button",{className:"parsely-top-posts-navigation-next",disabled:!u&&_.length<5,"aria-label":(0,o.__)("Next page","wp-parsely"),onClick:function(){E(S+1),d.trackEvent("dash_widget_navigation",{navigation:"next",to_page:S+1})},children:(0,o.__)("Next >>","wp-parsely")})]});if(g)return(0,a.jsxs)(a.Fragment,{children:[N,g.Message(),S>1&&O]});var I=(0,a.jsx)("div",{className:"parsely-spinner-wrapper",children:(0,a.jsx)(p.Spinner,{})});return(0,a.jsxs)(a.Fragment,{children:[N,u?I:(0,a.jsx)("ol",{className:"parsely-top-posts",style:{counterReset:"item "+5*(S-1)},children:_.map((function(e){return(0,a.jsx)(X,{metric:i.Metric,post:e},e.id)}))}),(_.length>=5||S>1)&&O]})}var J=function(r){var n;try{n=JSON.parse(r)}catch(r){return{Metric:t.Views,Period:e.Days7}}return x(null==n?void 0:n.Metric,t)||(n.Metric=t.Views),x(null==n?void 0:n.Period,e)||(n.Period=e.Days7),n};window.addEventListener("load",(function(){var e=document.querySelector("#wp-parsely-dashboard-widget > .inside");if(null!==e){var t=(0,a.jsx)(S,{endpoint:"dashboard-widget-settings",defaultSettings:J(window.wpParselyContentHelperSettings),children:(0,a.jsx)(u,{children:(0,a.jsx)(Q,{})})});s.createRoot?(0,s.createRoot)(e).render(t):(0,s.render)(t,e)}}),!1)}()}(); \ No newline at end of file +!function(){"use strict";var e={20:function(e,t,r){var n=r(609),a=Symbol.for("react.element"),s=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,i=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,s={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)o.call(t,n)&&!l.hasOwnProperty(n)&&(s[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===s[n]&&(s[n]=t[n]);return{$$typeof:a,type:e,key:c,ref:u,props:s,_owner:i.current}}t.Fragment=s,t.jsx=c,t.jsxs=c},848:function(e,t,r){e.exports=r(20)},609:function(e){e.exports=window.React}},t={};function r(n){var a=t[n];if(void 0!==a)return a.exports;var s=t[n]={exports:{}};return e[n](s,s.exports,r),s.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e,t,n,a=r(848),s=window.wp.element,o=window.wp.i18n,i=function(e){void 0===e&&(e=null);var t="";(null==e?void 0:e.children)&&(t=e.children);var r="content-helper-error-message";return(null==e?void 0:e.className)&&(r+=" "+e.className),(0,a.jsx)("div",{className:r,"data-testid":null==e?void 0:e.testId,dangerouslySetInnerHTML:{__html:t}})},l=function(e){var t;return void 0===e&&(e=null),(0,a.jsx)(i,{className:null==e?void 0:e.className,testId:"empty-credentials-message",children:null!==(t=window.wpParselyEmptyCredentialsMessage)&&void 0!==t?t:(0,o.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})},c=function(){return c=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]=1e4&&(clearInterval(s),r("Telemetry library not loaded"))}),100);else r("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,r){var n;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(r=this.prepareProperties(r),null===(n=this._tkq)||void 0===n||n.push(["recordEvent",t,r])):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,r={};return Object.keys(e).forEach((function(n){t.isProprietyValid(n)&&(r[n]=e[n])})),r},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),h=(d.trackEvent,function(e){var t=e.defaultValue,r=e.items,n=e.onChange;return(0,a.jsx)("select",{onChange:n,value:t,children:r.map((function(e){return(0,a.jsx)("option",{value:e[0],children:e[1]},e[0])}))})}),f=window.wp.data,y=function(){return y=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0?"".concat(a," ").concat(r):r)||this).hint=null,s.name=s.constructor.name,s.code=n;var i=[T.AccessToFeatureDisabled,T.ParselyApiForbidden,T.ParselyApiResponseContainsError,T.ParselyApiReturnedNoData,T.ParselyApiReturnedTooManyResults,T.PluginCredentialsNotSetMessageDetected,T.PluginSettingsApiSecretNotSet,T.PluginSettingsSiteIdNotSet,T.PostIsNotPublished,T.UnknownError,T.ParselySuggestionsApiAuthUnavailable,T.ParselySuggestionsApiNoAuthentication,T.ParselySuggestionsApiNoAuthorization,T.ParselySuggestionsApiNoData,T.ParselySuggestionsApiSchemaError];return s.retryFetch=!i.includes(s.code),Object.setPrototypeOf(s,t.prototype),s.code===T.AccessToFeatureDisabled?s.message=(0,o.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):s.code===T.ParselySuggestionsApiNoAuthorization?s.message=(0,o.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):s.code===T.ParselySuggestionsApiOpenAiError||s.code===T.ParselySuggestionsApiOpenAiUnavailable?s.message=(0,o.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):s.code===T.HttpRequestFailed&&s.message.includes("cURL error 28")?s.message=(0,o.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):s.code===T.ParselySuggestionsApiSchemaError?s.message=(0,o.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):s.code===T.ParselySuggestionsApiNoData?s.message=(0,o.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):s.code===T.ParselySuggestionsApiOpenAiSchema?s.message=(0,o.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):s.code===T.ParselySuggestionsApiAuthUnavailable&&(s.message=(0,o.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),s}return O(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[T.PluginCredentialsNotSetMessageDetected,T.PluginSettingsSiteIdNotSet,T.PluginSettingsApiSecretNotSet].includes(this.code)?l(e):(this.code===T.FetchError&&(this.hint=this.Hint((0,o.__)("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!==T.ParselyApiForbidden&&this.code!==T.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,o.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===T.HttpRequestFailed&&(this.hint=this.Hint((0,o.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,a.jsx)(i,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,o.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,f.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),C=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,r=Array.from(this.abortControllers.keys()).pop();r&&(t=this.abortControllers.get(r))&&(t.abort(),this.abortControllers.delete(r))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),r=new AbortController;return this.abortControllers.set(t,r),{abortController:r,abortId:t}},e.prototype.fetch=function(e,t){return r=this,n=void 0,s=function(){var r,n,a,s,i,l;return function(e,t){var r,n,a,s={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},o=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return o.next=i(0),o.throw=i(1),o.return=i(2),"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(i){return function(l){return function(i){if(r)throw new TypeError("Generator is already executing.");for(;o&&(o=0,i[0]&&(s=0)),s;)try{if(r=1,n&&(a=2&i[0]?n.return:i[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,i[1])).done)return a;switch(n=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,n=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((a=(a=s.trys).length>0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]=c){var u=t;(a=n/c)%1>1/i&&(u=a>10?1:2),u=parseFloat(a.toFixed(2))===parseFloat(a.toFixed(0))?0:u,s=a.toFixed(u),o=l}i=c})),s+r+o}function z(e){var t=e.metric,r=e.post,n=e.avgEngagedIcon,s=e.viewsIcon;return"views"===t?(0,a.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Number of Views","wp-parsely")}),s,$(r.views.toString())]}):"avg_engaged"===t?(0,a.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Average Time","wp-parsely")}),n,r.avgEngaged]}):(0,a.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}function X(e){var t,r=e.metric,n=e.post;return(0,a.jsx)("li",{className:"parsely-top-post",children:(0,a.jsxs)("div",{className:"parsely-top-post-content",children:[(0,a.jsx)(B,{post:n}),(0,a.jsxs)("div",{className:"parsely-top-post-data",children:[(0,a.jsx)(z,{metric:r,post:n}),(0,a.jsx)(Z,{post:n}),(0,a.jsxs)("a",{className:"parsely-top-post-icon-link",href:n.url,target:"_blank",rel:"noreferrer",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("View Post (opens in new tab)","wp-parsely")}),(0,a.jsx)(q,{})]}),0!==n.postId&&(0,a.jsxs)("a",{className:"parsely-top-post-icon-link",href:(t=n.postId,"/wp-admin/post.php?post=".concat(t,"&action=edit")),target:"_blank",rel:"noreferrer",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Edit Post (opens in new tab)","wp-parsely")}),(0,a.jsx)(G,{})]}),(0,a.jsxs)("div",{className:"parsely-top-post-metadata",children:[(0,a.jsxs)("span",{className:"parsely-top-post-date",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Date","wp-parsely")}),M(new Date(n.date))]}),(0,a.jsxs)("span",{className:"parsely-top-post-author",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Author","wp-parsely")}),n.author]})]})]})]})},n.id)}function B(e){var t=e.post;return t.thumbnailUrl?(0,a.jsxs)("div",{className:"parsely-top-post-thumbnail",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Thumbnail","wp-parsely")}),(0,a.jsx)("img",{src:t.thumbnailUrl,alt:(0,o.__)("Post thumbnail","wp-parsely")})]}):(0,a.jsx)("div",{className:"parsely-top-post-thumbnail",children:(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("Post thumbnail not available","wp-parsely")})})}function Z(e){var t=e.post;return(0,a.jsxs)("a",{className:"parsely-top-post-title",href:t.dashUrl,target:"_blank",rel:"noreferrer",children:[(0,a.jsx)("span",{className:"screen-reader-text",children:(0,o.__)("View in Parse.ly (opens in new tab)","wp-parsely")}),t.title]})}var W=function(){return W=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,t(n-1)];case 2:return r.sent(),[3,4];case 3:f(!1),v(e),r.label=4;case 4:return[2]}}))}))})),[2]}))}))};return f(!0),t(1),function(){f(!1),b([]),v(void 0)}}),[i,S]);var T=function(e,t){d.trackEvent("dash_widget_filter_changed",W({filter:e},t))},N=(0,a.jsxs)("div",{className:"parsely-top-posts-filters",children:[(0,a.jsx)(h,{defaultValue:i.Period,items:Object.values(e).map((function(e){return[e,A(e)]})),onChange:function(t){x(t.target.value,e)&&(l({Period:t.target.value}),T("period",{period:t.target.value}),E(1))}}),(0,a.jsx)(h,{defaultValue:i.Metric,items:Object.values(t).map((function(e){return[e,j(e)]})),onChange:function(e){x(e.target.value,t)&&(l({Metric:e.target.value}),T("metric",{metric:e.target.value}),E(1))}})]}),O=(0,a.jsxs)("div",{className:"parsely-top-posts-navigation",children:[(0,a.jsx)("button",{className:"parsely-top-posts-navigation-prev",disabled:S<=1,"aria-label":(0,o.__)("Previous page","wp-parsely"),onClick:function(){E(S-1),d.trackEvent("dash_widget_navigation",{navigation:"previous",to_page:S-1})},children:(0,o.__)("<< Previous","wp-parsely")}),(0,o.sprintf)(/* translators: 1: Current page */ /* translators: 1: Current page */(0,o.__)("Page %1$d","wp-parsely"),S),(0,a.jsx)("button",{className:"parsely-top-posts-navigation-next",disabled:!u&&_.length<5,"aria-label":(0,o.__)("Next page","wp-parsely"),onClick:function(){E(S+1),d.trackEvent("dash_widget_navigation",{navigation:"next",to_page:S+1})},children:(0,o.__)("Next >>","wp-parsely")})]});if(g)return(0,a.jsxs)(a.Fragment,{children:[N,g.Message(),S>1&&O]});var I=(0,a.jsx)("div",{className:"parsely-spinner-wrapper",children:(0,a.jsx)(p.Spinner,{})});return(0,a.jsxs)(a.Fragment,{children:[N,u?I:(0,a.jsx)("ol",{className:"parsely-top-posts",style:{counterReset:"item "+5*(S-1)},children:_.map((function(e){return(0,a.jsx)(X,{metric:i.Metric,post:e},e.id)}))}),(_.length>=5||S>1)&&O]})}var J=function(r){var n;try{n=JSON.parse(r)}catch(r){return{Metric:t.Views,Period:e.Days7}}return x(null==n?void 0:n.Metric,t)||(n.Metric=t.Views),x(null==n?void 0:n.Period,e)||(n.Period=e.Days7),n};window.addEventListener("load",(function(){var e=document.querySelector("#wp-parsely-dashboard-widget > .inside");if(null!==e){var t=(0,a.jsx)(S,{endpoint:"dashboard-widget",defaultSettings:J(window.wpParselyContentHelperSettings),children:(0,a.jsx)(u,{children:(0,a.jsx)(Q,{})})});s.createRoot?(0,s.createRoot)(e).render(t):(0,s.render)(t,e)}}),!1)}()}(); \ No newline at end of file diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 003a4d6c5..6858edd20 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-plugins', 'wp-primitives', 'wp-url'), 'version' => '2dba3c67213de163a67c'); + 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-plugins', 'wp-primitives', 'wp-url'), 'version' => '6e668f9bfad0f3f02bf6'); diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index cc3fa232b..57b55c601 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -1,19 +1,19 @@ -!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({},{_:function(){return ur}});var e,t,r,i,s,o,a,l,c,u,p,d=n(848),f=window.wp.components,h=window.wp.data,v=window.wp.domReady,g=n.n(v);void 0!==window.wp&&(null!==(t=null===(e=window.wp.editor)||void 0===e?void 0:e.PluginDocumentSettingPanel)&&void 0!==t||(null!==(i=null===(r=window.wp.editPost)||void 0===r?void 0:r.PluginDocumentSettingPanel)&&void 0!==i||(null===(s=window.wp.editSite)||void 0===s||s.PluginDocumentSettingPanel)),p=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 y,m,w,b=window.wp.element,_=window.wp.i18n,x=window.wp.primitives,k=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),S=window.wp.plugins,j=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}(),P=(j.trackEvent,function(){return(0,d.jsx)(f.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,d.jsx)(f.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"})})}),T=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,d.jsxs)(f.SVG,{className:i,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,d.jsx)(f.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,d.jsx)(f.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,d.jsx)(f.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,d.jsx)(f.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"})]})},L=function(){return L=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=[$.AccessToFeatureDisabled,$.ParselyApiForbidden,$.ParselyApiResponseContainsError,$.ParselyApiReturnedNoData,$.ParselyApiReturnedTooManyResults,$.PluginCredentialsNotSetMessageDetected,$.PluginSettingsApiSecretNotSet,$.PluginSettingsSiteIdNotSet,$.PostIsNotPublished,$.UnknownError,$.ParselySuggestionsApiAuthUnavailable,$.ParselySuggestionsApiNoAuthentication,$.ParselySuggestionsApiNoAuthorization,$.ParselySuggestionsApiNoData,$.ParselySuggestionsApiSchemaError];return s.retryFetch=!o.includes(s.code),Object.setPrototypeOf(s,t.prototype),s.code===$.AccessToFeatureDisabled?s.message=(0,_.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):s.code===$.ParselySuggestionsApiNoAuthorization?s.message=(0,_.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):s.code===$.ParselySuggestionsApiOpenAiError||s.code===$.ParselySuggestionsApiOpenAiUnavailable?s.message=(0,_.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):s.code===$.HttpRequestFailed&&s.message.includes("cURL error 28")?s.message=(0,_.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):s.code===$.ParselySuggestionsApiSchemaError?s.message=(0,_.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):s.code===$.ParselySuggestionsApiNoData?s.message=(0,_.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):s.code===$.ParselySuggestionsApiOpenAiSchema?s.message=(0,_.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):s.code===$.ParselySuggestionsApiAuthUnavailable&&(s.message=(0,_.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),s}return re(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[$.PluginCredentialsNotSetMessageDetected,$.PluginSettingsSiteIdNotSet,$.PluginSettingsApiSecretNotSet].includes(this.code)?K(e):(this.code===$.FetchError&&(this.hint=this.Hint((0,_.__)("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!==$.ParselyApiForbidden&&this.code!==$.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,_.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===$.HttpRequestFailed&&(this.hint=this.Hint((0,_.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,d.jsx)(W,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,_.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,h.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),se=function(e){var t=e.isDetectingEnabled,n=e.onLinkChange,r=e.onLinkRemove,i=e.onLinkAdd,s=e.debounceValue,o=void 0===s?500:s,a=(0,h.useSelect)((function(e){return{blocks:(0,e("core/block-editor").getBlocks)()}}),[]).blocks,l=(0,b.useRef)(a),c=(0,b.useRef)(t);return(0,b.useEffect)((function(){var e=(0,z.debounce)((function(){for(var t=[],s=0;s0)return r(e.innerBlocks,t[s].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[s])){var o=t[s],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==o?void 0:o.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:o,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);o.length>0&&(o.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),o);return e(t),function(){e.cancel()}}),[a,o,t,i,n,r]),null},oe=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,s=e.suffix,o=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,d.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,d.jsx)(f.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,d.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,d.jsx)(f.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,d.jsx)(f.__experimentalInputControlSuffixWrapper,{children:s}),size:null!=o?o:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,d.jsx)(f.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},ae=function(e,t,n,r){return new(n||(n=Promise))((function(i,s){function o(e){try{l(r.next(e))}catch(e){s(e)}}function a(e){try{l(r.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((r=r.apply(e,t||[])).next())}))},le=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]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])){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])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]

","\n\x3c!-- /wp:paragraph --\x3e");t&&h((0,Q.parse)(n))}),[s]),(0,d.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,d.jsx)(f.KeyboardShortcuts,{shortcuts:{left:o,right:a,up:o,down:a}}),(0,d.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=s.post_data)||void 0===t?void 0:t.title}),(0,d.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=s.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,d.jsx)($e,{topOrBottom:"top"}),(0,d.jsx)(Ze,{block:p[0],link:s,useOriginalBlock:!0}),!(null===(r=s.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,d.jsx)($e,{topOrBottom:"bottom"})]}),(0,d.jsx)(f.__experimentalDivider,{}),(0,d.jsx)(We,{link:s}),(0,d.jsxs)("div",{className:"review-controls",children:[(0,d.jsx)(f.Tooltip,{shortcut:"←",text:(0,_.__)("Previous","wp-parsely"),children:(0,d.jsx)(f.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:o,icon:He,children:(0,_.__)("Previous","wp-parsely")})}),(0,d.jsx)("div",{className:"reviews-controls-middle",children:(0,d.jsx)(f.Button,{target:"_blank",href:(null===(i=s.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+s.uid,variant:"secondary",onClick:function(){j.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:s.uid})},children:(0,_.__)("Open in the Editor","wp-parsely")})}),(0,d.jsx)(f.Tooltip,{shortcut:"→",text:(0,_.__)("Next","wp-parsely"),children:(0,d.jsxs)(f.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,_.__)("Next","wp-parsely"),(0,d.jsx)(X,{icon:ze})]})})]})]})},Ye=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,d.jsxs)(f.SVG,{xmlns:"http://www.w3.org/2000/svg",className:i,width:n,height:n,viewBox:"0 0 24 24",fill:"none",children:[(0,d.jsx)(f.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,d.jsx)(f.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,d.jsx)(f.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"})]})},Je=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,s=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,d.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,_.__)("NEW","wp-parsely"),(0,d.jsx)(Ye,{})]}),h=[];n&&n.length>0&&h.push({name:"outbound",title:(0,_.__)("Outbound","wp-parsely")}),r&&r.length>0&&h.push({name:"inbound",title:(0,_.__)("Inbound","wp-parsely")});var v="outbound";return h=h.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,_.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,_.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,d.jsxs)("div",{className:"smart-linking-review-sidebar",ref:s,children:[(0,d.jsx)(f.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,d.jsx)(f.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:h,onSelect:function(e){var t,s;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),j.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(s=null==n?void 0:n.length)&&void 0!==s?s:0})},children:function(e){return(0,d.jsxs)(d.Fragment,{children:["outbound"===e.name&&(0,d.jsx)(d.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,d.jsxs)(f.MenuItem,{ref:function(e){o.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,d.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,d.jsxs)(d.Fragment,{children:[" ",(0,_.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("div",{className:"review-sidebar-tip",children:(0,_.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var s;return(0,d.jsx)(f.MenuItem,{ref:function(e){o.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,d.jsx)("span",{className:"smart-linking-menu-item",children:null===(s=e.post_data)||void 0===s?void 0:s.title})},e.uid)})):(0,d.jsxs)(d.Fragment,{children:[" ",(0,_.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Xe=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),et=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),tt=function(e){var t,n,r,i,s=null===(t=e.link.match)||void 0===t?void 0:t.blockId,o=(0,h.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return s?{block:n(s),parents:r(s).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[s]),a=o.block,l=o.parents;return a?(0,d.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,d.jsxs)("span",{children:[(0,d.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Q.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,d.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,d.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,d.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Q.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,d.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,d.jsx)(d.Fragment,{})},nt=function(e){var t,n=e.link,r=(0,b.useState)(n.href),i=r[0],s=r[1],o=(0,b.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=o[0],l=o[1],c=(0,b.useRef)(null),u=(0,h.useDispatch)(Te).updateSmartLink;return(0,b.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,_.__)("External","wp-parsely")),De.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,b.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);s(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var s=Math.floor((t-3)/2),o=i.substring(0,s),a=i.substring(i.length-s);return"".concat(r).concat(o,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,d.jsx)(f.MenuItem,{ref:c,info:i,iconPosition:"left",icon:Ge,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},rt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,s=e.onReject,o=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,d.jsx)(Ke,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:s,onRemove:o,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,d.jsx)(d.Fragment,{children:(0,_.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,h.select)("core/block-editor").getBlock(u),v=t.applied;return p?(0,d.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,d.jsx)(f.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?o():s())}}}),(0,d.jsx)(tt,{link:t}),(0,d.jsx)("div",{className:"review-suggestion-preview",children:(0,d.jsx)(Ze,{block:p,link:t})}),(0,d.jsx)(f.__experimentalDivider,{}),(0,d.jsx)(nt,{link:t}),(0,d.jsxs)("div",{className:"review-controls",children:[(0,d.jsx)(f.Tooltip,{shortcut:"←",text:(0,_.__)("Previous","wp-parsely"),children:(0,d.jsx)(f.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:He,children:(0,_.__)("Previous","wp-parsely")})}),(0,d.jsxs)("div",{className:"reviews-controls-middle",children:[!v&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(f.Tooltip,{shortcut:"R",text:(0,_.__)("Reject","wp-parsely"),children:(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-reject",icon:Xe,onClick:s,variant:"secondary",children:(0,_.__)("Reject","wp-parsely")})}),(0,d.jsx)(f.Tooltip,{shortcut:"A",text:(0,_.__)("Accept","wp-parsely"),children:(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-accept",icon:et,onClick:i,variant:"secondary",children:(0,_.__)("Accept","wp-parsely")})})]}),v&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(f.Tooltip,{shortcut:"R",text:(0,_.__)("Remove","wp-parsely"),children:(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-reject",icon:Xe,onClick:o,variant:"secondary",children:(0,_.__)("Remove","wp-parsely")})}),(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,_.__)("Select in Editor","wp-parsely")})]})]}),(0,d.jsx)(f.Tooltip,{shortcut:"→",text:(0,_.__)("Next","wp-parsely"),children:(0,d.jsxs)(f.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,_.__)("Next","wp-parsely"),(0,d.jsx)(X,{icon:ze})]})})]})]}):(0,d.jsx)(d.Fragment,{children:(0,_.__)("No block is selected.","wp-parsely")})},it=function(e,t,n,r){return new(n||(n=Promise))((function(i,s){function o(e){try{l(r.next(e))}catch(e){s(e)}}function a(e){try{l(r.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((r=r.apply(e,t||[])).next())}))},st=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]0&&(a=o[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),te.updateBlockAttributes(n,{content:s.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},C=(0,b.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?o(!0):(ne.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){o(!1),e?(c(!1),T().then((function(){C()}))):c(!0)},O=function(){if(ue(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=v.indexOf(k),!v[t=e+1])return;S(v[t])}},I=function(){if(ue(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=v.indexOf(k),!v[t=e-1])return;S(v[t])}};return(0,b.useEffect)((function(){l?ne.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&C()}),[l,t,p,C]),(0,b.useEffect)((function(){c(n)}),[n]),(0,d.jsxs)(d.Fragment,{children:[l&&(0,d.jsx)(f.Modal,{title:(0,_.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:C,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,d.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,d.jsx)(Qe,{outboundLinks:v,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(ue(k)?(0,d.jsx)(Ke,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,d.jsx)(rt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return it(void 0,void 0,void 0,(function(){var e,t;return st(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,s=k,it(void 0,void 0,void 0,(function(){var e,t;return st(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=s.href,e.title=s.title,e.setAttribute("data-smartlink",s.uid),(t=(0,h.select)("core/block-editor").getBlock(i))?(fe(t,s,e),s.applied=!0,[4,L(s)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),j.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(C(),[2]):(e=v.indexOf(k),v[t=e+1]?S(v[t]):S(v[0]),[2])}var i,s}))}))},onReject:function(){return it(void 0,void 0,void 0,(function(){var e,t;return st(this,(function(n){switch(n.label){case 0:return e=v.indexOf(k),v[t=e+1]?S(v[t]):v[0]?S(v[0]):C(),[4,E(k.uid)];case 1:return n.sent(),j.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return it(void 0,void 0,void 0,(function(){var e,t,n,r;return st(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,h.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,N(e,k)]):[3,2]:[2];case 1:if(i.sent(),j.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return C(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,h.select)("core/block-editor").getBlock(k.match.blockId);if(e){te.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&ke(t,k.uid),j.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),C()}}}}))]})}),s&&(0,d.jsxs)(f.Modal,{title:(0,_.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,_.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,d.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,d.jsx)(f.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,_.__)("Go Back","wp-parsely")}),(0,d.jsx)(f.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,_.__)("Close","wp-parsely")})]})]})]})})),at=function(){return at=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&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ +!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({},{_:function(){return ur}});var e,t,r,i,s,o,a,l,c,u,p,d=n(848),f=window.wp.components,h=window.wp.data,v=window.wp.domReady,g=n.n(v);void 0!==window.wp&&(null!==(t=null===(e=window.wp.editor)||void 0===e?void 0:e.PluginDocumentSettingPanel)&&void 0!==t||(null!==(i=null===(r=window.wp.editPost)||void 0===r?void 0:r.PluginDocumentSettingPanel)&&void 0!==i||(null===(s=window.wp.editSite)||void 0===s||s.PluginDocumentSettingPanel)),p=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 y,m,w,b=window.wp.element,_=window.wp.i18n,x=window.wp.primitives,k=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),S=window.wp.plugins,j=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}(),P=(j.trackEvent,function(){return(0,d.jsx)(f.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,d.jsx)(f.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"})})}),T=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,d.jsxs)(f.SVG,{className:i,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,d.jsx)(f.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,d.jsx)(f.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,d.jsx)(f.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,d.jsx)(f.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"})]})},L=function(){return L=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=[$.AccessToFeatureDisabled,$.ParselyApiForbidden,$.ParselyApiResponseContainsError,$.ParselyApiReturnedNoData,$.ParselyApiReturnedTooManyResults,$.PluginCredentialsNotSetMessageDetected,$.PluginSettingsApiSecretNotSet,$.PluginSettingsSiteIdNotSet,$.PostIsNotPublished,$.UnknownError,$.ParselySuggestionsApiAuthUnavailable,$.ParselySuggestionsApiNoAuthentication,$.ParselySuggestionsApiNoAuthorization,$.ParselySuggestionsApiNoData,$.ParselySuggestionsApiSchemaError];return s.retryFetch=!o.includes(s.code),Object.setPrototypeOf(s,t.prototype),s.code===$.AccessToFeatureDisabled?s.message=(0,_.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):s.code===$.ParselySuggestionsApiNoAuthorization?s.message=(0,_.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):s.code===$.ParselySuggestionsApiOpenAiError||s.code===$.ParselySuggestionsApiOpenAiUnavailable?s.message=(0,_.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):s.code===$.HttpRequestFailed&&s.message.includes("cURL error 28")?s.message=(0,_.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):s.code===$.ParselySuggestionsApiSchemaError?s.message=(0,_.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):s.code===$.ParselySuggestionsApiNoData?s.message=(0,_.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):s.code===$.ParselySuggestionsApiOpenAiSchema?s.message=(0,_.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):s.code===$.ParselySuggestionsApiAuthUnavailable&&(s.message=(0,_.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),s}return re(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[$.PluginCredentialsNotSetMessageDetected,$.PluginSettingsSiteIdNotSet,$.PluginSettingsApiSecretNotSet].includes(this.code)?K(e):(this.code===$.FetchError&&(this.hint=this.Hint((0,_.__)("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!==$.ParselyApiForbidden&&this.code!==$.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,_.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===$.HttpRequestFailed&&(this.hint=this.Hint((0,_.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,d.jsx)(W,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,_.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,h.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),se=function(e){var t=e.isDetectingEnabled,n=e.onLinkChange,r=e.onLinkRemove,i=e.onLinkAdd,s=e.debounceValue,o=void 0===s?500:s,a=(0,h.useSelect)((function(e){return{blocks:(0,e("core/block-editor").getBlocks)()}}),[]).blocks,l=(0,b.useRef)(a),c=(0,b.useRef)(t);return(0,b.useEffect)((function(){var e=(0,z.debounce)((function(){for(var t=[],s=0;s0)return r(e.innerBlocks,t[s].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[s])){var o=t[s],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==o?void 0:o.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:o,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);o.length>0&&(o.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),o);return e(t),function(){e.cancel()}}),[a,o,t,i,n,r]),null},oe=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,s=e.suffix,o=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,d.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,d.jsx)(f.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,d.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,d.jsx)(f.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,d.jsx)(f.__experimentalInputControlSuffixWrapper,{children:s}),size:null!=o?o:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,d.jsx)(f.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},ae=function(e,t,n,r){return new(n||(n=Promise))((function(i,s){function o(e){try{l(r.next(e))}catch(e){s(e)}}function a(e){try{l(r.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((r=r.apply(e,t||[])).next())}))},le=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]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])){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])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]

","\n\x3c!-- /wp:paragraph --\x3e");t&&h((0,Q.parse)(n))}),[s]),(0,d.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,d.jsx)(f.KeyboardShortcuts,{shortcuts:{left:o,right:a,up:o,down:a}}),(0,d.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=s.post_data)||void 0===t?void 0:t.title}),(0,d.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=s.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,d.jsx)($e,{topOrBottom:"top"}),(0,d.jsx)(Ze,{block:p[0],link:s,useOriginalBlock:!0}),!(null===(r=s.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,d.jsx)($e,{topOrBottom:"bottom"})]}),(0,d.jsx)(f.__experimentalDivider,{}),(0,d.jsx)(We,{link:s}),(0,d.jsxs)("div",{className:"review-controls",children:[(0,d.jsx)(f.Tooltip,{shortcut:"←",text:(0,_.__)("Previous","wp-parsely"),children:(0,d.jsx)(f.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:o,icon:He,children:(0,_.__)("Previous","wp-parsely")})}),(0,d.jsx)("div",{className:"reviews-controls-middle",children:(0,d.jsx)(f.Button,{target:"_blank",href:(null===(i=s.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+s.uid,variant:"secondary",onClick:function(){j.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:s.uid})},children:(0,_.__)("Open in the Editor","wp-parsely")})}),(0,d.jsx)(f.Tooltip,{shortcut:"→",text:(0,_.__)("Next","wp-parsely"),children:(0,d.jsxs)(f.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,_.__)("Next","wp-parsely"),(0,d.jsx)(X,{icon:ze})]})})]})]})},Ye=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,d.jsxs)(f.SVG,{xmlns:"http://www.w3.org/2000/svg",className:i,width:n,height:n,viewBox:"0 0 24 24",fill:"none",children:[(0,d.jsx)(f.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,d.jsx)(f.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,d.jsx)(f.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"})]})},Je=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,s=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,d.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,_.__)("NEW","wp-parsely"),(0,d.jsx)(Ye,{})]}),h=[];n&&n.length>0&&h.push({name:"outbound",title:(0,_.__)("Outbound","wp-parsely")}),r&&r.length>0&&h.push({name:"inbound",title:(0,_.__)("Inbound","wp-parsely")});var v="outbound";return h=h.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,_.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,_.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,d.jsxs)("div",{className:"smart-linking-review-sidebar",ref:s,children:[(0,d.jsx)(f.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,d.jsx)(f.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:h,onSelect:function(e){var t,s;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),j.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(s=null==n?void 0:n.length)&&void 0!==s?s:0})},children:function(e){return(0,d.jsxs)(d.Fragment,{children:["outbound"===e.name&&(0,d.jsx)(d.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,d.jsxs)(f.MenuItem,{ref:function(e){o.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,d.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,d.jsxs)(d.Fragment,{children:[" ",(0,_.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("div",{className:"review-sidebar-tip",children:(0,_.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var s;return(0,d.jsx)(f.MenuItem,{ref:function(e){o.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,d.jsx)("span",{className:"smart-linking-menu-item",children:null===(s=e.post_data)||void 0===s?void 0:s.title})},e.uid)})):(0,d.jsxs)(d.Fragment,{children:[" ",(0,_.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Xe=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),et=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),tt=function(e){var t,n,r,i,s=null===(t=e.link.match)||void 0===t?void 0:t.blockId,o=(0,h.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return s?{block:n(s),parents:r(s).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[s]),a=o.block,l=o.parents;return a?(0,d.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,d.jsxs)("span",{children:[(0,d.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Q.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,d.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,d.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,d.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Q.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,d.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,d.jsx)(d.Fragment,{})},nt=function(e){var t,n=e.link,r=(0,b.useState)(n.href),i=r[0],s=r[1],o=(0,b.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=o[0],l=o[1],c=(0,b.useRef)(null),u=(0,h.useDispatch)(Te).updateSmartLink;return(0,b.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,_.__)("External","wp-parsely")),De.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,b.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);s(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var s=Math.floor((t-3)/2),o=i.substring(0,s),a=i.substring(i.length-s);return"".concat(r).concat(o,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,d.jsx)(f.MenuItem,{ref:c,info:i,iconPosition:"left",icon:Ge,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},rt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,s=e.onReject,o=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,d.jsx)(Ke,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:s,onRemove:o,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,d.jsx)(d.Fragment,{children:(0,_.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,h.select)("core/block-editor").getBlock(u),v=t.applied;return p?(0,d.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,d.jsx)(f.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?o():s())}}}),(0,d.jsx)(tt,{link:t}),(0,d.jsx)("div",{className:"review-suggestion-preview",children:(0,d.jsx)(Ze,{block:p,link:t})}),(0,d.jsx)(f.__experimentalDivider,{}),(0,d.jsx)(nt,{link:t}),(0,d.jsxs)("div",{className:"review-controls",children:[(0,d.jsx)(f.Tooltip,{shortcut:"←",text:(0,_.__)("Previous","wp-parsely"),children:(0,d.jsx)(f.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:He,children:(0,_.__)("Previous","wp-parsely")})}),(0,d.jsxs)("div",{className:"reviews-controls-middle",children:[!v&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(f.Tooltip,{shortcut:"R",text:(0,_.__)("Reject","wp-parsely"),children:(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-reject",icon:Xe,onClick:s,variant:"secondary",children:(0,_.__)("Reject","wp-parsely")})}),(0,d.jsx)(f.Tooltip,{shortcut:"A",text:(0,_.__)("Accept","wp-parsely"),children:(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-accept",icon:et,onClick:i,variant:"secondary",children:(0,_.__)("Accept","wp-parsely")})})]}),v&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(f.Tooltip,{shortcut:"R",text:(0,_.__)("Remove","wp-parsely"),children:(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-reject",icon:Xe,onClick:o,variant:"secondary",children:(0,_.__)("Remove","wp-parsely")})}),(0,d.jsx)(f.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,_.__)("Select in Editor","wp-parsely")})]})]}),(0,d.jsx)(f.Tooltip,{shortcut:"→",text:(0,_.__)("Next","wp-parsely"),children:(0,d.jsxs)(f.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,_.__)("Next","wp-parsely"),(0,d.jsx)(X,{icon:ze})]})})]})]}):(0,d.jsx)(d.Fragment,{children:(0,_.__)("No block is selected.","wp-parsely")})},it=function(e,t,n,r){return new(n||(n=Promise))((function(i,s){function o(e){try{l(r.next(e))}catch(e){s(e)}}function a(e){try{l(r.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((r=r.apply(e,t||[])).next())}))},st=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]0&&(a=o[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),te.updateBlockAttributes(n,{content:s.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},C=(0,b.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?o(!0):(ne.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){o(!1),e?(c(!1),T().then((function(){C()}))):c(!0)},O=function(){if(ue(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=v.indexOf(k),!v[t=e+1])return;S(v[t])}},I=function(){if(ue(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=v.indexOf(k),!v[t=e-1])return;S(v[t])}};return(0,b.useEffect)((function(){l?ne.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&C()}),[l,t,p,C]),(0,b.useEffect)((function(){c(n)}),[n]),(0,d.jsxs)(d.Fragment,{children:[l&&(0,d.jsx)(f.Modal,{title:(0,_.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:C,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,d.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,d.jsx)(Qe,{outboundLinks:v,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(ue(k)?(0,d.jsx)(Ke,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,d.jsx)(rt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return it(void 0,void 0,void 0,(function(){var e,t;return st(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,s=k,it(void 0,void 0,void 0,(function(){var e,t;return st(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=s.href,e.title=s.title,e.setAttribute("data-smartlink",s.uid),(t=(0,h.select)("core/block-editor").getBlock(i))?(fe(t,s,e),s.applied=!0,[4,L(s)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),j.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(C(),[2]):(e=v.indexOf(k),v[t=e+1]?S(v[t]):S(v[0]),[2])}var i,s}))}))},onReject:function(){return it(void 0,void 0,void 0,(function(){var e,t;return st(this,(function(n){switch(n.label){case 0:return e=v.indexOf(k),v[t=e+1]?S(v[t]):v[0]?S(v[0]):C(),[4,E(k.uid)];case 1:return n.sent(),j.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return it(void 0,void 0,void 0,(function(){var e,t,n,r;return st(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,h.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,N(e,k)]):[3,2]:[2];case 1:if(i.sent(),j.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return C(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,h.select)("core/block-editor").getBlock(k.match.blockId);if(e){te.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&ke(t,k.uid),j.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),C()}}}}))]})}),s&&(0,d.jsxs)(f.Modal,{title:(0,_.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,_.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,d.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,d.jsx)(f.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,_.__)("Go Back","wp-parsely")}),(0,d.jsx)(f.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,_.__)("Close","wp-parsely")})]})]})]})})),at=function(){return at=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&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ (0,_.sprintf)((0,_.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,b.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};te(e)}}),[te,a]);var he=(0,h.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,s=t.getBlocks,o=e("core/editor"),a=o.getEditedPostContent,l=o.getCurrentPostAttribute;return{allBlocks:s(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),ve=he.allBlocks,me=he.selectedBlock,xe=he.postContent,ke=he.postPermalink,Se=function(e){return lt(void 0,void 0,void 0,(function(){var t,n,r,i,s;return ct(this,(function(o){switch(o.label){case 0:t=[],o.label=1;case 1:return o.trys.push([1,4,,9]),[4,re((n=E||!me)?_e.All:_e.Selected)];case 2:return o.sent(),a=ke.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,De.getInstance().generateSmartLinks(me&&!n?(0,Q.getBlockContent)(me):xe,O,r)];case 3:return t=o.sent(),[3,9];case 4:if((s=o.sent()).code&&s.code===$.ParselyAborted)throw s.numRetries=3-e,s;return e>0&&s.retryFetch?(console.error(s),[4,ce(!0)]):[3,8];case 5:return o.sent(),[4,ue()];case 6:return o.sent(),[4,Se(e-1)];case 7:return[2,o.sent()];case 8:throw s;case 9:return[2,t]}var a}))}))},je=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},Ne=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),ne.unlockPostSaving("wp-parsely-block-overlay")};return(0,d.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,d.jsx)(se,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){ae(this,void 0,void 0,(function(){var t,n,r;return le(this,(function(i){switch(i.label){case 0:return[4,we((0,Q.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,h.dispatch)(Te).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,d.jsxs)(f.PanelRow,{className:t,children:[(0,d.jsxs)("div",{className:"smart-linking-text",children:[(0,_.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,d.jsxs)(f.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/smart-linking/",target:"_blank",variant:"link",children:[(0,_.__)("Learn more about Parse.ly AI","wp-parsely"),(0,d.jsx)(X,{icon:ee,size:18,className:"parsely-external-link-icon"})]})]}),C&&(0,d.jsx)(f.Notice,{status:"info",onRemove:function(){return Z(null)},className:"wp-parsely-content-helper-error",children:C.Message()}),w&&g>0&&(0,d.jsx)(f.Notice,{status:"success",onRemove:function(){return x(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,_.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ (0,_.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,d.jsx)(Ce,{disabled:T,selectedBlock:me,onSettingChange:function(e,t){var n;p({SmartLinking:at(at({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&oe(t)}}),(0,d.jsx)("div",{className:"smart-linking-generate",children:(0,d.jsx)(f.Button,{onClick:function(){return lt(void 0,void 0,void 0,(function(){var e,t,n,r,s,o,a,l;return ct(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,pe()];case 2:return c.sent(),[4,Z(null)];case 3:return c.sent(),x(!1),j.trackEvent("smart_linking_generate_pressed",{is_full_content:E,selected_block:null!==(o=null==me?void 0:me.name)&&void 0!==o?o:"none",context:i}),[4,je(E?"all":null==me?void 0:me.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),j.trackEvent("smart_linking_generate_timeout",{is_full_content:E,selected_block:null!==(e=null==me?void 0:me.name)&&void 0!==e?e:"none",context:i}),Pe(E?"all":null==me?void 0:me.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,Se(3)];case 6:return n=c.sent(),[4,(u=n,lt(void 0,void 0,void 0,(function(){var e;return ct(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ke.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=ge(E?ve:[me],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,s=i+r.text.length;return t>=i&&n<=s}))})),[4,W(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new ie((0,_.__)("No smart links were generated.","wp-parsely"),$.ParselySuggestionsApiNoData,"");return de(!0),[3,15];case 8:return r=c.sent(),s=new ie(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:$.UnknownError),r.code&&r.code===$.ParselyAborted&&(s.message=(0,_.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ (0,_.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,_._n)("attempt","attempts",r.numRetries,"wp-parsely"))),console.error(r),[4,Z(s)];case 9:return c.sent(),s.createErrorSnackbar(),[3,15];case 10:return[4,q(!1)];case 11:return c.sent(),[4,re(t)];case 12:return c.sent(),[4,ce(!1)];case 13:return c.sent(),[4,Pe(E?"all":null==me?void 0:me.clientId)];case 14:return c.sent(),clearTimeout(e),[7];case 15:return[2]}var u}))}))},variant:"primary",isBusy:T,disabled:T,children:M?(0,_.sprintf)(/* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ /* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ -(0,_.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,_.__)("Generating Smart Links…","wp-parsely"):(0,_.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,d.jsx)("div",{className:"smart-linking-manage",children:(0,d.jsx)(f.Button,{onClick:function(){return lt(void 0,void 0,void 0,(function(){var e,t;return ct(this,(function(n){switch(n.label){case 0:return[4,be()];case 1:return e=n.sent(),t=ye(),[4,W(t)];case 2:return n.sent(),de(!0),j.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,_.__)("Review Smart Links","wp-parsely")})})]}),L&&(0,d.jsx)(ot,{isOpen:L,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){x(!0),de(!1)}})]})},ft=function(){return ft=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)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,s){function o(e){try{l(r.next(e))}catch(e){s(e)}}function a(e){try{l(r.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");ke(t,e)}))})))},jt=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M7 11.5h10V13H7z"})}),Pt=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),Tt=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,s=void 0===i?2:i,o=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,d.jsxs)("div",{className:"performance-stat-panel",children:[(0,d.jsxs)(f.__experimentalHStack,{className:"panel-header level-"+s,children:[(0,d.jsx)(f.__experimentalHeading,{level:s,children:t}),r&&!c&&(0,d.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,d.jsx)(f.DropdownMenu,{icon:n,label:(0,_.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,d.jsx)(f.DropdownMenu,{icon:n,label:(0,_.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,d.jsx)(f.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,d.jsx)("div",{className:"panel-body",children:u?(0,d.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,d.jsx)(f.Spinner,{})}):o})]})};function Lt(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,s=r.toString(),o="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,s=i.toFixed(u),o=l}a=c})),s+n+o}var Et=function(e){var t=e.data,n=e.isLoading,r=(0,b.useState)(m.Views),i=r[0],s=r[1],o=(0,b.useState)(!1),a=o[0],l=o[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,_.__)("Social","wp-parsely");case"search":return(0,_.__)("Search","wp-parsely");case"other":return(0,_.__)("Other","wp-parsely");case"internal":return(0,_.__)("Internal","wp-parsely");case"direct":return(0,_.__)("Direct","wp-parsely")}return e},u=(0,_.sprintf)((0,_.__)("By %s","wp-parsely"),V(i)); +(0,_.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,_.__)("Generating Smart Links…","wp-parsely"):(0,_.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,d.jsx)("div",{className:"smart-linking-manage",children:(0,d.jsx)(f.Button,{onClick:function(){return lt(void 0,void 0,void 0,(function(){var e,t;return ct(this,(function(n){switch(n.label){case 0:return[4,be()];case 1:return e=n.sent(),t=ye(),[4,W(t)];case 2:return n.sent(),de(!0),j.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,_.__)("Review Smart Links","wp-parsely")})})]}),L&&(0,d.jsx)(ot,{isOpen:L,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){x(!0),de(!1)}})]})},ft=function(){return ft=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)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,s){function o(e){try{l(r.next(e))}catch(e){s(e)}}function a(e){try{l(r.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");ke(t,e)}))})))},jt=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M7 11.5h10V13H7z"})}),Pt=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),Tt=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,s=void 0===i?2:i,o=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,d.jsxs)("div",{className:"performance-stat-panel",children:[(0,d.jsxs)(f.__experimentalHStack,{className:"panel-header level-"+s,children:[(0,d.jsx)(f.__experimentalHeading,{level:s,children:t}),r&&!c&&(0,d.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,d.jsx)(f.DropdownMenu,{icon:n,label:(0,_.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,d.jsx)(f.DropdownMenu,{icon:n,label:(0,_.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,d.jsx)(f.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,d.jsx)("div",{className:"panel-body",children:u?(0,d.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,d.jsx)(f.Spinner,{})}):o})]})};function Lt(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,s=r.toString(),o="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,s=i.toFixed(u),o=l}a=c})),s+n+o}var Et=function(e){var t=e.data,n=e.isLoading,r=(0,b.useState)(m.Views),i=r[0],s=r[1],o=(0,b.useState)(!1),a=o[0],l=o[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,_.__)("Social","wp-parsely");case"search":return(0,_.__)("Search","wp-parsely");case"other":return(0,_.__)("Other","wp-parsely");case"internal":return(0,_.__)("Internal","wp-parsely");case"direct":return(0,_.__)("Direct","wp-parsely")}return e},u=(0,_.sprintf)((0,_.__)("By %s","wp-parsely"),V(i)); /* translators: %s: metric description */return(0,d.jsxs)(Tt,{title:(0,_.__)("Categories","wp-parsely"),level:3,subtitle:u,isOpen:a,onClick:function(){return l(!a)},children:[a&&(0,d.jsx)("div",{className:"panel-settings",children:(0,d.jsx)(f.SelectControl,{value:i,prefix:(0,_.__)("By:","wp-parsely"),onChange:function(e){D(e,m)&&s(e)},children:Object.values(m).map((function(e){return(0,d.jsxs)("option",{value:e,disabled:"avg_engaged"===e,children:[V(e),"avg_engaged"===e&&" "+(0,_.__)("(coming soon)","wp-parsely")]},e)}))})}),n?(0,d.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,d.jsx)(f.Spinner,{})}):(0,d.jsxs)("div",{children:[(0,d.jsx)("div",{className:"multi-percentage-bar",children:Object.entries(t.referrers.types).map((function(e){var t=e[0],n=e[1],r=(0,_.sprintf)(/* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ /* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ (0,_.__)("%1$s: %2$s%%","wp-parsely"),c(t),n.viewsPercentage);return(0,d.jsx)(f.Tooltip /* translators: %s: percentage value */,{ /* translators: %s: percentage value */ text:"".concat(c(t)," - ").concat((0,_.sprintf)((0,_.__)("%s%%","wp-parsely"),n.viewsPercentage)),delay:150,children:(0,d.jsx)("div",{"aria-label":r,className:"bar-fill "+t,style:{width:n.viewsPercentage+"%"}})},t)}))}),(0,d.jsx)("div",{className:"percentage-bar-labels",children:Object.entries(t.referrers.types).map((function(e){var t=e[0],n=e[1];return(0,d.jsxs)("div",{className:"single-label "+t,children:[(0,d.jsx)("div",{className:"label-color "+t}),(0,d.jsx)("div",{className:"label-text",children:c(t)}),(0,d.jsx)("div",{className:"label-value",children:Lt(n.views)})]},t)}))})]})]})},Nt=(0,d.jsx)(x.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,d.jsx)(x.Path,{d:"M3.99961 13C4.67043 13.3354 4.6703 13.3357 4.67017 13.3359L4.67298 13.3305C4.67621 13.3242 4.68184 13.3135 4.68988 13.2985C4.70595 13.2686 4.7316 13.2218 4.76695 13.1608C4.8377 13.0385 4.94692 12.8592 5.09541 12.6419C5.39312 12.2062 5.84436 11.624 6.45435 11.0431C7.67308 9.88241 9.49719 8.75 11.9996 8.75C14.502 8.75 16.3261 9.88241 17.5449 11.0431C18.1549 11.624 18.6061 12.2062 18.9038 12.6419C19.0523 12.8592 19.1615 13.0385 19.2323 13.1608C19.2676 13.2218 19.2933 13.2686 19.3093 13.2985C19.3174 13.3135 19.323 13.3242 19.3262 13.3305L19.3291 13.3359C19.3289 13.3357 19.3288 13.3354 19.9996 13C20.6704 12.6646 20.6703 12.6643 20.6701 12.664L20.6697 12.6632L20.6688 12.6614L20.6662 12.6563L20.6583 12.6408C20.6517 12.6282 20.6427 12.6108 20.631 12.5892C20.6078 12.5459 20.5744 12.4852 20.5306 12.4096C20.4432 12.2584 20.3141 12.0471 20.1423 11.7956C19.7994 11.2938 19.2819 10.626 18.5794 9.9569C17.1731 8.61759 14.9972 7.25 11.9996 7.25C9.00203 7.25 6.82614 8.61759 5.41987 9.9569C4.71736 10.626 4.19984 11.2938 3.85694 11.7956C3.68511 12.0471 3.55605 12.2584 3.4686 12.4096C3.42484 12.4852 3.39142 12.5459 3.36818 12.5892C3.35656 12.6108 3.34748 12.6282 3.34092 12.6408L3.33297 12.6563L3.33041 12.6614L3.32948 12.6632L3.32911 12.664C3.32894 12.6643 3.32879 12.6646 3.99961 13ZM11.9996 16C13.9326 16 15.4996 14.433 15.4996 12.5C15.4996 10.567 13.9326 9 11.9996 9C10.0666 9 8.49961 10.567 8.49961 12.5C8.49961 14.433 10.0666 16 11.9996 16Z"})}),Ct=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})}),At=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M12 4V2.2L9 4.8l3 2.5V5.5c3.6 0 6.5 2.9 6.5 6.5 0 2.9-1.9 5.3-4.5 6.2v.2l-.1-.2c-.4.1-.7.2-1.1.2l.2 1.5c.3 0 .6-.1 1-.2 3.5-.9 6-4 6-7.7 0-4.4-3.6-8-8-8zm-7.9 7l1.5.2c.1-1.2.5-2.3 1.2-3.2l-1.1-.9C4.8 8.2 4.3 9.6 4.1 11zm1.5 1.8l-1.5.2c.1.7.3 1.4.5 2 .3.7.6 1.3 1 1.8l1.2-.8c-.3-.5-.6-1-.8-1.5s-.4-1.1-.4-1.7zm1.5 5.5c1.1.9 2.4 1.4 3.8 1.6l.2-1.5c-1.1-.1-2.2-.5-3.1-1.2l-.9 1.1z"})}),Ot=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M11 13h2v-2h-2v2zm-6 0h2v-2H5v2zm12-2v2h2v-2h-2z"})}),It=function(){return It=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]1?[2,Promise.reject(new ie((0,_.sprintf)(/* translators: URL of the published post */ /* translators: URL of the published post */ -(0,_.__)("Multiple results were returned for the post %s by the Parse.ly API.","wp-parsely"),t),$.ParselyApiReturnedTooManyResults))]:[2,n[0]]}}))}))},t.prototype.fetchReferrerDataFromWpEndpoint=function(e,t,n){return Zt(this,void 0,void 0,(function(){return $t(this,(function(r){switch(r.label){case 0:return[4,this.fetch({path:(0,Oe.addQueryArgs)("/wp-parsely/v1/referrers/post/detail",qt(qt({},zt(e)),{itm_source:this.itmSource,total_views:n,url:t}))})];case 1:return[2,r.sent()]}}))}))},t}(Ie),Kt=function(){return Kt=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&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return t.sent(),[4,n(r-1)];case 2:return t.sent(),[3,4];case 3:a(e),i(!1),t.label=4;case 4:return[2]}}))}))})),[2]}))}))};return i(!0),n(1),function(){a(void 0)}}),[t]),(0,d.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,d.jsx)(Tt,{title:(0,_.__)("Performance Stats","wp-parsely"),icon:Pt,dropdownChildren:function(e){var t=e.onClose;return(0,d.jsx)(tn,{onClose:t})},children:(0,d.jsx)("div",{className:"panel-settings",children:(0,d.jsx)(f.SelectControl,{size:"__unstable-large",value:h.PerformanceStats.Period,prefix:(0,d.jsx)(f.__experimentalInputControlPrefixWrapper,{children:(0,_.__)("Period:","wp-parsely")}),onChange:function(e){D(e,y)&&(v({PerformanceStats:Kt(Kt({},h.PerformanceStats),{Period:e})}),j.trackEvent("editor_sidebar_performance_period_changed",{period:e}))},children:Object.values(y).map((function(e){return(0,d.jsx)("option",{value:e,children:F(e)},e)}))})})}),o?o.Message():(0,d.jsxs)(d.Fragment,{children:[en(h,"overview")&&(0,d.jsx)(Gt,{data:c,isLoading:r}),en(h,"categories")&&(0,d.jsx)(Et,{data:c,isLoading:r}),en(h,"referrers")&&(0,d.jsx)(Ht,{data:c,isLoading:r})]}),window.wpParselyPostUrl&&(0,d.jsx)(f.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){j.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,_.__)("View this in Parse.ly","wp-parsely")})]})},rn=function(e){var t=e.period;return(0,d.jsx)(f.Panel,{children:(0,d.jsx)(J,{children:(0,d.jsx)(nn,{period:t})})})},sn=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i=1&&(0,d.jsx)(f.__experimentalToggleGroupControlOption,{value:w.Tag,label:(0,_.__)("Tag","wp-parsely")}),r.categories.length>=1&&(0,d.jsx)(f.__experimentalToggleGroupControlOption,{value:w.Section,label:(0,_.__)("Section","wp-parsely")}),r.authors.length>=1&&(0,d.jsx)(f.__experimentalToggleGroupControlOption,{value:w.Author,label:(0,_.__)("Author","wp-parsely")})]})})},an=function(e){var t=e.filter,n=e.label,r=e.postData,i=sn(e,["filter","label","postData"]);return(0,d.jsx)("div",{className:"related-posts-filter-values",children:(0,d.jsx)(f.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return i.onFilterValueChange(e)},options:w.Tag===t.type?r.tags.map((function(e){return{value:e,label:e}})):w.Section===t.type?r.categories.map((function(e){return{value:e,label:e}})):w.Author===t.type?r.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},ln=function(e){var t=e.filter,n=e.postData,r=e.label,i=sn(e,["filter","postData","label"]),s=function(){return n.authors.length>0&&n.categories.length>0||n.authors.length>0&&n.tags.length>0||n.tags.length>0&&n.categories.length>0},o=function(){return w.Tag===t.type&&n.tags.length>1||w.Section===t.type&&n.categories.length>1||w.Author===t.type&&n.authors.length>1};return s()||o()?(0,d.jsxs)("div",{className:"related-posts-filter-settings",children:[s()&&(0,d.jsx)(on,{filter:t,label:r,onFilterTypeChange:i.onFilterTypeChange,postData:n}),o()&&(0,d.jsx)(an,{filter:t,label:s()?void 0:r,onFilterValueChange:i.onFilterValueChange,postData:n})]}):null},cn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"})}),un=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5.625 5.5h9.75c.069 0 .125.056.125.125v9.75a.125.125 0 0 1-.125.125h-9.75a.125.125 0 0 1-.125-.125v-9.75c0-.069.056-.125.125-.125ZM4 5.625C4 4.728 4.728 4 5.625 4h9.75C16.273 4 17 4.728 17 5.625v9.75c0 .898-.727 1.625-1.625 1.625h-9.75A1.625 1.625 0 0 1 4 15.375v-9.75Zm14.5 11.656v-9H20v9C20 18.8 18.77 20 17.251 20H6.25v-1.5h11.001c.69 0 1.249-.528 1.249-1.219Z"})}),pn=function(){return(0,d.jsx)(f.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,d.jsx)(f.Rect,{width:"1",height:"40",fill:"#cccccc"})})};function dn(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,d.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,d.jsx)("span",{className:"screen-reader-text",children:(0,_.__)("Number of Views","wp-parsely")}),i,Lt(n.views.toString())]}):"avg_engaged"===t?(0,d.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,d.jsx)("span",{className:"screen-reader-text",children:(0,_.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,d.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var fn,hn=function(e){var t,n,r=e.metric,i=e.post,s=e.postContent,o=(0,h.useDispatch)("core/notices").createNotice,a=s&&(t=s,n=q(i.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,d.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,d.jsx)("div",{className:"related-post-title",children:(0,d.jsxs)("a",{href:i.url,target:"_blank",rel:"noreferrer",children:[(0,d.jsx)("span",{className:"screen-reader-text",children:(0,_.__)("View on website (opens new tab)","wp-parsely")}),i.title]})}),(0,d.jsx)("div",{className:"related-post-actions",children:(0,d.jsxs)("div",{className:"related-post-info",children:[(0,d.jsxs)("div",{children:[(0,d.jsx)("div",{className:"related-post-metric",children:(0,d.jsx)(dn,{metric:r,post:i,viewsIcon:(0,d.jsx)(X,{icon:Nt}),avgEngagedIcon:(0,d.jsx)(f.Dashicon,{icon:"clock",size:24})})}),a&&(0,d.jsx)("div",{className:"related-post-linked",children:(0,d.jsx)(f.Tooltip,{text:(0,_.__)("This post is linked in the content","wp-parsely"),children:(0,d.jsx)(X,{icon:cn,size:24})})})]}),(0,d.jsx)(pn,{}),(0,d.jsxs)("div",{children:[(0,d.jsx)(f.Button,{icon:un,iconSize:24,onClick:function(){navigator.clipboard.writeText(i.rawUrl).then((function(){o("success",(0,_.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,_.__)("Copy URL to clipboard","wp-parsely")}),(0,d.jsx)(f.Button,{icon:(0,d.jsx)(T,{}),iconSize:18,href:i.dashUrl,target:"_blank",label:(0,_.__)("View in Parse.ly","wp-parsely")})]})]})})]})},vn=window.wp.coreData,gn=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)}}(),yn=function(){return yn=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]1?[2,Promise.reject(new ie((0,_.sprintf)(/* translators: URL of the published post */ /* translators: URL of the published post */ +(0,_.__)("Multiple results were returned for the post %d by the Parse.ly API.","wp-parsely"),t),$.ParselyApiReturnedTooManyResults))]:[2,n[0]]}}))}))},t.prototype.fetchReferrerDataFromWpEndpoint=function(e,t,n){return Zt(this,void 0,void 0,(function(){return $t(this,(function(r){switch(r.label){case 0:return[4,this.fetch({path:(0,Oe.addQueryArgs)("/wp-parsely/v2/stats/post/".concat(t,"/referrers"),qt(qt({},zt(e)),{itm_source:this.itmSource,total_views:n}))})];case 1:return[2,r.sent()]}}))}))},t}(Ie),Kt=function(){return Kt=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&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return t.sent(),[4,n(r-1)];case 2:return t.sent(),[3,4];case 3:a(e),i(!1),t.label=4;case 4:return[2]}}))}))})),[2]}))}))};return i(!0),n(1),function(){a(void 0)}}),[t]),(0,d.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,d.jsx)(Tt,{title:(0,_.__)("Performance Stats","wp-parsely"),icon:Pt,dropdownChildren:function(e){var t=e.onClose;return(0,d.jsx)(tn,{onClose:t})},children:(0,d.jsx)("div",{className:"panel-settings",children:(0,d.jsx)(f.SelectControl,{size:"__unstable-large",value:h.PerformanceStats.Period,prefix:(0,d.jsx)(f.__experimentalInputControlPrefixWrapper,{children:(0,_.__)("Period:","wp-parsely")}),onChange:function(e){D(e,y)&&(v({PerformanceStats:Kt(Kt({},h.PerformanceStats),{Period:e})}),j.trackEvent("editor_sidebar_performance_period_changed",{period:e}))},children:Object.values(y).map((function(e){return(0,d.jsx)("option",{value:e,children:F(e)},e)}))})})}),o?o.Message():(0,d.jsxs)(d.Fragment,{children:[en(h,"overview")&&(0,d.jsx)(Gt,{data:c,isLoading:r}),en(h,"categories")&&(0,d.jsx)(Et,{data:c,isLoading:r}),en(h,"referrers")&&(0,d.jsx)(Ht,{data:c,isLoading:r})]}),window.wpParselyPostUrl&&(0,d.jsx)(f.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){j.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,_.__)("View this in Parse.ly","wp-parsely")})]})},rn=function(e){var t=e.period;return(0,d.jsx)(f.Panel,{children:(0,d.jsx)(J,{children:(0,d.jsx)(nn,{period:t})})})},sn=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i=1&&(0,d.jsx)(f.__experimentalToggleGroupControlOption,{value:w.Tag,label:(0,_.__)("Tag","wp-parsely")}),r.categories.length>=1&&(0,d.jsx)(f.__experimentalToggleGroupControlOption,{value:w.Section,label:(0,_.__)("Section","wp-parsely")}),r.authors.length>=1&&(0,d.jsx)(f.__experimentalToggleGroupControlOption,{value:w.Author,label:(0,_.__)("Author","wp-parsely")})]})})},an=function(e){var t=e.filter,n=e.label,r=e.postData,i=sn(e,["filter","label","postData"]);return(0,d.jsx)("div",{className:"related-posts-filter-values",children:(0,d.jsx)(f.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return i.onFilterValueChange(e)},options:w.Tag===t.type?r.tags.map((function(e){return{value:e,label:e}})):w.Section===t.type?r.categories.map((function(e){return{value:e,label:e}})):w.Author===t.type?r.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},ln=function(e){var t=e.filter,n=e.postData,r=e.label,i=sn(e,["filter","postData","label"]),s=function(){return n.authors.length>0&&n.categories.length>0||n.authors.length>0&&n.tags.length>0||n.tags.length>0&&n.categories.length>0},o=function(){return w.Tag===t.type&&n.tags.length>1||w.Section===t.type&&n.categories.length>1||w.Author===t.type&&n.authors.length>1};return s()||o()?(0,d.jsxs)("div",{className:"related-posts-filter-settings",children:[s()&&(0,d.jsx)(on,{filter:t,label:r,onFilterTypeChange:i.onFilterTypeChange,postData:n}),o()&&(0,d.jsx)(an,{filter:t,label:s()?void 0:r,onFilterValueChange:i.onFilterValueChange,postData:n})]}):null},cn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"})}),un=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5.625 5.5h9.75c.069 0 .125.056.125.125v9.75a.125.125 0 0 1-.125.125h-9.75a.125.125 0 0 1-.125-.125v-9.75c0-.069.056-.125.125-.125ZM4 5.625C4 4.728 4.728 4 5.625 4h9.75C16.273 4 17 4.728 17 5.625v9.75c0 .898-.727 1.625-1.625 1.625h-9.75A1.625 1.625 0 0 1 4 15.375v-9.75Zm14.5 11.656v-9H20v9C20 18.8 18.77 20 17.251 20H6.25v-1.5h11.001c.69 0 1.249-.528 1.249-1.219Z"})}),pn=function(){return(0,d.jsx)(f.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,d.jsx)(f.Rect,{width:"1",height:"40",fill:"#cccccc"})})};function dn(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,d.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,d.jsx)("span",{className:"screen-reader-text",children:(0,_.__)("Number of Views","wp-parsely")}),i,Lt(n.views.toString())]}):"avg_engaged"===t?(0,d.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,d.jsx)("span",{className:"screen-reader-text",children:(0,_.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,d.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var fn,hn=function(e){var t,n,r=e.metric,i=e.post,s=e.postContent,o=(0,h.useDispatch)("core/notices").createNotice,a=s&&(t=s,n=q(i.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,d.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,d.jsx)("div",{className:"related-post-title",children:(0,d.jsxs)("a",{href:i.url,target:"_blank",rel:"noreferrer",children:[(0,d.jsx)("span",{className:"screen-reader-text",children:(0,_.__)("View on website (opens new tab)","wp-parsely")}),i.title]})}),(0,d.jsx)("div",{className:"related-post-actions",children:(0,d.jsxs)("div",{className:"related-post-info",children:[(0,d.jsxs)("div",{children:[(0,d.jsx)("div",{className:"related-post-metric",children:(0,d.jsx)(dn,{metric:r,post:i,viewsIcon:(0,d.jsx)(X,{icon:Nt}),avgEngagedIcon:(0,d.jsx)(f.Dashicon,{icon:"clock",size:24})})}),a&&(0,d.jsx)("div",{className:"related-post-linked",children:(0,d.jsx)(f.Tooltip,{text:(0,_.__)("This post is linked in the content","wp-parsely"),children:(0,d.jsx)(X,{icon:cn,size:24})})})]}),(0,d.jsx)(pn,{}),(0,d.jsxs)("div",{children:[(0,d.jsx)(f.Button,{icon:un,iconSize:24,onClick:function(){navigator.clipboard.writeText(i.rawUrl).then((function(){o("success",(0,_.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,_.__)("Copy URL to clipboard","wp-parsely")}),(0,d.jsx)(f.Button,{icon:(0,d.jsx)(T,{}),iconSize:18,href:i.dashUrl,target:"_blank",label:(0,_.__)("View in Parse.ly","wp-parsely")})]})]})})]})},vn=window.wp.coreData,gn=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)}}(),yn=function(){return yn=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&&f.every(Number.isInteger)?null!==(n=l("taxonomy","category",{include:f,context:"view"}))&&void 0!==n?n:void 0:null,tagRecords:o=Array.isArray(h)&&h.length>0&&h.every(Number.isInteger)?null!==(r=l("taxonomy","post_tag",{include:h,context:"view"}))&&void 0!==r?r:void 0:null,isLoading:u("getEntityRecords",["root","user",{include:[d],context:"view"}])||u("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||u("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}]),hasResolved:(c("getEntityRecords",["root","user",{include:[d],context:"view"}])||null===i)&&(c("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||null===s)&&(c("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}])||null===o)}}),[]);return(0,b.useEffect)((function(){var e=r.authorRecords,t=r.categoryRecords,i=r.tagRecords,s=r.isLoading;r.hasResolved&&!s&&n({authors:e,categories:t,tags:i,isReady:!0})}),[r]),t}(),c=l.authors,u=l.categories,p=l.tags,v=l.isReady;(0,b.useEffect)((function(){if(v){var e=function(e){return function(e){return!(!Array.isArray(e)||0===e.length)&&e.every((function(e){return"name"in e&&"id"in e&&"slug"in e&&"description"in e&&"link"in e}))}(e)?e.map((function(e){return e.name})):[]};a({authors:e(c),categories:e(u),tags:e(p)})}}),[c,u,p,v]);var g=(0,b.useState)(!0),x=g[0],k=g[1],S=(0,b.useState)(),P=S[0],T=S[1],L=(0,b.useState)(),E=L[0],N=L[1],C=(0,b.useState)([]),A=C[0],O=C[1],I=(0,b.useState)({type:t.RelatedPosts.FilterBy,value:t.RelatedPosts.FilterValue}),R=I[0],M=I[1],G=(0,b.useState)(void 0),H=G[0],U=G[1],q=(0,z.useDebounce)(U,1e3);(0,h.useSelect)((function(e){if("undefined"==typeof jest){var t=e("core/editor").getEditedPostContent;q(t())}else q("Jest test is running")}),[q]);var Z=function(e,r){n({RelatedPosts:xn(xn({},t.RelatedPosts),{FilterBy:e,FilterValue:r})})};return(0,b.useEffect)((function(){var e,t,n=function(e){return kn(void 0,void 0,void 0,(function(){return Sn(this,(function(t){return bn.getInstance().getRelatedPosts(r,i,R).then((function(e){O(e.posts),N(e.message),k(!1)})).catch((function(t){return kn(void 0,void 0,void 0,(function(){return Sn(this,(function(r){switch(r.label){case 0:return e>0&&t.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,n(e-1)];case 2:return r.sent(),[3,4];case 3:k(!1),T(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},s=w.Author===R.type,a=w.Tag===R.type,l=w.Section===R.type,c=w.Unavailable===R.type,u=0===o.authors.length,p=0===o.tags.length,d=0===o.categories.length,f=s&&!o.authors.includes(R.value),h=a&&!o.tags.includes(R.value),v=l&&!o.categories.includes(R.value);return k(!0),c||a&&p||l&&d||s&&u?Object.values(o).every((function(e){return 0===e.length}))||M((e="",t=w.Unavailable,o.tags.length>=1?(t=w.Tag,e=o.tags[0]):o.categories.length>=1?(t=w.Section,e=o.categories[0]):o.authors.length>=1&&(t=w.Author,e=o.authors[0]),{type:t,value:e})):h?M({type:w.Tag,value:o.tags[0]}):v?M({type:w.Section,value:o.categories[0]}):f?M({type:w.Author,value:o.authors[0]}):n(1),function(){k(!1),O([]),N(""),T(void 0)}}),[r,i,R,o]),0===o.authors.length&&0===o.categories.length&&0===o.tags.length&&v?(0,d.jsx)("div",{className:"wp-parsely-related-posts",children:(0,d.jsx)("div",{className:"related-posts-body",children:(0,_.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,d.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,d.jsx)("div",{className:"related-posts-description",children:(0,_.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,d.jsxs)("div",{className:"related-posts-body",children:[(0,d.jsxs)("div",{className:"related-posts-settings",children:[(0,d.jsx)(f.SelectControl,{size:"__unstable-large",onChange:function(e){var r;D(r=e,m)&&(n({RelatedPosts:xn(xn({},t.RelatedPosts),{Metric:r})}),j.trackEvent("related_posts_metric_changed",{metric:r}))},prefix:(0,d.jsx)(f.__experimentalInputControlPrefixWrapper,{children:(0,_.__)("Metric:","wp-parsely")}),value:i,children:Object.values(m).map((function(e){return(0,d.jsx)("option",{value:e,children:V(e)},e)}))}),(0,d.jsx)(f.SelectControl,{size:"__unstable-large",value:r,prefix:(0,d.jsxs)(f.__experimentalInputControlPrefixWrapper,{children:[(0,_.__)("Period:","wp-parsely")," "]}),onChange:function(e){return function(e){D(e,y)&&(n({RelatedPosts:xn(xn({},t.RelatedPosts),{Period:e})}),j.trackEvent("related_posts_period_changed",{period:e}))}(e)},children:Object.values(y).map((function(e){return(0,d.jsx)("option",{value:e,children:F(e)},e)}))})]}),(0,d.jsx)(ln,{label:(0,_.__)("Filter by","wp-parsely"),filter:R,onFilterTypeChange:function(e){if(D(e,w)){var t="",n=e;w.Tag===n&&(t=o.tags[0]),w.Section===n&&(t=o.categories[0]),w.Author===n&&(t=o.authors[0]),""!==t&&(Z(n,t),M({type:n,value:t}),j.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(Z(R.type,e),M(xn(xn({},R),{value:e})))},postData:o}),(0,d.jsxs)("div",{className:"related-posts-wrapper",children:[(0,d.jsx)("div",{children:(0,d.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:w.Tag===R.type?(0,_.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ (0,_.__)("Top related posts with the “%1$s” tag in the %2$s.","wp-parsely"),R.value,F(r,!0)):w.Section===R.type?(0,_.sprintf)(/* translators: 1: section name, 2: period */ /* translators: 1: section name, 2: period */ (0,_.__)("Top related posts in the “%1$s” section in the %2$s.","wp-parsely"),R.value,F(r,!0)):w.Author===R.type?(0,_.sprintf)(/* translators: 1: author name, 2: period */ /* translators: 1: author name, 2: period */ -(0,_.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),R.value,F(r,!0)):null!=E?E:""})}),P&&P.Message(),x&&(0,d.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,_.__)("Loading…","wp-parsely")}),!x&&!P&&0===A.length&&(0,d.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,_.__)("No related posts found.","wp-parsely")}),!x&&A.length>0&&(0,d.jsx)("div",{className:"related-posts-list",children:A.map((function(e){return(0,d.jsx)(hn,{metric:i,post:e,postContent:H},e.id)}))})]})]})]})},Pn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"m19 7-3-3-8.5 8.5-1 4 4-1L19 7Zm-7 11.5H5V20h7v-1.5Z"})}),Tn=function(){return(0,d.jsx)(f.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",children:(0,d.jsx)(f.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"})})},Ln={journalist:{label:(0,_.__)("Journalist","wp-parsely")},editorialWriter:{label:(0,_.__)("Editorial Writer","wp-parsely")},investigativeReporter:{label:(0,_.__)("Investigative Reporter","wp-parsely")},techAnalyst:{label:(0,_.__)("Tech Analyst","wp-parsely")},businessAnalyst:{label:(0,_.__)("Business Analyst","wp-parsely")},culturalCommentator:{label:(0,_.__)("Cultural Commentator","wp-parsely")},scienceCorrespondent:{label:(0,_.__)("Science Correspondent","wp-parsely")},politicalAnalyst:{label:(0,_.__)("Political Analyst","wp-parsely")},healthWellnessAdvocate:{label:(0,_.__)("Health and Wellness Advocate","wp-parsely")},environmentalJournalist:{label:(0,_.__)("Environmental Journalist","wp-parsely")},custom:{label:(0,_.__)("Custom Persona","wp-parsely"),icon:Pn}},En=Object.keys(Ln),Nn=function(e){return"custom"===e||""===e?Ln.custom.label:Cn(e)?e:Ln[e].label},Cn=function(e){return!En.includes(e)||"custom"===e},An=function(e){var t=e.value,n=e.onChange,r=(0,b.useState)(""),i=r[0],s=r[1],o=(0,z.useDebounce)(n,500);return(0,d.jsx)("div",{className:"parsely-persona-selector-custom",children:(0,d.jsx)(f.TextControl,{value:i||t,placeholder:(0,_.__)("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)}})})},On=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,_.__)("Select a persona…","wp-parsely"):n,i=e.label,s=void 0===i?(0,_.__)("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;return(0,d.jsxs)(f.Disabled,{isDisabled:c,children:[s&&(0,d.jsx)("div",{className:"wp-parsely-dropdown-label",children:s}),(0,d.jsx)(f.DropdownMenu,{label:(0,_.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("div",{className:"parsely-persona-selector-label",children:Cn(t)?Ln.custom.label:r}),(0,d.jsx)(Tn,{})]})},children:function(e){var n=e.onClose;return(0,d.jsx)(f.MenuGroup,{label:(0,_.__)("Persona","wp-parsely"),children:(0,d.jsx)(d.Fragment,{children:En.map((function(e){if(!p&&"custom"===e)return null;var r=Ln[e],i=e===t||Cn(t)&&"custom"===e;return(0,d.jsxs)(f.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,d.jsx)(X,{icon:r.icon}),r.label]},e)}))})})}}),p&&Cn(t)&&(0,d.jsx)(An,{onChange:function(e){o(""!==e?e:"custom")},value:"custom"===t?"":t})]})},In={neutral:{label:(0,_.__)("Neutral","wp-parsely")},formal:{label:(0,_.__)("Formal","wp-parsely")},humorous:{label:(0,_.__)("Humorous","wp-parsely")},confident:{label:(0,_.__)("Confident","wp-parsely")},provocative:{label:(0,_.__)("Provocative","wp-parsely")},serious:{label:(0,_.__)("Serious","wp-parsely")},inspirational:{label:(0,_.__)("Inspirational","wp-parsely")},skeptical:{label:(0,_.__)("Skeptical","wp-parsely")},conversational:{label:(0,_.__)("Conversational","wp-parsely")},analytical:{label:(0,_.__)("Analytical","wp-parsely")},custom:{label:(0,_.__)("Custom Tone","wp-parsely"),icon:Pn}},Rn=Object.keys(In),Bn=function(e){return"custom"===e||""===e?In.custom.label:Mn(e)?e:In[e].label},Mn=function(e){return!Rn.includes(e)||"custom"===e},Dn=function(e){var t=e.value,n=e.onChange,r=(0,b.useState)(""),i=r[0],s=r[1],o=(0,z.useDebounce)(n,500);return(0,d.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,d.jsx)(f.TextControl,{value:i||t,placeholder:(0,_.__)("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)}})})},Fn=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,_.__)("Select a tone","wp-parsely"):n,i=e.label,s=void 0===i?(0,_.__)("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;return(0,d.jsxs)(f.Disabled,{isDisabled:c,children:[(0,d.jsx)("div",{className:"wp-parsely-dropdown-label",children:s}),(0,d.jsx)(f.DropdownMenu,{label:(0,_.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("div",{className:"parsely-tone-selector-label",children:Mn(t)?In.custom.label:r}),(0,d.jsx)(Tn,{})]})},children:function(e){var n=e.onClose;return(0,d.jsx)(f.MenuGroup,{label:(0,_.__)("Select a tone","wp-parsely"),children:(0,d.jsx)(d.Fragment,{children:Rn.map((function(e){if(!p&&"custom"===e)return null;var r=In[e],i=e===t||Mn(t)&&"custom"===e;return(0,d.jsxs)(f.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,d.jsx)(X,{icon:r.icon}),r.label]},e)}))})})}}),p&&Mn(t)&&(0,d.jsx)(Dn,{onChange:function(e){o(""!==e?e:"custom")},value:"custom"===t?"":t})]})},Vn=(0,d.jsx)(x.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,d.jsx)(x.Path,{d:"M10.97 10.159a3.382 3.382 0 0 0-2.857.955l1.724 1.723-2.836 2.913L7 17h1.25l2.913-2.837 1.723 1.723a3.38 3.38 0 0 0 .606-.825c.33-.63.446-1.343.35-2.032L17 10.695 13.305 7l-2.334 3.159Z"})}),Gn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M18.3 11.7c-.6-.6-1.4-.9-2.3-.9H6.7l2.9-3.3-1.1-1-4.5 5L8.5 16l1-1-2.7-2.7H16c.5 0 .9.2 1.3.5 1 1 1 3.4 1 4.5v.3h1.5v-.2c0-1.5 0-4.3-1.5-5.7z"})}),Hn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 5.5A2.25 2.25 0 0 0 9.878 7h4.244A2.251 2.251 0 0 0 12 5.5ZM12 4a3.751 3.751 0 0 0-3.675 3H5v1.5h1.27l.818 8.997a2.75 2.75 0 0 0 2.739 2.501h4.347a2.75 2.75 0 0 0 2.738-2.5L17.73 8.5H19V7h-3.325A3.751 3.751 0 0 0 12 4Zm4.224 4.5H7.776l.806 8.861a1.25 1.25 0 0 0 1.245 1.137h4.347a1.25 1.25 0 0 0 1.245-1.137l.805-8.861Z"})}),zn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"m21.5 9.1-6.6-6.6-4.2 5.6c-1.2-.1-2.4.1-3.6.7-.1 0-.1.1-.2.1-.5.3-.9.6-1.2.9l3.7 3.7-5.7 5.7v1.1h1.1l5.7-5.7 3.7 3.7c.4-.4.7-.8.9-1.2.1-.1.1-.2.2-.3.6-1.1.8-2.4.6-3.6l5.6-4.1zm-7.3 3.5.1.9c.1.9 0 1.8-.4 2.6l-6-6c.8-.4 1.7-.5 2.6-.4l.9.1L15 4.9 19.1 9l-4.9 3.6z"})}),Un=function(){return Un=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])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,d.jsx)("span",{className:"parsely-write-titles-text",children:(0,b.createInterpolateElement)( +(0,_.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),R.value,F(r,!0)):null!=E?E:""})}),P&&P.Message(),x&&(0,d.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,_.__)("Loading…","wp-parsely")}),!x&&!P&&0===A.length&&(0,d.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,_.__)("No related posts found.","wp-parsely")}),!x&&A.length>0&&(0,d.jsx)("div",{className:"related-posts-list",children:A.map((function(e){return(0,d.jsx)(hn,{metric:i,post:e,postContent:H},e.id)}))})]})]})]})},Pn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"m19 7-3-3-8.5 8.5-1 4 4-1L19 7Zm-7 11.5H5V20h7v-1.5Z"})}),Tn=function(){return(0,d.jsx)(f.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",children:(0,d.jsx)(f.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"})})},Ln={journalist:{label:(0,_.__)("Journalist","wp-parsely")},editorialWriter:{label:(0,_.__)("Editorial Writer","wp-parsely")},investigativeReporter:{label:(0,_.__)("Investigative Reporter","wp-parsely")},techAnalyst:{label:(0,_.__)("Tech Analyst","wp-parsely")},businessAnalyst:{label:(0,_.__)("Business Analyst","wp-parsely")},culturalCommentator:{label:(0,_.__)("Cultural Commentator","wp-parsely")},scienceCorrespondent:{label:(0,_.__)("Science Correspondent","wp-parsely")},politicalAnalyst:{label:(0,_.__)("Political Analyst","wp-parsely")},healthWellnessAdvocate:{label:(0,_.__)("Health and Wellness Advocate","wp-parsely")},environmentalJournalist:{label:(0,_.__)("Environmental Journalist","wp-parsely")},custom:{label:(0,_.__)("Custom Persona","wp-parsely"),icon:Pn}},En=Object.keys(Ln),Nn=function(e){return"custom"===e||""===e?Ln.custom.label:Cn(e)?e:Ln[e].label},Cn=function(e){return!En.includes(e)||"custom"===e},An=function(e){var t=e.value,n=e.onChange,r=(0,b.useState)(""),i=r[0],s=r[1],o=(0,z.useDebounce)(n,500);return(0,d.jsx)("div",{className:"parsely-persona-selector-custom",children:(0,d.jsx)(f.TextControl,{value:i||t,placeholder:(0,_.__)("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)}})})},On=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,_.__)("Select a persona…","wp-parsely"):n,i=e.label,s=void 0===i?(0,_.__)("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;return(0,d.jsxs)(f.Disabled,{isDisabled:c,children:[s&&(0,d.jsx)("div",{className:"wp-parsely-dropdown-label",children:s}),(0,d.jsx)(f.DropdownMenu,{label:(0,_.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("div",{className:"parsely-persona-selector-label",children:Cn(t)?Ln.custom.label:r}),(0,d.jsx)(Tn,{})]})},children:function(e){var n=e.onClose;return(0,d.jsx)(f.MenuGroup,{label:(0,_.__)("Persona","wp-parsely"),children:(0,d.jsx)(d.Fragment,{children:En.map((function(e){if(!p&&"custom"===e)return null;var r=Ln[e],i=e===t||Cn(t)&&"custom"===e;return(0,d.jsxs)(f.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,d.jsx)(X,{icon:r.icon}),r.label]},e)}))})})}}),p&&Cn(t)&&(0,d.jsx)(An,{onChange:function(e){o(""!==e?e:"custom")},value:"custom"===t?"":t})]})},In={neutral:{label:(0,_.__)("Neutral","wp-parsely")},formal:{label:(0,_.__)("Formal","wp-parsely")},humorous:{label:(0,_.__)("Humorous","wp-parsely")},confident:{label:(0,_.__)("Confident","wp-parsely")},provocative:{label:(0,_.__)("Provocative","wp-parsely")},serious:{label:(0,_.__)("Serious","wp-parsely")},inspirational:{label:(0,_.__)("Inspirational","wp-parsely")},skeptical:{label:(0,_.__)("Skeptical","wp-parsely")},conversational:{label:(0,_.__)("Conversational","wp-parsely")},analytical:{label:(0,_.__)("Analytical","wp-parsely")},custom:{label:(0,_.__)("Custom Tone","wp-parsely"),icon:Pn}},Rn=Object.keys(In),Bn=function(e){return"custom"===e||""===e?In.custom.label:Mn(e)?e:In[e].label},Mn=function(e){return!Rn.includes(e)||"custom"===e},Dn=function(e){var t=e.value,n=e.onChange,r=(0,b.useState)(""),i=r[0],s=r[1],o=(0,z.useDebounce)(n,500);return(0,d.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,d.jsx)(f.TextControl,{value:i||t,placeholder:(0,_.__)("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)}})})},Fn=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,_.__)("Select a tone","wp-parsely"):n,i=e.label,s=void 0===i?(0,_.__)("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;return(0,d.jsxs)(f.Disabled,{isDisabled:c,children:[(0,d.jsx)("div",{className:"wp-parsely-dropdown-label",children:s}),(0,d.jsx)(f.DropdownMenu,{label:(0,_.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("div",{className:"parsely-tone-selector-label",children:Mn(t)?In.custom.label:r}),(0,d.jsx)(Tn,{})]})},children:function(e){var n=e.onClose;return(0,d.jsx)(f.MenuGroup,{label:(0,_.__)("Select a tone","wp-parsely"),children:(0,d.jsx)(d.Fragment,{children:Rn.map((function(e){if(!p&&"custom"===e)return null;var r=In[e],i=e===t||Mn(t)&&"custom"===e;return(0,d.jsxs)(f.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,d.jsx)(X,{icon:r.icon}),r.label]},e)}))})})}}),p&&Mn(t)&&(0,d.jsx)(Dn,{onChange:function(e){o(""!==e?e:"custom")},value:"custom"===t?"":t})]})},Vn=(0,d.jsx)(x.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,d.jsx)(x.Path,{d:"M10.97 10.159a3.382 3.382 0 0 0-2.857.955l1.724 1.723-2.836 2.913L7 17h1.25l2.913-2.837 1.723 1.723a3.38 3.38 0 0 0 .606-.825c.33-.63.446-1.343.35-2.032L17 10.695 13.305 7l-2.334 3.159Z"})}),Gn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"M18.3 11.7c-.6-.6-1.4-.9-2.3-.9H6.7l2.9-3.3-1.1-1-4.5 5L8.5 16l1-1-2.7-2.7H16c.5 0 .9.2 1.3.5 1 1 1 3.4 1 4.5v.3h1.5v-.2c0-1.5 0-4.3-1.5-5.7z"})}),Hn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 5.5A2.25 2.25 0 0 0 9.878 7h4.244A2.251 2.251 0 0 0 12 5.5ZM12 4a3.751 3.751 0 0 0-3.675 3H5v1.5h1.27l.818 8.997a2.75 2.75 0 0 0 2.739 2.501h4.347a2.75 2.75 0 0 0 2.738-2.5L17.73 8.5H19V7h-3.325A3.751 3.751 0 0 0 12 4Zm4.224 4.5H7.776l.806 8.861a1.25 1.25 0 0 0 1.245 1.137h4.347a1.25 1.25 0 0 0 1.245-1.137l.805-8.861Z"})}),zn=(0,d.jsx)(x.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,d.jsx)(x.Path,{d:"m21.5 9.1-6.6-6.6-4.2 5.6c-1.2-.1-2.4.1-3.6.7-.1 0-.1.1-.2.1-.5.3-.9.6-1.2.9l3.7 3.7-5.7 5.7v1.1h1.1l5.7-5.7 3.7 3.7c.4-.4.7-.8.9-1.2.1-.1.1-.2.2-.3.6-1.1.8-2.4.6-3.6l5.6-4.1zm-7.3 3.5.1.9c.1.9 0 1.8-.4 2.6l-6-6c.8-.4 1.7-.5 2.6-.4l.9.1L15 4.9 19.1 9l-4.9 3.6z"})}),Un=function(){return Un=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])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,d.jsx)("span",{className:"parsely-write-titles-text",children:(0,b.createInterpolateElement)( // translators: %1$s is the tone, %2$s is the persona. // translators: %1$s is the tone, %2$s is the persona. -(0,_.__)("We've generated a few titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,d.jsx)("strong",{children:Bn(a)}),persona:(0,d.jsx)("strong",{children:Nn(u)})})}):(0,_.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,d.jsxs)(f.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,_.__)("Learn more about Parse.ly AI","wp-parsely"),(0,d.jsx)(X,{icon:ee,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,d.jsx)(f.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return s(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,d.jsx)(Jn,{title:k,type:fn.PostTitle,isOriginal:!0}),00&&(0,d.jsx)(Qn,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,d.jsx)(er,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,d.jsx)(Xn,{isLoading:g,onPersonaChange:function(e){C("Persona",e),p(e)},onSettingChange:C,onToneChange:function(e){C("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,d.jsx)("div",{className:"title-suggestions-generate",children:(0,d.jsxs)(f.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return ir(void 0,void 0,void 0,(function(){return sr(this,(function(e){switch(e.label){case 0:return s(void 0),!1!==g?[3,2]:(j.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=fn.PostTitle,n=A,r=a,i=u,ir(void 0,void 0,void 0,(function(){var e,o,a;return sr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=nr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return o=l.sent(),[4,P(t,o)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),s(a),P(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,_.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,_.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,_.__)("Generate Titles","wp-parsely")]})})]})})},ar=function(){return ar=Object.assign||function(e){for(var t,n=1,r=arguments.length;n titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,d.jsx)("strong",{children:Bn(a)}),persona:(0,d.jsx)("strong",{children:Nn(u)})})}):(0,_.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,d.jsxs)(f.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,_.__)("Learn more about Parse.ly AI","wp-parsely"),(0,d.jsx)(X,{icon:ee,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,d.jsx)(f.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return s(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,d.jsx)(Jn,{title:k,type:fn.PostTitle,isOriginal:!0}),00&&(0,d.jsx)(Qn,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,d.jsx)(er,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,d.jsx)(Xn,{isLoading:g,onPersonaChange:function(e){C("Persona",e),p(e)},onSettingChange:C,onToneChange:function(e){C("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,d.jsx)("div",{className:"title-suggestions-generate",children:(0,d.jsxs)(f.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return ir(void 0,void 0,void 0,(function(){return sr(this,(function(e){switch(e.label){case 0:return s(void 0),!1!==g?[3,2]:(j.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=fn.PostTitle,n=A,r=a,i=u,ir(void 0,void 0,void 0,(function(){var e,o,a;return sr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=nr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return o=l.sent(),[4,P(t,o)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),s(a),P(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,_.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,_.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,_.__)("Generate Titles","wp-parsely")]})})]})})},ar=function(){return ar=Object.assign||function(e){for(var t,n=1,r=arguments.length;n array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '2a31635723a6474c1f34'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'f4a464bba52051300fa7'); diff --git a/build/content-helper/excerpt-generator.js b/build/content-helper/excerpt-generator.js index d4e3e24bd..724730f86 100644 --- a/build/content-helper/excerpt-generator.js +++ b/build/content-helper/excerpt-generator.js @@ -1,4 +1,4 @@ -!function(){"use strict";var e={20:function(e,t,r){var n=r(609),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,s=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,a={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,n)&&!l.hasOwnProperty(n)&&(a[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===a[n]&&(a[n]=t[n]);return{$$typeof:o,type:e,key:c,ref:u,props:a,_owner:s.current}}t.Fragment=a,t.jsx=c,t.jsxs=c},848:function(e,t,r){e.exports=r(20)},609:function(e){e.exports=window.React}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e,t,n,o,a,i,s,l,c,u,p,d=window.wp.data,y=window.wp.hooks,h=window.wp.plugins,f=((0,d.dispatch)("core/block-editor"),(0,d.dispatch)("core/editor"),(0,d.dispatch)("core/edit-post")),w=r(848),v=window.wp.components,g=window.wp.editor;void 0!==window.wp&&(p=null!==(t=null===(e=window.wp.editor)||void 0===e?void 0:e.PluginDocumentSettingPanel)&&void 0!==t?t:null!==(o=null===(n=window.wp.editPost)||void 0===n?void 0:n.PluginDocumentSettingPanel)&&void 0!==o?o:null===(a=window.wp.editSite)||void 0===a?void 0:a.PluginDocumentSettingPanel,null!==(s=null===(i=window.wp.editor)||void 0===i?void 0:i.PluginSidebar)&&void 0!==s||null!==(c=null===(l=window.wp.editPost)||void 0===l?void 0:l.PluginSidebar)&&void 0!==c||null===(u=window.wp.editSite)||void 0===u||u.PluginSidebar);var _,b,P=window.wp.element,m=window.wp.i18n,x=window.wp.wordcount,E=window.wp.primitives,A=(0,w.jsx)(E.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,w.jsx)(E.Path,{d:"M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"})}),S=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 r=this,n=arguments,a=function(t,r){var n;return void 0===r&&(r={}),function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(l){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=1e4&&(clearInterval(a),r("Telemetry library not loaded"))}),100);else r("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,r){var n;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(r=this.prepareProperties(r),null===(n=this._tkq)||void 0===n||n.push(["recordEvent",t,r])):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,r={};return Object.keys(e).forEach((function(n){t.isProprietyValid(n)&&(r[n]=e[n])})),r},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),k=(S.trackEvent,function(e){void 0===e&&(e=null);var t="";(null==e?void 0:e.children)&&(t=e.children);var r="content-helper-error-message";return(null==e?void 0:e.className)&&(r+=" "+e.className),(0,w.jsx)("div",{className:r,"data-testid":null==e?void 0:e.testId,dangerouslySetInnerHTML:{__html:t}})}),T=(_=function(e,t){return _=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},_(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function __(){this.constructor=e}_(e,t),e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)});!function(e){e.AccessToFeatureDisabled="ch_access_to_feature_disabled",e.CannotFormulateApiQuery="ch_cannot_formulate_api_query",e.FetchError="fetch_error",e.HttpRequestFailed="http_request_failed",e.ParselyAborted="ch_parsely_aborted",e[e.ParselyApiForbidden=403]="ParselyApiForbidden",e.ParselyApiResponseContainsError="ch_response_contains_error",e.ParselyApiReturnedNoData="ch_parsely_api_returned_no_data",e.ParselyApiReturnedTooManyResults="ch_parsely_api_returned_too_many_results",e.PluginCredentialsNotSetMessageDetected="parsely_credentials_not_set_message_detected",e.PluginSettingsApiSecretNotSet="parsely_api_secret_not_set",e.PluginSettingsSiteIdNotSet="parsely_site_id_not_set",e.PostIsNotPublished="ch_post_not_published",e.UnknownError="ch_unknown_error",e.ParselySuggestionsApiAuthUnavailable="AUTH_UNAVAILABLE",e.ParselySuggestionsApiNoAuthentication="NO_AUTHENTICATION",e.ParselySuggestionsApiNoAuthorization="NO_AUTHORIZATION",e.ParselySuggestionsApiNoData="NO_DATA",e.ParselySuggestionsApiOpenAiError="OPENAI_ERROR",e.ParselySuggestionsApiOpenAiSchema="OPENAI_SCHEMA",e.ParselySuggestionsApiOpenAiUnavailable="OPENAI_UNAVAILABLE",e.ParselySuggestionsApiSchemaError="SCHEMA_ERROR"}(b||(b={}));var N=function(e){function t(r,n,o){void 0===o&&(o=(0,m.__)("Error:","wp-parsely"));var a=this;r.startsWith(o)&&(o=""),(a=e.call(this,o.length>0?"".concat(o," ").concat(r):r)||this).hint=null,a.name=a.constructor.name,a.code=n;var i=[b.AccessToFeatureDisabled,b.ParselyApiForbidden,b.ParselyApiResponseContainsError,b.ParselyApiReturnedNoData,b.ParselyApiReturnedTooManyResults,b.PluginCredentialsNotSetMessageDetected,b.PluginSettingsApiSecretNotSet,b.PluginSettingsSiteIdNotSet,b.PostIsNotPublished,b.UnknownError,b.ParselySuggestionsApiAuthUnavailable,b.ParselySuggestionsApiNoAuthentication,b.ParselySuggestionsApiNoAuthorization,b.ParselySuggestionsApiNoData,b.ParselySuggestionsApiSchemaError];return a.retryFetch=!i.includes(a.code),Object.setPrototypeOf(a,t.prototype),a.code===b.AccessToFeatureDisabled?a.message=(0,m.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):a.code===b.ParselySuggestionsApiNoAuthorization?a.message=(0,m.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):a.code===b.ParselySuggestionsApiOpenAiError||a.code===b.ParselySuggestionsApiOpenAiUnavailable?a.message=(0,m.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):a.code===b.HttpRequestFailed&&a.message.includes("cURL error 28")?a.message=(0,m.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):a.code===b.ParselySuggestionsApiSchemaError?a.message=(0,m.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):a.code===b.ParselySuggestionsApiNoData?a.message=(0,m.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):a.code===b.ParselySuggestionsApiOpenAiSchema?a.message=(0,m.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):a.code===b.ParselySuggestionsApiAuthUnavailable&&(a.message=(0,m.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),a}return T(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[b.PluginCredentialsNotSetMessageDetected,b.PluginSettingsSiteIdNotSet,b.PluginSettingsApiSecretNotSet].includes(this.code)?function(e){var t;return void 0===e&&(e=null),(0,w.jsx)(k,{className:null==e?void 0:e.className,testId:"empty-credentials-message",children:null!==(t=window.wpParselyEmptyCredentialsMessage)&&void 0!==t?t:(0,m.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})}(e):(this.code===b.FetchError&&(this.hint=this.Hint((0,m.__)("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!==b.ParselyApiForbidden&&this.code!==b.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,m.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===b.HttpRequestFailed&&(this.hint=this.Hint((0,m.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,w.jsx)(k,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,m.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,d.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),j=function(e){var t=e.size,r=void 0===t?24:t,n=e.className,o=void 0===n?"wp-parsely-icon":n;return(0,w.jsxs)(v.SVG,{className:o,height:r,viewBox:"0 0 60 65",width:r,xmlns:"http://www.w3.org/2000/svg",children:[(0,w.jsx)(v.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,w.jsx)(v.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,w.jsx)(v.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,w.jsx)(v.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"})]})},I=window.wp.url,O=window.wp.apiFetch,C=r.n(O),R=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,r=Array.from(this.abortControllers.keys()).pop();r&&(t=this.abortControllers.get(r))&&(t.abort(),this.abortControllers.delete(r))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),r=new AbortController;return this.abortControllers.set(t,r),{abortController:r,abortId:t}},e.prototype.fetch=function(e,t){return r=this,n=void 0,a=function(){var r,n,o,a,i,s;return function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(l){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0?(0,m.sprintf)( +!function(){"use strict";var e={20:function(e,t,r){var n=r(609),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,s=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,a={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,n)&&!l.hasOwnProperty(n)&&(a[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===a[n]&&(a[n]=t[n]);return{$$typeof:o,type:e,key:c,ref:u,props:a,_owner:s.current}}t.Fragment=a,t.jsx=c,t.jsxs=c},848:function(e,t,r){e.exports=r(20)},609:function(e){e.exports=window.React}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e,t,n,o,a,i,s,l,c,u,p,d=window.wp.data,y=window.wp.hooks,h=window.wp.plugins,f=((0,d.dispatch)("core/block-editor"),(0,d.dispatch)("core/editor"),(0,d.dispatch)("core/edit-post")),w=r(848),v=window.wp.components,g=window.wp.editor;void 0!==window.wp&&(p=null!==(t=null===(e=window.wp.editor)||void 0===e?void 0:e.PluginDocumentSettingPanel)&&void 0!==t?t:null!==(o=null===(n=window.wp.editPost)||void 0===n?void 0:n.PluginDocumentSettingPanel)&&void 0!==o?o:null===(a=window.wp.editSite)||void 0===a?void 0:a.PluginDocumentSettingPanel,null!==(s=null===(i=window.wp.editor)||void 0===i?void 0:i.PluginSidebar)&&void 0!==s||null!==(c=null===(l=window.wp.editPost)||void 0===l?void 0:l.PluginSidebar)&&void 0!==c||null===(u=window.wp.editSite)||void 0===u||u.PluginSidebar);var _,b,P=window.wp.element,m=window.wp.i18n,x=window.wp.wordcount,E=window.wp.primitives,A=(0,w.jsx)(E.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,w.jsx)(E.Path,{d:"M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"})}),S=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 r=this,n=arguments,a=function(t,r){var n;return void 0===r&&(r={}),function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(l){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=1e4&&(clearInterval(a),r("Telemetry library not loaded"))}),100);else r("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,r){var n;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(r=this.prepareProperties(r),null===(n=this._tkq)||void 0===n||n.push(["recordEvent",t,r])):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,r={};return Object.keys(e).forEach((function(n){t.isProprietyValid(n)&&(r[n]=e[n])})),r},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),k=(S.trackEvent,function(e){void 0===e&&(e=null);var t="";(null==e?void 0:e.children)&&(t=e.children);var r="content-helper-error-message";return(null==e?void 0:e.className)&&(r+=" "+e.className),(0,w.jsx)("div",{className:r,"data-testid":null==e?void 0:e.testId,dangerouslySetInnerHTML:{__html:t}})}),T=(_=function(e,t){return _=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},_(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function __(){this.constructor=e}_(e,t),e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)});!function(e){e.AccessToFeatureDisabled="ch_access_to_feature_disabled",e.CannotFormulateApiQuery="ch_cannot_formulate_api_query",e.FetchError="fetch_error",e.HttpRequestFailed="http_request_failed",e.ParselyAborted="ch_parsely_aborted",e[e.ParselyApiForbidden=403]="ParselyApiForbidden",e.ParselyApiResponseContainsError="ch_response_contains_error",e.ParselyApiReturnedNoData="ch_parsely_api_returned_no_data",e.ParselyApiReturnedTooManyResults="ch_parsely_api_returned_too_many_results",e.PluginCredentialsNotSetMessageDetected="parsely_credentials_not_set_message_detected",e.PluginSettingsApiSecretNotSet="parsely_api_secret_not_set",e.PluginSettingsSiteIdNotSet="parsely_site_id_not_set",e.PostIsNotPublished="ch_post_not_published",e.UnknownError="ch_unknown_error",e.ParselySuggestionsApiAuthUnavailable="AUTH_UNAVAILABLE",e.ParselySuggestionsApiNoAuthentication="NO_AUTHENTICATION",e.ParselySuggestionsApiNoAuthorization="NO_AUTHORIZATION",e.ParselySuggestionsApiNoData="NO_DATA",e.ParselySuggestionsApiOpenAiError="OPENAI_ERROR",e.ParselySuggestionsApiOpenAiSchema="OPENAI_SCHEMA",e.ParselySuggestionsApiOpenAiUnavailable="OPENAI_UNAVAILABLE",e.ParselySuggestionsApiSchemaError="SCHEMA_ERROR"}(b||(b={}));var N=function(e){function t(r,n,o){void 0===o&&(o=(0,m.__)("Error:","wp-parsely"));var a=this;r.startsWith(o)&&(o=""),(a=e.call(this,o.length>0?"".concat(o," ").concat(r):r)||this).hint=null,a.name=a.constructor.name,a.code=n;var i=[b.AccessToFeatureDisabled,b.ParselyApiForbidden,b.ParselyApiResponseContainsError,b.ParselyApiReturnedNoData,b.ParselyApiReturnedTooManyResults,b.PluginCredentialsNotSetMessageDetected,b.PluginSettingsApiSecretNotSet,b.PluginSettingsSiteIdNotSet,b.PostIsNotPublished,b.UnknownError,b.ParselySuggestionsApiAuthUnavailable,b.ParselySuggestionsApiNoAuthentication,b.ParselySuggestionsApiNoAuthorization,b.ParselySuggestionsApiNoData,b.ParselySuggestionsApiSchemaError];return a.retryFetch=!i.includes(a.code),Object.setPrototypeOf(a,t.prototype),a.code===b.AccessToFeatureDisabled?a.message=(0,m.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):a.code===b.ParselySuggestionsApiNoAuthorization?a.message=(0,m.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):a.code===b.ParselySuggestionsApiOpenAiError||a.code===b.ParselySuggestionsApiOpenAiUnavailable?a.message=(0,m.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):a.code===b.HttpRequestFailed&&a.message.includes("cURL error 28")?a.message=(0,m.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):a.code===b.ParselySuggestionsApiSchemaError?a.message=(0,m.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):a.code===b.ParselySuggestionsApiNoData?a.message=(0,m.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):a.code===b.ParselySuggestionsApiOpenAiSchema?a.message=(0,m.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):a.code===b.ParselySuggestionsApiAuthUnavailable&&(a.message=(0,m.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),a}return T(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[b.PluginCredentialsNotSetMessageDetected,b.PluginSettingsSiteIdNotSet,b.PluginSettingsApiSecretNotSet].includes(this.code)?function(e){var t;return void 0===e&&(e=null),(0,w.jsx)(k,{className:null==e?void 0:e.className,testId:"empty-credentials-message",children:null!==(t=window.wpParselyEmptyCredentialsMessage)&&void 0!==t?t:(0,m.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})}(e):(this.code===b.FetchError&&(this.hint=this.Hint((0,m.__)("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!==b.ParselyApiForbidden&&this.code!==b.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,m.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===b.HttpRequestFailed&&(this.hint=this.Hint((0,m.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,w.jsx)(k,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,m.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,d.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),j=function(e){var t=e.size,r=void 0===t?24:t,n=e.className,o=void 0===n?"wp-parsely-icon":n;return(0,w.jsxs)(v.SVG,{className:o,height:r,viewBox:"0 0 60 65",width:r,xmlns:"http://www.w3.org/2000/svg",children:[(0,w.jsx)(v.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,w.jsx)(v.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,w.jsx)(v.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,w.jsx)(v.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"})]})},I=window.wp.url,O=window.wp.apiFetch,C=r.n(O),R=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,r=Array.from(this.abortControllers.keys()).pop();r&&(t=this.abortControllers.get(r))&&(t.abort(),this.abortControllers.delete(r))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),r=new AbortController;return this.abortControllers.set(t,r),{abortController:r,abortId:t}},e.prototype.fetch=function(e,t){return r=this,n=void 0,a=function(){var r,n,o,a,i,s;return function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(l){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0?(0,m.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. (0,m._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[h.currentExcerpt,k]),(0,P.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[h.newExcerptGeneratedCount]),(0,w.jsxs)("div",{className:"editor-post-excerpt",children:[(0,w.jsxs)("div",{style:{position:"relative"},children:[t&&(0,w.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,w.jsx)(H,{})}),(0,w.jsx)(v.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,m.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){h.isUnderReview||_({excerpt:e}),f(F(F({},h),{currentExcerpt:e})),l(!0)},onKeyUp:function(){var e;if(s)l(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),r=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";f(F(F({},h),{currentExcerpt:r}))}},value:t?"":h.isUnderReview?h.currentExcerpt:k,help:u||null})]}),(0,w.jsxs)(v.Button,{href:(0,m.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,m.__)("Learn more about manual excerpts","wp-parsely"),(0,w.jsx)(v.Icon,{icon:A,size:18,className:"parsely-external-link-icon"})]}),(0,w.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[(0,w.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,w.jsx)(j,{size:16}),(0,w.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,m.__)("Generate With Parse.ly","wp-parsely"),(0,w.jsx)("span",{className:"beta-label",children:(0,m.__)("Beta","wp-parsely")})]})]}),o&&(0,w.jsx)(v.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return a(void 0)},status:"info",children:o.Message()}),(0,w.jsx)("div",{className:"wp-parsely-excerpt-generator-controls",children:h.isUnderReview?(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(v.Button,{variant:"secondary",onClick:function(){return L(void 0,void 0,void 0,(function(){return M(this,(function(e){switch(e.label){case 0:return[4,_({excerpt:h.currentExcerpt})];case 1:return e.sent(),f(F(F({},h),{isUnderReview:!1})),S.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,m.__)("Accept","wp-parsely")}),(0,w.jsx)(v.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return L(void 0,void 0,void 0,(function(){return M(this,(function(e){return _({excerpt:h.oldExcerpt}),f(F(F({},h),{currentExcerpt:h.oldExcerpt,isUnderReview:!1})),S.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,m.__)("Discard","wp-parsely")})]}):(0,w.jsxs)(v.Button,{onClick:function(){return L(void 0,void 0,void 0,(function(){var e,t;return M(this,(function(n){switch(n.label){case 0:r(!0),a(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),S.trackEvent("excerpt_generator_pressed"),[4,D.getInstance().generateExcerpt(I,T)];case 2:return e=n.sent(),f({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:h.newExcerptGeneratedCount+1,oldExcerpt:k}),[3,5];case 3:return(t=n.sent())instanceof N?a(t):(a(new N((0,m.__)("An unknown error occurred.","wp-parsely"),b.UnknownError)),console.error(t)),[3,5];case 4:return r(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:t,disabled:t||!T,children:[t&&(0,m.__)("Generating Excerpt…","wp-parsely"),!t&&h.newExcerptGeneratedCount>0&&(0,m.__)("Regenerate Excerpt","wp-parsely"),!t&&0===h.newExcerptGeneratedCount&&(0,m.__)("Generate Excerpt","wp-parsely")]})}),(0,w.jsxs)(v.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,m.__)("Learn more about Parse.ly AI","wp-parsely"),(0,w.jsx)(v.Icon,{icon:A,size:18,className:"parsely-external-link-icon"})]})]})]})},H=function(){return(0,w.jsx)(v.Animate,{type:"loading",children:function(e){var t=e.className;return(0,w.jsx)("span",{className:t,children:(0,m.__)("Generating…","wp-parsely")})}})},q=function(){return(0,w.jsx)(g.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,w.jsx)(p,{name:"parsely-post-excerpt",title:(0,m.__)("Excerpt","wp-parsely"),children:(0,w.jsx)(G,{})})})};(0,y.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-generator",(function(e,t){var r,n,o;return"wp-parsely-block-editor-sidebar"!==t||((null===(r=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===r?void 0:r.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,y.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,h.registerPlugin)("wp-parsely-excerpt-generator",{render:q}),(null===(n=(0,d.dispatch)("core/editor"))||void 0===n?void 0:n.removeEditorPanel)?null===(o=(0,d.dispatch)("core/editor"))||void 0===o||o.removeEditorPanel("post-excerpt"):null==f||f.removeEditorPanel("post-excerpt")),e}),1e3)}()}(); \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon index c00d788c7..7f1422252 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -13,7 +13,7 @@ parameters: - vendor/php-stubs/wordpress-stubs/wordpress-stubs.php - vendor/php-stubs/wordpress-tests-stubs/wordpress-tests-stubs.php type_coverage: - return_type: 91 + return_type: 90 param_type: 79.2 property_type: 0 # We can't use property types until PHP 7.4 becomes the plugin's minimum version. print_suggestions: false diff --git a/src/Endpoints/class-analytics-post-detail-api-proxy.php b/src/Endpoints/class-analytics-post-detail-api-proxy.php deleted file mode 100644 index 787ae0e50..000000000 --- a/src/Endpoints/class-analytics-post-detail-api-proxy.php +++ /dev/null @@ -1,48 +0,0 @@ -register_endpoint( '/stats/post/detail' ); - } - - /** - * Cached "proxy" to the Parse.ly `/analytics/post/detail` API endpoint. - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - public function get_items( WP_REST_Request $request ) { - return $this->get_data( $request ); - } - - /** - * Generates the final data from the passed response. - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - return $this->generate_post_data( $response ); - } -} diff --git a/src/Endpoints/class-analytics-posts-api-proxy.php b/src/Endpoints/class-analytics-posts-api-proxy.php deleted file mode 100644 index 3ee862caf..000000000 --- a/src/Endpoints/class-analytics-posts-api-proxy.php +++ /dev/null @@ -1,48 +0,0 @@ -register_endpoint( '/stats/posts' ); - } - - /** - * Cached "proxy" to the Parse.ly `/analytics/posts` API endpoint. - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - public function get_items( WP_REST_Request $request ) { - return $this->get_data( $request ); - } - - /** - * Generates the final data from the passed response. - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - return $this->generate_post_data( $response ); - } -} diff --git a/src/Endpoints/class-base-api-proxy.php b/src/Endpoints/class-base-api-proxy.php deleted file mode 100644 index 627543128..000000000 --- a/src/Endpoints/class-base-api-proxy.php +++ /dev/null @@ -1,281 +0,0 @@ - $response The response received by the proxy. - * @return array The generated data. - */ - abstract protected function generate_data( $response ): array; - - /** - * Cached "proxy" to the Parse.ly API endpoint. - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - abstract public function get_items( WP_REST_Request $request ); - - /** - * Returns whether the endpoint is available for access by the current - * user. - * - * @since 3.14.0 Renamed from `permission_callback()`. - * - * @return bool - */ - public function is_available_to_current_user(): bool { - return $this->api->is_available_to_current_user(); - } - - /** - * Constructor. - * - * @param Parsely $parsely Instance of Parsely class. - * @param Remote_API_Interface $api API object which does the actual calls to the Parse.ly API. - */ - public function __construct( Parsely $parsely, Remote_API_Interface $api ) { - $this->parsely = $parsely; - $this->api = $api; - } - - /** - * Registers the endpoint's WP REST route. - * - * @param string $endpoint The endpoint's route (e.g. /stats/posts). - * @param array $methods The HTTP methods to use for the endpoint. - */ - protected function register_endpoint( string $endpoint, array $methods = array( WP_REST_Server::READABLE ) ): void { - if ( ! apply_filters( 'wp_parsely_enable_' . Utils::convert_endpoint_to_filter_key( $endpoint ) . '_api_proxy', true ) ) { - return; - } - - $get_items_args = array( - 'query' => array( - 'default' => array(), - 'sanitize_callback' => function ( array $query ) { - $sanitized_query = array(); - foreach ( $query as $key => $value ) { - $sanitized_query[ sanitize_key( $key ) ] = sanitize_text_field( $value ); - } - - return $sanitized_query; - }, - ), - ); - - $rest_route_args = array( - array( - 'methods' => $methods, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'is_available_to_current_user' ), - 'args' => $get_items_args, - 'show_in_index' => $this->is_available_to_current_user(), - ), - ); - - register_rest_route( 'wp-parsely/v1', $endpoint, $rest_route_args ); - } - - /** - * Cached "proxy" to the endpoint. - * - * @param WP_REST_Request $request The request object. - * @param bool $require_api_secret Specifies if the API Secret is required. - * @param string|null $param_item The param element to use to get the items. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - protected function get_data( WP_REST_Request $request, bool $require_api_secret = true, string $param_item = null ) { - // Validate Site ID and secret. - $validation = $this->validate_apikey_and_secret( $require_api_secret ); - if ( is_wp_error( $validation ) ) { - return $validation; - } - - if ( null !== $param_item ) { - $params = $request->get_param( $param_item ); - } else { - $params = $request->get_params(); - } - - if ( is_array( $params ) && isset( $params['itm_source'] ) ) { - $this->itm_source = $params['itm_source']; - } - - // A proxy with caching behavior is used here. - $response = $this->api->get_items( $params ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - return (object) array( - 'data' => $this->generate_data( $response ), // @phpstan-ignore-line. - ); - } - - /** - * Validates that the Site ID and secret are set. - * If the API secret is not required, it will not be validated. - * - * @since 3.13.0 - * - * @param bool $require_api_secret Specifies if the API Secret is required. - * @return WP_Error|bool - */ - protected function validate_apikey_and_secret( bool $require_api_secret = true ) { - if ( false === $this->parsely->site_id_is_set() ) { - return new WP_Error( - 'parsely_site_id_not_set', - __( 'A Parse.ly Site ID must be set in site options to use this endpoint', 'wp-parsely' ), - array( 'status' => 403 ) - ); - } - - if ( $require_api_secret && false === $this->parsely->api_secret_is_set() ) { - return new WP_Error( - 'parsely_api_secret_not_set', - __( 'A Parse.ly API Secret must be set in site options to use this endpoint', 'wp-parsely' ), - array( 'status' => 403 ) - ); - } - - return true; - } - - /** - * Extracts the post data from the passed object. - * - * Should only be used with endpoints that return post data. - * - * @since 3.10.0 - * - * @param stdClass $item The object to extract the data from. - * @return array The extracted data. - */ - protected function extract_post_data( stdClass $item ): array { - $data = array(); - - if ( isset( $item->author ) ) { - $data['author'] = $item->author; - } - - if ( isset( $item->metrics->views ) ) { - $data['views'] = number_format_i18n( $item->metrics->views ); - } - - if ( isset( $item->metrics->visitors ) ) { - $data['visitors'] = number_format_i18n( $item->metrics->visitors ); - } - - // The avg_engaged metric can be in different locations depending on the - // endpoint and passed sort/url parameters. - $avg_engaged = $item->metrics->avg_engaged ?? $item->avg_engaged ?? null; - if ( null !== $avg_engaged ) { - $data['avgEngaged'] = Utils::get_formatted_duration( (float) $avg_engaged ); - } - - if ( isset( $item->pub_date ) ) { - $data['date'] = wp_date( Utils::get_date_format(), strtotime( $item->pub_date ) ); - } - - if ( isset( $item->title ) ) { - $data['title'] = $item->title; - } - - if ( isset( $item->url ) ) { - $site_id = $this->parsely->get_site_id(); - // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid - $post_id = url_to_postid( $item->url ); // 0 if the post cannot be found. - - $post_url = Parsely::get_url_with_itm_source( $item->url, null ); - if ( Utils::parsely_is_https_supported() ) { - $post_url = str_replace( 'http://', 'https://', $post_url ); - } - - $data['rawUrl'] = $post_url; - $data['dashUrl'] = Parsely::get_dash_url( $site_id, $post_url ); - $data['id'] = Parsely::get_url_with_itm_source( $post_url, null ); // Unique. - $data['postId'] = $post_id; // Might not be unique. - $data['url'] = Parsely::get_url_with_itm_source( $post_url, $this->itm_source ); - - // Set thumbnail URL, falling back to the Parse.ly thumbnail if needed. - $thumbnail_url = get_the_post_thumbnail_url( $post_id, 'thumbnail' ); - if ( false !== $thumbnail_url ) { - $data['thumbnailUrl'] = $thumbnail_url; - } elseif ( isset( $item->thumb_url_medium ) ) { - $data['thumbnailUrl'] = $item->thumb_url_medium; - } - } - - return $data; - } - - /** - * Generates the post data from the passed response. - * - * Should only be used with endpoints that return post data. - * - * @since 3.10.0 - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_post_data( array $response ): array { - $data = array(); - - foreach ( $response as $item ) { - $data [] = (object) $this->extract_post_data( $item ); - } - - return $data; - } -} diff --git a/src/Endpoints/class-base-endpoint.php b/src/Endpoints/class-base-endpoint.php deleted file mode 100644 index d9e18812c..000000000 --- a/src/Endpoints/class-base-endpoint.php +++ /dev/null @@ -1,194 +0,0 @@ -parsely = $parsely; - } - - /** - * Returns the user capability allowing access to the endpoint, after having - * applied capability filters. - * - * `DEFAULT_ACCESS_CAPABILITY` is not passed here by default, to allow for - * a more explicit declaration in child classes. - * - * @since 3.14.0 - * - * @param string $capability The original capability allowing access. - * @return string The capability allowing access after applying the filters. - */ - protected function apply_capability_filters( string $capability ): string { - /** - * Filter to change the default user capability for all private endpoints. - * - * @var string - */ - $default_user_capability = apply_filters( - 'wp_parsely_user_capability_for_all_private_apis', - $capability - ); - - /** - * Filter to change the user capability for the specific endpoint. - * - * @var string - */ - $endpoint_specific_user_capability = apply_filters( - 'wp_parsely_user_capability_for_' . Utils::convert_endpoint_to_filter_key( static::ENDPOINT ) . '_api', - $default_user_capability - ); - - return $endpoint_specific_user_capability; - } - - /** - * Registers the endpoint's WP REST route. - * - * @since 3.11.0 Moved from Base_Endpoint_Remote into Base_Endpoint. - * - * @param string $endpoint The endpoint's route. - * @param string $callback The callback function to call when the endpoint is hit. - * @param array $methods The HTTP methods to allow for the endpoint. - */ - public function register_endpoint( - string $endpoint, - string $callback, - array $methods = array( 'GET' ) - ): void { - if ( ! apply_filters( 'wp_parsely_enable_' . Utils::convert_endpoint_to_filter_key( $endpoint ) . '_api_proxy', true ) ) { - return; - } - - $get_items_args = array( - 'query' => array( - 'default' => array(), - 'sanitize_callback' => function ( array $query ) { - $sanitized_query = array(); - foreach ( $query as $key => $value ) { - $sanitized_query[ sanitize_key( $key ) ] = sanitize_text_field( $value ); - } - - return $sanitized_query; - }, - ), - ); - - $rest_route_args = array( - array( - 'methods' => $methods, - 'callback' => array( $this, $callback ), - 'permission_callback' => array( $this, 'is_available_to_current_user' ), - 'args' => $get_items_args, - 'show_in_index' => static::is_available_to_current_user(), - ), - ); - - register_rest_route( 'wp-parsely/v1', $endpoint, $rest_route_args ); - } - - /** - * Registers the endpoint's WP REST route with arguments. - * - * @since 3.16.0 - * - * @param string $endpoint The endpoint's route. - * @param string $callback The callback function to call when the endpoint is hit. - * @param array $methods The HTTP methods to allow for the endpoint. - * @param array $args The arguments for the endpoint. - */ - public function register_endpoint_with_args( - string $endpoint, - string $callback, - array $methods = array( 'GET' ), - array $args = array() - ): void { - if ( ! apply_filters( 'wp_parsely_enable_' . Utils::convert_endpoint_to_filter_key( $endpoint ) . '_api_proxy', true ) ) { - return; - } - - $rest_route_args = array( - array( - 'methods' => $methods, - 'callback' => array( $this, $callback ), - 'permission_callback' => array( $this, 'is_available_to_current_user' ), - 'args' => $args, - 'show_in_index' => static::is_available_to_current_user(), - ), - ); - - register_rest_route( 'wp-parsely/v1', $endpoint, $rest_route_args ); - } -} diff --git a/src/Endpoints/class-referrers-post-detail-api-proxy.php b/src/Endpoints/class-referrers-post-detail-api-proxy.php deleted file mode 100644 index 812a9ca81..000000000 --- a/src/Endpoints/class-referrers-post-detail-api-proxy.php +++ /dev/null @@ -1,259 +0,0 @@ -register_endpoint( '/referrers/post/detail' ); - } - - /** - * Cached "proxy" to the Parse.ly `/referrers/post/detail` API endpoint. - * - * @since 3.6.0 - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - public function get_items( WP_REST_Request $request ) { - $total_views = $request->get_param( 'total_views' ) ?? '0'; - - if ( ! is_string( $total_views ) ) { - $total_views = '0'; - } - - $this->total_views = Utils::convert_to_positive_integer( $total_views ); - $request->offsetUnset( 'total_views' ); // Remove param from request. - return $this->get_data( $request ); - } - - /** - * Generates the final data from the passed response. - * - * @since 3.6.0 - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - $referrers_types = $this->generate_referrer_types_data( $response ); - $direct_views = Utils::convert_to_positive_integer( - $referrers_types->direct->views ?? '0' - ); - $referrers_top = $this->generate_referrers_data( 5, $response, $direct_views ); - - return array( - 'top' => $referrers_top, - 'types' => $referrers_types, - ); - } - - /** - * Generates the referrer types data. - * - * Referrer types are: - * - `social`: Views coming from social media. - * - `search`: Views coming from search engines. - * - `other`: Views coming from other referrers, like external websites. - * - `internal`: Views coming from linking pages of the same website. - * - * Returned object properties: - * - `views`: The number of views. - * - `viewPercentage`: The number of views as a percentage, compared to the - * total views of all referrer types. - * - * @since 3.6.0 - * - * @param array $response The response received by the proxy. - * @return stdClass The generated data. - */ - private function generate_referrer_types_data( array $response ): stdClass { - $result = new stdClass(); - $total_referrer_views = 0; // Views from all referrer types combined. - - // Set referrer type order as it is displayed in the Parse.ly dashboard. - $referrer_type_keys = array( 'social', 'search', 'other', 'internal', 'direct' ); - foreach ( $referrer_type_keys as $key ) { - $result->$key = (object) array( 'views' => 0 ); - } - - // Set views and views totals. - foreach ( $response as $referrer_data ) { - /** - * Variable. - * - * @var int - */ - $current_views = $referrer_data->metrics->referrers_views ?? 0; - $total_referrer_views += $current_views; - - /** - * Variable. - * - * @var string - */ - $current_key = $referrer_data->type ?? ''; - if ( '' !== $current_key ) { - if ( ! isset( $result->$current_key->views ) ) { - $result->$current_key = (object) array( 'views' => 0 ); - } - - $result->$current_key->views += $current_views; - } - } - - // Add direct and total views to the object. - $result->direct->views = $this->total_views - $total_referrer_views; - $result->totals = (object) array( 'views' => $this->total_views ); - - // Remove referrer types without views. - foreach ( $referrer_type_keys as $key ) { - if ( 0 === $result->$key->views ) { - unset( $result->$key ); - } - } - - // Set percentage values and format numbers. - // @phpstan-ignore-next-line. - foreach ( $result as $key => $value ) { - // Set and format percentage values. - $result->{ $key }->viewsPercentage = $this->get_i18n_percentage( - absint( $value->views ), - $this->total_views - ); - - // Format views values. - $result->{ $key }->views = number_format_i18n( $result->{ $key }->views ); - } - - return $result; - } - - /** - * Generates the top referrers data. - * - * Returned object properties: - * - `views`: The number of views. - * - `viewPercentage`: The number of views as a percentage, compared to the - * total views of all referrer types. - * - `datasetViewsPercentage: The number of views as a percentage, compared - * to the total views of the current dataset. - * - * @since 3.6.0 - * - * @param int $limit The limit of returned referrers. - * @param array $response The response received by the proxy. - * @param int $direct_views The count of direct views. - * @return stdClass The generated data. - */ - private function generate_referrers_data( - int $limit, - array $response, - int $direct_views - ): stdClass { - $temp_views = array(); - $totals = 0; - $referrer_count = count( $response ); - - // Set views and views totals. - $loop_count = $referrer_count > $limit ? $limit : $referrer_count; - for ( $i = 0; $i < $loop_count; $i++ ) { - $data = $response[ $i ]; - - /** - * Variable. - * - * @var int - */ - $referrer_views = $data->metrics->referrers_views ?? 0; - $totals += $referrer_views; - if ( isset( $data->name ) ) { - $temp_views[ $data->name ] = $referrer_views; - } - } - - // If applicable, add the direct views. - if ( isset( $referrer_views ) && $direct_views >= $referrer_views ) { - $temp_views['direct'] = $direct_views; - $totals += $direct_views; - arsort( $temp_views ); - if ( count( $temp_views ) > $limit ) { - $totals -= array_pop( $temp_views ); - } - } - - // Convert temporary array to result object and add totals. - $result = new stdClass(); - foreach ( $temp_views as $key => $value ) { - $result->$key = (object) array( 'views' => $value ); - } - $result->totals = (object) array( 'views' => $totals ); - - // Set percentages values and format numbers. - // @phpstan-ignore-next-line. - foreach ( $result as $key => $value ) { - // Percentage against all referrer views, even those not included - // in the dataset due to the $limit argument. - $result->{ $key }->viewsPercentage = $this - ->get_i18n_percentage( absint( $value->views ), $this->total_views ); - - // Percentage against the current dataset that is limited due to the - // $limit argument. - $result->{ $key }->datasetViewsPercentage = $this - ->get_i18n_percentage( absint( $value->views ), $totals ); - - // Format views values. - $result->{ $key }->views = number_format_i18n( $result->{ $key }->views ); - } - - return $result; - } - - /** - * Returns the passed number compared to the passed total, in an - * internationalized percentage format. - * - * @since 3.6.0 - * - * @param int $number The number to be calculated as a percentage. - * @param int $total The total number to compare against. - * @return string|false The internationalized percentage or false on error. - */ - private function get_i18n_percentage( int $number, int $total ) { - if ( 0 === $total ) { - return false; - } - - return number_format_i18n( $number / $total * 100, 2 ); - } -} diff --git a/src/Endpoints/class-related-api-proxy.php b/src/Endpoints/class-related-api-proxy.php deleted file mode 100644 index 983536362..000000000 --- a/src/Endpoints/class-related-api-proxy.php +++ /dev/null @@ -1,61 +0,0 @@ -register_endpoint( '/related' ); - } - - /** - * Cached "proxy" to the Parse.ly `/related` API endpoint. - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - public function get_items( WP_REST_Request $request ) { - return $this->get_data( $request, false, 'query' ); - } - - /** - * Generates the final data from the passed response. - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - $itm_source = $this->itm_source; - - return array_map( - static function ( stdClass $item ) use ( $itm_source ) { - return (object) array( - 'image_url' => $item->image_url, - 'thumb_url_medium' => $item->thumb_url_medium, - 'title' => $item->title, - 'url' => Parsely::get_url_with_itm_source( $item->url, $itm_source ), - ); - }, - $response - ); - } -} diff --git a/src/Endpoints/content-suggestions/class-suggest-brief-api-proxy.php b/src/Endpoints/content-suggestions/class-suggest-brief-api-proxy.php deleted file mode 100644 index 78bb9c327..000000000 --- a/src/Endpoints/content-suggestions/class-suggest-brief-api-proxy.php +++ /dev/null @@ -1,152 +0,0 @@ -suggest_brief_api = new Suggest_Brief_API( $parsely ); - parent::__construct( $parsely, $this->suggest_brief_api ); - } - - /** - * Registers the endpoint's WP REST route. - * - * @since 3.13.0 - */ - public function run(): void { - $this->register_endpoint( '/content-suggestions/suggest-brief', array( 'POST' ) ); - } - - /** - * Generates the final data from the passed response. - * - * @since 3.13.0 - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - // Unused function. - return $response; - } - - /** - * Cached "proxy" to the Parse.ly API endpoint. - * - * @since 3.13.0 - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - public function get_items( WP_REST_Request $request ) { - $validation = $this->validate_apikey_and_secret(); - if ( is_wp_error( $validation ) ) { - return $validation; - } - - $pch_options = $this->parsely->get_options()['content_helper']; - if ( ! Permissions::current_user_can_use_pch_feature( 'excerpt_suggestions', $pch_options ) ) { - return new WP_Error( 'ch_access_to_feature_disabled', '', array( 'status' => 403 ) ); - } - - /** - * The post content to be sent to the API. - * - * @var string|null $post_content - */ - $post_content = $request->get_param( 'content' ); - - /** - * The post title to be sent to the API. - * - * @var string|null $post_title - */ - $post_title = $request->get_param( 'title' ); - - /** - * The persona to be sent to the API. - * - * @var string|null $persona - */ - $persona = $request->get_param( 'persona' ); - - /** - * The style to be sent to the API. - * - * @var string|null $style - */ - $style = $request->get_param( 'style' ); - - if ( null === $post_content ) { - return new WP_Error( - 'parsely_content_not_set', - __( 'A post content must be set to use this endpoint', 'wp-parsely' ), - array( 'status' => 403 ) - ); - } - - if ( null === $post_title ) { - return new WP_Error( - 'parsely_title_not_set', - __( 'A post title must be set to use this endpoint', 'wp-parsely' ), - array( 'status' => 403 ) - ); - } - - if ( null === $persona ) { - $persona = 'journalist'; - } - - if ( null === $style ) { - $style = 'neutral'; - } - - $response = $this->suggest_brief_api->get_suggestion( $post_title, $post_content, $persona, $style ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - return (object) array( - 'data' => $response, - ); - } -} diff --git a/src/Endpoints/content-suggestions/class-suggest-headline-api-proxy.php b/src/Endpoints/content-suggestions/class-suggest-headline-api-proxy.php deleted file mode 100644 index 49e02a77a..000000000 --- a/src/Endpoints/content-suggestions/class-suggest-headline-api-proxy.php +++ /dev/null @@ -1,123 +0,0 @@ -suggest_headline_api = new Suggest_Headline_API( $parsely ); - parent::__construct( $parsely, $this->suggest_headline_api ); - } - - /** - * Registers the endpoint's WP REST route. - * - * @since 3.12.0 - */ - public function run(): void { - $this->register_endpoint( '/content-suggestions/suggest-headline', array( 'POST' ) ); - } - - /** - * Generates the final data from the passed response. - * - * @since 3.12.0 - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - // Unused function. - return $response; - } - - /** - * Cached "proxy" to the Parse.ly API endpoint. - * - * @since 3.12.0 - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error object on failure. - */ - public function get_items( WP_REST_Request $request ) { - $validation = $this->validate_apikey_and_secret(); - if ( is_wp_error( $validation ) ) { - return $validation; - } - - $pch_options = $this->parsely->get_options()['content_helper']; - if ( ! Permissions::current_user_can_use_pch_feature( 'title_suggestions', $pch_options ) ) { - return new WP_Error( 'ch_access_to_feature_disabled', '', array( 'status' => 403 ) ); - } - - /** - * The post content to be sent to the API. - * - * @var string|null $post_content - */ - $post_content = $request->get_param( 'content' ); - - if ( null === $post_content ) { - return new WP_Error( - 'parsely_content_not_set', - __( 'A post content must be set to use this endpoint', 'wp-parsely' ), - array( 'status' => 403 ) - ); - } - - $limit = is_numeric( $request->get_param( 'limit' ) ) ? intval( $request->get_param( 'limit' ) ) : 3; - $tone = is_string( $request->get_param( 'tone' ) ) ? $request->get_param( 'tone' ) : 'neutral'; - $persona = is_string( $request->get_param( 'persona' ) ) ? $request->get_param( 'persona' ) : 'journalist'; - - if ( 0 === $limit ) { - $limit = 3; - } - - $response = $this->suggest_headline_api->get_titles( $post_content, $limit, $persona, $tone ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - return (object) array( - 'data' => $response, - ); - } -} diff --git a/src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php b/src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php deleted file mode 100644 index c224155ed..000000000 --- a/src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php +++ /dev/null @@ -1,162 +0,0 @@ -suggest_linked_reference_api = new Suggest_Linked_Reference_API( $parsely ); - parent::__construct( $parsely, $this->suggest_linked_reference_api ); - } - - /** - * Registers the endpoint's WP REST route. - * - * @since 3.14.0 - */ - public function run(): void { - $this->register_endpoint( '/content-suggestions/suggest-linked-reference', array( 'POST' ) ); - } - - /** - * Generates the final data from the passed response. - * - * @since 3.14.0 - * - * @param array $response The response received by the proxy. - * @return array The generated data. - */ - protected function generate_data( $response ): array { - // Unused function. - return $response; - } - - /** - * Cached "proxy" to the Parse.ly API endpoint. - * - * @since 3.14.0 - * - * @param WP_REST_Request $request The request object. - * @return stdClass|WP_Error stdClass containing the data or a WP_Error - * object on failure. - */ - public function get_items( WP_REST_Request $request ) { - $validation = $this->validate_apikey_and_secret(); - if ( is_wp_error( $validation ) ) { - return $validation; - } - - $pch_options = $this->parsely->get_options()['content_helper']; - if ( ! Permissions::current_user_can_use_pch_feature( 'smart_linking', $pch_options ) ) { - return new WP_Error( 'ch_access_to_feature_disabled', '', array( 'status' => 403 ) ); - } - - /** - * The post content to be sent to the API. - * - * @var string|null $post_content - */ - $post_content = $request->get_param( 'text' ); - - /** - * The maximum amount of words of the link text. - * - * @var string|null $max_link_words - */ - $max_link_words = $request->get_param( 'max_link_words' ); - - /** - * The maximum number of links to return. - * - * @var string|null $max_links - */ - $max_links = $request->get_param( 'max_links' ); - - /** - * The URL exclusion list. - * - * @var mixed $url_exclusion_list - */ - $url_exclusion_list = $request->get_param( 'url_exclusion_list' ) ?? array(); - - if ( null === $post_content ) { - return new WP_Error( - 'parsely_content_not_set', - __( 'A post content must be set to use this endpoint', 'wp-parsely' ), - array( 'status' => 403 ) - ); - } - - if ( is_numeric( $max_link_words ) ) { - $max_link_words = (int) $max_link_words; - } else { - $max_link_words = 4; - } - - if ( is_numeric( $max_links ) ) { - $max_links = (int) $max_links; - } else { - $max_links = 10; - } - - if ( ! is_array( $url_exclusion_list ) ) { - $url_exclusion_list = array(); - } - - $response = $this->suggest_linked_reference_api->get_links( - $post_content, - $max_link_words, - $max_links, - $url_exclusion_list - ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - // Convert the smart links to an array of objects. - $smart_links = array(); - foreach ( $response as $link ) { - $smart_links[] = $link->to_array(); - } - - return (object) array( - 'data' => $smart_links, - ); - } -} diff --git a/src/Models/class-smart-link.php b/src/Models/class-smart-link.php index 009998a63..469a00bee 100644 --- a/src/Models/class-smart-link.php +++ b/src/Models/class-smart-link.php @@ -127,7 +127,9 @@ public function __construct( int $offset, int $post_id = 0 ) { - $this->set_href( $href ); + if ( '' !== $href ) { + $this->set_href( $href ); + } // Set the title to be the destination post title if the destination post ID is set. if ( 0 !== $this->destination_post_id ) { diff --git a/src/RemoteAPI/class-analytics-post-detail-api.php b/src/RemoteAPI/class-analytics-post-detail-api.php deleted file mode 100644 index 8d946f521..000000000 --- a/src/RemoteAPI/class-analytics-post-detail-api.php +++ /dev/null @@ -1,45 +0,0 @@ -apply_capability_filters( - Base_Endpoint::DEFAULT_ACCESS_CAPABILITY - ) - ); - } -} diff --git a/src/RemoteAPI/class-analytics-posts-api.php b/src/RemoteAPI/class-analytics-posts-api.php deleted file mode 100644 index 9b70421cc..000000000 --- a/src/RemoteAPI/class-analytics-posts-api.php +++ /dev/null @@ -1,107 +0,0 @@ -, - * } - * - * @phpstan-type Analytics_Post array{ - * title?: string, - * url?: string, - * link?: string, - * author?: string, - * authors?: string[], - * section?: string, - * tags?: string[], - * metrics?: Analytics_Post_Metrics, - * full_content_word_count?: int, - * image_url?: string, - * metadata?: string, - * pub_date?: string, - * thumb_url_medium?: string, - * } - * - * @phpstan-type Analytics_Post_Metrics array{ - * avg_engaged?: float, - * views?: int, - * visitors?: int, - * } - */ -class Analytics_Posts_API extends Base_Endpoint_Remote { - public const MAX_RECORDS_LIMIT = 2000; - public const ANALYTICS_API_DAYS_LIMIT = 7; - - protected const API_BASE_URL = Parsely::PUBLIC_API_BASE_URL; - protected const ENDPOINT = '/analytics/posts'; - protected const QUERY_FILTER = 'wp_parsely_analytics_posts_endpoint_args'; - - /** - * Returns whether the endpoint is available for access by the current - * user. - * - * @since 3.14.0 - * @since 3.16.0 Added the `$request` parameter. - * - * @param WP_REST_Request|null $request The request object. - * @return bool - */ - public function is_available_to_current_user( $request = null ): bool { - return current_user_can( - // phpcs:ignore WordPress.WP.Capabilities.Undetermined - $this->apply_capability_filters( - Base_Endpoint::DEFAULT_ACCESS_CAPABILITY - ) - ); - } - - /** - * Calls Parse.ly Analytics API to get posts info. - * - * Main purpose of this function is to enforce typing. - * - * @param Analytics_Post_API_Params $api_params Parameters of the API. - * @return Analytics_Post[]|WP_Error|null - */ - public function get_posts_analytics( $api_params ) { - return $this->get_items( $api_params, true ); // @phpstan-ignore-line - } - - /** - * Returns the request's options for the remote API call. - * - * @since 3.9.0 - * - * @return array The array of options. - */ - public function get_request_options(): array { - return array( - 'timeout' => 30, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout - ); - } -} diff --git a/src/RemoteAPI/class-base-endpoint-remote.php b/src/RemoteAPI/class-base-endpoint-remote.php deleted file mode 100644 index 334f38e0d..000000000 --- a/src/RemoteAPI/class-base-endpoint-remote.php +++ /dev/null @@ -1,149 +0,0 @@ - $query The query arguments to send to the remote API. - * @throws UnexpectedValueException If the endpoint constant is not defined. - * @throws UnexpectedValueException If the query filter constant is not defined. - * @return string - */ - public function get_api_url( array $query ): string { - $this->validate_required_constraints(); - - $query['apikey'] = $this->parsely->get_site_id(); - if ( $this->parsely->api_secret_is_set() ) { - $query['secret'] = $this->parsely->get_api_secret(); - } - $query = array_filter( $query ); - - // Sort by key so the query args are in alphabetical order. - ksort( $query ); - - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Hook names are defined in child classes. - $query = apply_filters( static::QUERY_FILTER, $query ); - return add_query_arg( $query, static::API_BASE_URL . static::ENDPOINT ); - } - - /** - * Gets items from the specified endpoint. - * - * @since 3.2.0 - * @since 3.7.0 Added $associative param. - * - * @param array $query The query arguments to send to the remote API. - * @param bool $associative When TRUE, returned objects will be converted into associative arrays. - * @return array|object|WP_Error - */ - public function get_items( array $query, bool $associative = false ) { - $full_api_url = $this->get_api_url( $query ); - - /** - * GET request options. - * - * @var WP_HTTP_Request_Args $options - */ - $options = $this->get_request_options(); - $response = wp_safe_remote_get( $full_api_url, $options ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - $body = wp_remote_retrieve_body( $response ); - $decoded = json_decode( $body ); - - if ( ! is_object( $decoded ) ) { - return new WP_Error( 400, __( 'Unable to decode upstream API response', 'wp-parsely' ) ); - } - - if ( ! property_exists( $decoded, 'data' ) ) { - return new WP_Error( $decoded->code ?? 400, $decoded->message ?? __( 'Unable to read data from upstream API', 'wp-parsely' ) ); - } - - if ( ! is_array( $decoded->data ) ) { - return new WP_Error( 400, __( 'Unable to parse data from upstream API', 'wp-parsely' ) ); - } - - $data = $decoded->data; - - return $associative ? Utils::convert_to_associative_array( $data ) : $data; - } - - /** - * Returns the request's options for the remote API call. - * - * @since 3.9.0 - * - * @return array The array of options. - */ - public function get_request_options(): array { - return array(); - } - - /** - * Validates that required constants are defined. - * - * @since 3.14.0 - * - * @throws UnexpectedValueException If any required constant is not defined. - */ - protected function validate_required_constraints(): void { - if ( static::ENDPOINT === '' ) { - throw new UnexpectedValueException( 'ENDPOINT constant must be defined in child class.' ); - } - if ( static::QUERY_FILTER === '' ) { - throw new UnexpectedValueException( 'QUERY_FILTER constant must be defined in child class.' ); - } - } -} diff --git a/src/RemoteAPI/class-referrers-post-detail-api.php b/src/RemoteAPI/class-referrers-post-detail-api.php deleted file mode 100644 index 45233630e..000000000 --- a/src/RemoteAPI/class-referrers-post-detail-api.php +++ /dev/null @@ -1,45 +0,0 @@ -apply_capability_filters( - Base_Endpoint::DEFAULT_ACCESS_CAPABILITY - ) - ); - } -} diff --git a/src/RemoteAPI/class-related-api.php b/src/RemoteAPI/class-related-api.php deleted file mode 100644 index ea130bf02..000000000 --- a/src/RemoteAPI/class-related-api.php +++ /dev/null @@ -1,39 +0,0 @@ -remote_api = $remote_api; - $this->cache = $cache; - } - - /** - * Implements caching for the Remote API interface. - * - * @param array $query The query arguments to send to the remote API. - * @param bool $associative Always `false`, just present to make definition compatible - * with interface. - * @return array|object|WP_Error The response from the remote API, or false if the - * response is empty. - */ - public function get_items( array $query, bool $associative = false ) { - $cache_key = 'parsely_api_' . - wp_hash( $this->remote_api->get_endpoint() ) . '_' . - wp_hash( (string) wp_json_encode( $query ) ); - - /** - * Variable. - * - * @var array|false - */ - $items = $this->cache->get( $cache_key, self::CACHE_GROUP ); - - if ( false === $items ) { - $items = $this->remote_api->get_items( $query ); - $this->cache->set( $cache_key, $items, self::CACHE_GROUP, self::OBJECT_CACHE_TTL ); - } - - return $items; - } - - /** - * Returns whether the endpoint is available for access by the current - * user. - * - * @since 3.7.0 - * @since 3.14.0 Renamed from `is_user_allowed_to_make_api_call()`. - * @since 3.16.0 Added the `$request` parameter. - * - * @param WP_REST_Request|null $request The request object. - * @return bool - */ - public function is_available_to_current_user( $request = null ): bool { - return $this->remote_api->is_available_to_current_user( $request ); - } -} diff --git a/src/RemoteAPI/class-validate-api.php b/src/RemoteAPI/class-validate-api.php deleted file mode 100644 index 2fb0674e7..000000000 --- a/src/RemoteAPI/class-validate-api.php +++ /dev/null @@ -1,124 +0,0 @@ -apply_capability_filters( - Base_Endpoint::DEFAULT_ACCESS_CAPABILITY - ) - ); - } - - /** - * Gets the URL for the Parse.ly API credentials validation endpoint. - * - * @since 3.11.0 - * - * @param array $query The query arguments to send to the remote API. - * @return string - */ - public function get_api_url( array $query ): string { - $query = array( - 'apikey' => $query['apikey'], - 'secret' => $query['secret'], - ); - - return add_query_arg( $query, static::API_BASE_URL . static::ENDPOINT ); - } - - /** - * Queries the Parse.ly API credentials validation endpoint. - * The API will return a 200 response if the credentials are valid and a 401 response if they are not. - * - * @param array $query The query arguments to send to the remote API. - * @return object|WP_Error The response from the remote API, or a WP_Error object if the response is an error. - */ - private function api_validate_credentials( array $query ) { - /** - * GET request options. - * - * @var WP_HTTP_Request_Args $options - */ - $options = $this->get_request_options(); - $response = wp_safe_remote_get( $this->get_api_url( $query ), $options ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - $body = wp_remote_retrieve_body( $response ); - $decoded = json_decode( $body ); - - if ( ! is_object( $decoded ) ) { - return new WP_Error( - 400, - __( - 'Unable to decode upstream API response', - 'wp-parsely' - ) - ); - } - - if ( ! property_exists( $decoded, 'success' ) || false === $decoded->success ) { - return new WP_Error( - $decoded->code ?? 400, - $decoded->message ?? __( 'Unable to read data from upstream API', 'wp-parsely' ) - ); - } - - return $decoded; - } - - /** - * Returns the response from the Parse.ly API credentials validation endpoint. - * - * @since 3.11.0 - * - * @param array $query The query arguments to send to the remote API. - * @param bool $associative (optional) When TRUE, returned objects will be converted into - * associative arrays. - * @return array|object|WP_Error - */ - public function get_items( array $query, bool $associative = false ) { - $api_request = $this->api_validate_credentials( $query ); - return $associative ? Utils::convert_to_associative_array( $api_request ) : $api_request; - } -} diff --git a/src/RemoteAPI/class-wordpress-cache.php b/src/RemoteAPI/class-wordpress-cache.php deleted file mode 100644 index 59c63e32b..000000000 --- a/src/RemoteAPI/class-wordpress-cache.php +++ /dev/null @@ -1,52 +0,0 @@ -apply_capability_filters( - Base_Endpoint::DEFAULT_ACCESS_CAPABILITY - ) - ); - } - - /** - * Returns the request's options for the remote API call. - * - * @since 3.12.0 - * - * @return array The array of options. - */ - public function get_request_options(): array { - $options = array( - 'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ), - 'data_format' => 'body', - 'timeout' => 60, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout - 'body' => '{}', - ); - - // Add API key to request headers. - if ( $this->parsely->api_secret_is_set() ) { - $options['headers']['X-APIKEY-SECRET'] = $this->parsely->get_api_secret(); - } - - return $options; - } - - /** - * Gets the URL for a particular Parse.ly API Content Suggestion endpoint. - * - * @since 3.14.0 - * - * @param array $query The query arguments to send to the remote API. - * @throws UnexpectedValueException If the endpoint constant is not defined. - * @throws UnexpectedValueException If the query filter constant is not defined. - * @return string - */ - public function get_api_url( array $query = array() ): string { - $this->validate_required_constraints(); - - $query['apikey'] = $this->parsely->get_site_id(); - - // Remove empty entries and sort by key so the query args are in - // alphabetical order. - $query = array_filter( $query ); - ksort( $query ); - - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Hook names are defined in child classes. - $query = apply_filters( static::QUERY_FILTER, $query ); - return add_query_arg( $query, static::API_BASE_URL . static::ENDPOINT ); - } - - /** - * Sends a POST request to the Parse.ly Content Suggestion API. - * - * This method sends a POST request to the Parse.ly Content Suggestion API and returns the - * response. The response is either a WP_Error object in case of an error, or a decoded JSON - * object in case of a successful request. - * - * @since 3.13.0 - * - * @param array $query An associative array containing the query - * parameters for the API request. - * @param array> $body An associative array containing the body - * parameters for the API request. - * @return WP_Error|object Returns a WP_Error object in case of an error, or a decoded JSON - * object in case of a successful request. - */ - protected function post_request( array $query = array(), array $body = array() ) { - $full_api_url = $this->get_api_url( $query ); - - /** - * GET request options. - * - * @var WP_HTTP_Request_Args $options - */ - $options = $this->get_request_options(); - if ( count( $body ) > 0 ) { - $body = $this->truncate_array_content( $body ); - - $options['body'] = wp_json_encode( $body ); - if ( false === $options['body'] ) { - return new WP_Error( 400, __( 'Unable to encode request body', 'wp-parsely' ) ); - } - } - - $response = wp_safe_remote_post( $full_api_url, $options ); - if ( is_wp_error( $response ) ) { - return $response; - } - - // Handle any errors returned by the API. - if ( 200 !== $response['response']['code'] ) { - $error = json_decode( wp_remote_retrieve_body( $response ), true ); - - if ( ! is_array( $error ) ) { - return new WP_Error( - 400, - __( 'Unable to decode upstream API error', 'wp-parsely' ) - ); - } - - return new WP_Error( $error['error'], $error['detail'] ); - } - - $body = wp_remote_retrieve_body( $response ); - $decoded = json_decode( $body ); - - if ( ! is_object( $decoded ) ) { - return new WP_Error( 400, __( 'Unable to decode upstream API response', 'wp-parsely' ) ); - } - - return $decoded; - } - - /** - * Truncates the content of an array to a maximum length. - * - * @since 3.14.1 - * - * @param string|array|mixed $content The content to truncate. - * @return string|array|mixed The truncated content. - */ - public function truncate_array_content( $content ) { - if ( is_array( $content ) ) { - // If the content is an array, iterate over its elements. - foreach ( $content as $key => $value ) { - // Recursively process/truncate each element of the array. - $content[ $key ] = $this->truncate_array_content( $value ); - } - return $content; - } elseif ( is_string( $content ) ) { - // If the content is a string, truncate it. - if ( static::TRUNCATE_CONTENT ) { - // Check if the string length exceeds the maximum and truncate if necessary. - if ( mb_strlen( $content ) > self::TRUNCATE_CONTENT_LENGTH ) { - return mb_substr( $content, 0, self::TRUNCATE_CONTENT_LENGTH ); - } - } - return $content; - } - return $content; - } -} diff --git a/src/RemoteAPI/content-suggestions/class-suggest-brief-api.php b/src/RemoteAPI/content-suggestions/class-suggest-brief-api.php deleted file mode 100644 index 7a9ffa7fe..000000000 --- a/src/RemoteAPI/content-suggestions/class-suggest-brief-api.php +++ /dev/null @@ -1,73 +0,0 @@ - array( - 'persona' => $persona, - 'style' => $style, - ), - 'title' => $title, - 'text' => wp_strip_all_tags( $content ), - ); - - $decoded = $this->post_request( array(), $body ); - - if ( is_wp_error( $decoded ) ) { - return $decoded; - } - - if ( ! property_exists( $decoded, 'result' ) || - ! is_string( $decoded->result[0] ) ) { - return new WP_Error( - 400, - __( 'Unable to parse meta description from upstream API', 'wp-parsely' ) - ); - } - - return $decoded->result[0]; - } -} diff --git a/src/RemoteAPI/content-suggestions/class-suggest-headline-api.php b/src/RemoteAPI/content-suggestions/class-suggest-headline-api.php deleted file mode 100644 index 346697663..000000000 --- a/src/RemoteAPI/content-suggestions/class-suggest-headline-api.php +++ /dev/null @@ -1,69 +0,0 @@ -|WP_Error The response from the remote API, or a WP_Error - * object if the response is an error. - */ - public function get_titles( - string $content, - int $limit, - string $persona = 'journalist', - string $tone = 'neutral' - ) { - $body = array( - 'output_config' => array( - 'persona' => $persona, - 'style' => $tone, - 'max_items' => $limit, - ), - 'text' => wp_strip_all_tags( $content ), - ); - - $decoded = $this->post_request( array(), $body ); - - if ( is_wp_error( $decoded ) ) { - return $decoded; - } - - if ( ! property_exists( $decoded, 'result' ) || ! is_array( $decoded->result ) ) { - return new WP_Error( - 400, - __( 'Unable to parse titles from upstream API', 'wp-parsely' ) - ); - } - - return $decoded->result; - } -} diff --git a/src/RemoteAPI/content-suggestions/class-suggest-linked-reference-api.php b/src/RemoteAPI/content-suggestions/class-suggest-linked-reference-api.php deleted file mode 100644 index 073d401e2..000000000 --- a/src/RemoteAPI/content-suggestions/class-suggest-linked-reference-api.php +++ /dev/null @@ -1,88 +0,0 @@ - array( - 'max_link_words' => $max_link_words, - 'max_items' => $max_links, - ), - 'text' => wp_strip_all_tags( $content ), - ); - - if ( count( $url_exclusion_list ) > 0 ) { - $body['url_exclusion_list'] = $url_exclusion_list; - } - - $decoded = $this->post_request( array(), $body ); - - if ( is_wp_error( $decoded ) ) { - return $decoded; - } - - if ( ! property_exists( $decoded, 'result' ) || - ! is_array( $decoded->result ) ) { - return new WP_Error( - 400, - __( 'Unable to parse suggested links from upstream API', 'wp-parsely' ) - ); - } - - // Convert the links to Smart_Link objects. - $links = array(); - foreach ( $decoded->result as $link ) { - $link = apply_filters( 'wp_parsely_suggest_linked_reference_link', $link ); - $link_obj = new Smart_Link( - esc_url( $link->canonical_url ), - esc_attr( $link->title ), - wp_kses_post( $link->text ), - $link->offset - ); - $links[] = $link_obj; - } - - return $links; - } -} diff --git a/src/RemoteAPI/interface-cache.php b/src/RemoteAPI/interface-cache.php deleted file mode 100644 index 9b20fa5fc..000000000 --- a/src/RemoteAPI/interface-cache.php +++ /dev/null @@ -1,46 +0,0 @@ - $query The query arguments to send to the remote API. - * @param bool $associative (optional) When TRUE, returned objects will be converted into - * associative arrays. - * @return array|object|WP_Error - */ - public function get_items( array $query, bool $associative = false ); - - /** - * Returns whether the endpoint is available for access by the current - * user. - * - * @since 3.14.0 Renamed from `is_user_allowed_to_make_api_call()`. - * @since 3.16.0 Added the `$request` parameter. - * - * @param WP_REST_Request|null $request The request object. - * @return bool - */ - public function is_available_to_current_user( $request = null ): bool; -} diff --git a/src/UI/class-recommended-widget.php b/src/UI/class-recommended-widget.php index b72bd2e5e..25f8fca2e 100644 --- a/src/UI/class-recommended-widget.php +++ b/src/UI/class-recommended-widget.php @@ -92,7 +92,7 @@ public function __construct( Parsely $parsely ) { * @return string API URL. */ private function get_api_url( string $site_id, ?int $published_within, ?string $sort, int $return_limit ): string { - $related_api_endpoint = Parsely::PUBLIC_API_BASE_URL . '/related'; + $related_api_endpoint = $this->parsely->get_content_api()->get_endpoint( '/related' ); $query_args = array( 'apikey' => $site_id, @@ -104,7 +104,7 @@ private function get_api_url( string $site_id, ?int $published_within, ?string $ $query_args['pub_date_start'] = $published_within . 'd'; } - return add_query_arg( $query_args, $related_api_endpoint ); + return $related_api_endpoint->get_endpoint_url( $query_args ); } /** diff --git a/src/UI/class-settings-page.php b/src/UI/class-settings-page.php index 5e756525b..a901ace8d 100644 --- a/src/UI/class-settings-page.php +++ b/src/UI/class-settings-page.php @@ -1198,7 +1198,7 @@ public function validate_options( $input ) { * @param ParselySettingOptions $input Options from the settings page. * @return ParselySettingOptions Validated inputs. */ - private function validate_basic_section( $input ) { + private function validate_basic_section( $input ): array { $are_credentials_managed = $this->parsely->are_credentials_managed; $options = $this->parsely->get_options(); @@ -1217,7 +1217,10 @@ private function validate_basic_section( $input ) { $valid_credentials = true; } - if ( is_wp_error( $valid_credentials ) && Validator::INVALID_API_CREDENTIALS === $valid_credentials->get_error_code() ) { + if ( + ( is_wp_error( $valid_credentials ) && Validator::INVALID_API_CREDENTIALS === $valid_credentials->get_error_code() ) || + ( is_bool( $valid_credentials ) && ! $valid_credentials ) + ) { add_settings_error( Parsely::OPTIONS_KEY, 'api_secret', diff --git a/src/blocks/recommendations/components/parsely-recommendations-fetcher.tsx b/src/blocks/recommendations/components/parsely-recommendations-fetcher.tsx index 37fb2ef01..1f1169ff3 100644 --- a/src/blocks/recommendations/components/parsely-recommendations-fetcher.tsx +++ b/src/blocks/recommendations/components/parsely-recommendations-fetcher.tsx @@ -44,7 +44,7 @@ export const ParselyRecommendationsFetcher = ( try { response = await apiFetch>( { - path: addQueryArgs( '/wp-parsely/v1/related', { query } ), + path: addQueryArgs( '/wp-parsely/v2/stats/related', query ), } ); } catch ( wpError ) { error = wpError; diff --git a/src/blocks/recommendations/components/parsely-recommendations.tsx b/src/blocks/recommendations/components/parsely-recommendations.tsx index 4e9ae75c8..fa2f117ea 100644 --- a/src/blocks/recommendations/components/parsely-recommendations.tsx +++ b/src/blocks/recommendations/components/parsely-recommendations.tsx @@ -41,7 +41,7 @@ export function ParselyRecommendations( { if ( httpError ) { message = __( 'The Parse.ly Recommendations API is not accessible. You may be offline.', 'wp-parsely' ); - } else if ( message.includes( 'Error: {"code":403,"message":"Forbidden","data":null}' ) ) { + } else if ( error.message === 'Forbidden' && error.data?.status === 403 && error.code === 403 ) { message = __( 'Access denied. Please verify that your Site ID is valid.', 'wp-parsely' ); } else if ( message.startsWith( 'Error: {"code":"parsely_site_id_not_set"' ) ) { message = __( 'To use this Block, a Parse.ly Site ID must be set in the plugin\'s options', 'wp-parsely' ); diff --git a/src/blocks/recommendations/recommendations-store.tsx b/src/blocks/recommendations/recommendations-store.tsx index fff294e4d..65d3008a9 100644 --- a/src/blocks/recommendations/recommendations-store.tsx +++ b/src/blocks/recommendations/recommendations-store.tsx @@ -9,12 +9,14 @@ import { createContext, useContext, useMemo, useReducer } from '@wordpress/eleme import { RecommendationsAction } from './constants'; import { Recommendation } from './models/Recommendation'; +type RecommendationError = Error & { code: string|number, data?: { status?: string|number } }; + interface RecommendationState { isLoaded: boolean; recommendations: Recommendation[]; uuid: string | null; clientId: string | null; - error: Error | null; + error: RecommendationError | null; } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/class-parsely.php b/src/class-parsely.php index e7c673fed..a7a9bee5e 100644 --- a/src/class-parsely.php +++ b/src/class-parsely.php @@ -10,6 +10,9 @@ namespace Parsely; +use Parsely\REST_API\REST_API_Controller; +use Parsely\Services\Content_API\Content_API_Service; +use Parsely\Services\Suggestions_API\Suggestions_API_Service; use Parsely\UI\Metadata_Renderer; use Parsely\UI\Settings_Page; use Parsely\Utils\Utils; @@ -58,12 +61,12 @@ * } * * @phpstan-type WP_HTTP_Request_Args array{ - * method: string, - * timeout: float, - * blocking: bool, - * headers: array, - * body: string, - * data_format: string, + * method?: string, + * timeout?: float, + * blocking?: bool, + * headers?: array, + * body?: string, + * data_format?: string, * } * * @phpstan-import-type Metadata_Attributes from Metadata @@ -72,13 +75,32 @@ class Parsely { /** * Declare our constants */ - public const VERSION = PARSELY_VERSION; - public const MENU_SLUG = 'parsely'; // The page param passed to options-general.php. - public const OPTIONS_KEY = 'parsely'; // The key used to store options in the WP database. - public const CAPABILITY = 'manage_options'; // The capability required to administer settings. - public const DASHBOARD_BASE_URL = 'https://dash.parsely.com'; - public const PUBLIC_API_BASE_URL = 'https://api.parsely.com/v2'; - public const PUBLIC_SUGGESTIONS_API_BASE_URL = 'https://content-suggestions-api.parsely.net/prod'; + public const VERSION = PARSELY_VERSION; + public const MENU_SLUG = 'parsely'; // The page param passed to options-general.php. + public const OPTIONS_KEY = 'parsely'; // The key used to store options in the WP database. + public const CAPABILITY = 'manage_options'; // The capability required to administer settings. + public const DASHBOARD_BASE_URL = 'https://dash.parsely.com'; + + /** + * The Content API service. + * + * @var ?Content_API_Service $content_api_service + */ + private $content_api_service; + + /** + * The Suggestions API service. + * + * @var ?Suggestions_API_Service $suggestions_api_service + */ + private $suggestions_api_service; + + /** + * The Parse.ly internal REST API controller. + * + * @var REST_API_Controller|null $rest_api_controller + */ + private $rest_api_controller; /** * Declare some class properties @@ -237,6 +259,57 @@ public function run(): void { add_action( 'save_post', array( $this, 'update_metadata_endpoint' ) ); } + /** + * Returns the Content API service. + * + * This method returns the Content API service, which is used to interact with the Parse.ly Content API. + * + * @since 3.17.0 + * + * @return Content_API_Service + */ + public function get_content_api(): Content_API_Service { + if ( ! isset( $this->content_api_service ) ) { + $this->content_api_service = new Content_API_Service( $this ); + } + + return $this->content_api_service; + } + + /** + * Returns the Suggestions API service. + * + * This method returns the Suggestions API service, which is used to interact with the Parse.ly Suggestions API. + * + * @since 3.17.0 + * + * @return Suggestions_API_Service + */ + public function get_suggestions_api(): Suggestions_API_Service { + if ( ! isset( $this->suggestions_api_service ) ) { + $this->suggestions_api_service = new Suggestions_API_Service( $this ); + } + + return $this->suggestions_api_service; + } + + /** + * Gets the REST API controller. + * + * If the controller is not set, a new instance is created. + * + * @since 3.17.0 + * + * @return REST_API_Controller + */ + public function get_rest_api_controller(): REST_API_Controller { + if ( ! isset( $this->rest_api_controller ) ) { + $this->rest_api_controller = new REST_API_Controller( $this ); + } + + return $this->rest_api_controller; + } + /** * Gets the full URL of the JavaScript tracker file for the site. If an API * key is not set, return an empty string. @@ -384,7 +457,8 @@ public function update_metadata_endpoint( int $post_id ): void { 'tags' => $metadata['keywords'] ?? '', ); - $parsely_api_endpoint = self::PUBLIC_API_BASE_URL . '/metadata/posts'; + $parsely_api_base_url = Content_API_Service::get_base_url(); + $parsely_api_endpoint = $parsely_api_base_url . '/metadata/posts'; $parsely_metadata_secret = $parsely_options['metadata_secret']; $headers = array( 'Content-Type' => 'application/json' ); @@ -938,8 +1012,8 @@ private function sanitize_managed_option( string $option_id, $value ) { private function allow_parsely_remote_requests(): void { $allowed_urls = array( self::DASHBOARD_BASE_URL, - self::PUBLIC_API_BASE_URL, - self::PUBLIC_SUGGESTIONS_API_BASE_URL, + Content_API_Service::get_base_url(), + Suggestions_API_Service::get_base_url(), ); add_filter( diff --git a/src/class-validator.php b/src/class-validator.php index 26c915c85..2f0bfe0da 100644 --- a/src/class-validator.php +++ b/src/class-validator.php @@ -44,7 +44,7 @@ public static function validate_metadata_secret( string $metadata_secret ): bool * @param Parsely $parsely The Parsely instance. * @param string $site_id The Site ID to be validated. * @param string $api_secret The API Secret to be validated. - * @return true|WP_Error True if the API Credentials are valid, WP_Error otherwise. + * @return bool|WP_Error True if the API Credentials are valid, WP_Error otherwise. */ public static function validate_api_credentials( Parsely $parsely, string $site_id, string $api_secret ) { // If the API secret is empty, the validation endpoint will always fail. @@ -54,21 +54,16 @@ public static function validate_api_credentials( Parsely $parsely, string $site_ return true; } - $query_args = array( - 'apikey' => $site_id, - 'secret' => $api_secret, - ); + $content_api = $parsely->get_content_api(); + $is_valid = $content_api->validate_credentials( $site_id, $api_secret ); - $validate_api = new RemoteAPI\Validate_API( $parsely ); - $request = $validate_api->get_items( $query_args ); - - if ( is_wp_error( $request ) ) { + if ( is_wp_error( $is_valid ) ) { return new WP_Error( self::INVALID_API_CREDENTIALS, __( 'Invalid API Credentials', 'wp-parsely' ) ); } - return true; + return $is_valid; } } diff --git a/src/content-helper/common/class-content-helper-feature.php b/src/content-helper/common/class-content-helper-feature.php index b0edb6505..83c6f04b7 100644 --- a/src/content-helper/common/class-content-helper-feature.php +++ b/src/content-helper/common/class-content-helper-feature.php @@ -166,15 +166,17 @@ protected function inject_inline_scripts( $settings = rest_do_request( new WP_REST_Request( 'GET', - '/wp-parsely/v1' . $settings_route + '/wp-parsely/v2/settings/' . $settings_route ) )->get_data(); } - if ( ! is_string( $settings ) ) { - $settings = ''; + if ( ! is_array( $settings ) ) { + $settings = array(); } + $settings = wp_json_encode( $settings ); + wp_add_inline_script( static::get_script_id(), "window.wpParselyContentHelperSettings = '$settings';", diff --git a/src/content-helper/common/settings/provider.tsx b/src/content-helper/common/settings/provider.tsx index ef4ea23f7..5e696b4bc 100644 --- a/src/content-helper/common/settings/provider.tsx +++ b/src/content-helper/common/settings/provider.tsx @@ -78,6 +78,7 @@ type ReactDeps = React.DependencyList | undefined; * * @since 3.13.0 * @since 3.14.0 Moved from `content-helper/common/hooks/useSaveSettings.ts`. + * @since 3.17.0 Updated to the new API endpoints. * * @param {string} endpoint The settings endpoint to send the data to. * @param {Settings} data The data to send. @@ -96,7 +97,7 @@ const useSaveSettings = ( } apiFetch( { - path: '/wp-parsely/v1/user-meta/content-helper/' + endpoint, + path: '/wp-parsely/v2/settings/' + endpoint, method: 'PUT', data, } ); diff --git a/src/content-helper/dashboard-widget/class-dashboard-widget.php b/src/content-helper/dashboard-widget/class-dashboard-widget.php index a166adff6..cc72d0e79 100644 --- a/src/content-helper/dashboard-widget/class-dashboard-widget.php +++ b/src/content-helper/dashboard-widget/class-dashboard-widget.php @@ -10,11 +10,9 @@ namespace Parsely\Content_Helper; -use Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint; use Parsely\Parsely; -use Parsely\RemoteAPI\Analytics_Posts_API; - use Parsely\Utils\Utils; +use Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings; use const Parsely\PARSELY_FILE; @@ -89,12 +87,13 @@ public function run(): void { * @return bool Whether the Dashboard Widget can be enabled. */ public function can_enable_widget(): bool { - $screen = get_current_screen(); - $posts_api = new Analytics_Posts_API( $GLOBALS['parsely'] ); + $screen = get_current_screen(); return $this->can_enable_feature( null !== $screen && 'dashboard' === $screen->id, - $posts_api->is_available_to_current_user() + $this->parsely->get_rest_api_controller()->is_available_to_current_user( + '/stats/posts' + ) ); } @@ -136,7 +135,7 @@ public function enqueue_assets(): void { true ); - $this->inject_inline_scripts( Dashboard_Widget_Settings_Endpoint::get_route() ); + $this->inject_inline_scripts( Endpoint_Dashboard_Widget_Settings::get_endpoint_name() ); wp_enqueue_style( static::get_style_id(), diff --git a/src/content-helper/dashboard-widget/dashboard-widget.tsx b/src/content-helper/dashboard-widget/dashboard-widget.tsx index 09959ee2f..b67f4acf6 100644 --- a/src/content-helper/dashboard-widget/dashboard-widget.tsx +++ b/src/content-helper/dashboard-widget/dashboard-widget.tsx @@ -56,7 +56,7 @@ window.addEventListener( if ( null !== container ) { const component = diff --git a/src/content-helper/dashboard-widget/provider.ts b/src/content-helper/dashboard-widget/provider.ts index 23bc4673e..0338e490a 100644 --- a/src/content-helper/dashboard-widget/provider.ts +++ b/src/content-helper/dashboard-widget/provider.ts @@ -83,7 +83,7 @@ export class DashboardWidgetProvider extends BaseProvider { settings: TopPostsSettings, page: number ): Promise { const response = this.fetch( { - path: addQueryArgs( '/wp-parsely/v1/stats/posts/', { + path: addQueryArgs( '/wp-parsely/v2/stats/posts/', { limit: TOP_POSTS_DEFAULT_LIMIT, ...getApiPeriodParams( settings.Period ), sort: settings.Metric, diff --git a/src/content-helper/editor-sidebar/class-editor-sidebar.php b/src/content-helper/editor-sidebar/class-editor-sidebar.php index 9d0accb25..7b2256aa3 100644 --- a/src/content-helper/editor-sidebar/class-editor-sidebar.php +++ b/src/content-helper/editor-sidebar/class-editor-sidebar.php @@ -12,20 +12,14 @@ use Parsely\Content_Helper\Editor_Sidebar\Smart_Linking; use Parsely\Dashboard_Link; -use Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint; use Parsely\Parsely; -use Parsely\Content_Helper\Content_Helper_Feature; +use Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings; use Parsely\Utils\Utils; use WP_Post; use const Parsely\PARSELY_FILE; -/** - * Features requires for the PCH Editor Sidebar. - */ -require_once __DIR__ . '/smart-linking/class-smart-linking.php'; - /** * Class that generates and manages the PCH Editor Sidebar. * @@ -163,7 +157,7 @@ public function run(): void { true ); - $this->inject_inline_scripts( Editor_Sidebar_Settings_Endpoint::get_route() ); + $this->inject_inline_scripts( Endpoint_Editor_Sidebar_Settings::get_endpoint_name() ); // Inject inline variables for the editor sidebar, without UTM parameters. $parsely_post_url = $this->get_parsely_post_url( null, false ); diff --git a/src/content-helper/editor-sidebar/editor-sidebar.tsx b/src/content-helper/editor-sidebar/editor-sidebar.tsx index f3e36d922..2c57a4988 100644 --- a/src/content-helper/editor-sidebar/editor-sidebar.tsx +++ b/src/content-helper/editor-sidebar/editor-sidebar.tsx @@ -228,7 +228,7 @@ const ContentHelperEditorSidebar = (): React.JSX.Element => { title={ __( 'Parse.ly', 'wp-parsely' ) } > @@ -279,7 +279,7 @@ registerPlugin( BLOCK_PLUGIN_ID, { icon: LeafIcon, render: () => ( diff --git a/src/content-helper/editor-sidebar/performance-stats/provider.ts b/src/content-helper/editor-sidebar/performance-stats/provider.ts index 5bc524cd6..df8293aca 100644 --- a/src/content-helper/editor-sidebar/performance-stats/provider.ts +++ b/src/content-helper/editor-sidebar/performance-stats/provider.ts @@ -68,13 +68,13 @@ export class PerformanceStatsProvider extends BaseProvider { ); } - // Get post URL. - const postUrl = editor.getPermalink(); + // Get post ID. + const postID = editor.getCurrentPostId(); - if ( null === postUrl ) { + if ( null === postID ) { return Promise.reject( new ContentHelperError( __( - "The post's URL returned null.", + "The post's ID returned null.", 'wp-parsely' ), ContentHelperErrorCode.PostIsNotPublished ) ); @@ -84,10 +84,10 @@ export class PerformanceStatsProvider extends BaseProvider { let performanceData, referrerData; try { performanceData = await this.fetchPerformanceDataFromWpEndpoint( - period, postUrl + period, postID ); referrerData = await this.fetchReferrerDataFromWpEndpoint( - period, postUrl, performanceData.views + period, postID, performanceData.views ); } catch ( contentHelperError ) { return Promise.reject( contentHelperError ); @@ -100,20 +100,19 @@ export class PerformanceStatsProvider extends BaseProvider { * Fetches the performance data for the current post from the WordPress REST * API. * - * @param {Period} period The period for which to fetch data. - * @param {string} postUrl + * @param {Period} period The period for which to fetch data. + * @param {number} postId The post's ID. * * @return {Promise } The current post's details. */ private async fetchPerformanceDataFromWpEndpoint( - period: Period, postUrl: string + period: Period, postId: number ): Promise { const response = await this.fetch( { path: addQueryArgs( - '/wp-parsely/v1/stats/post/detail', { + `/wp-parsely/v2/stats/post/${ postId }/details`, { ...getApiPeriodParams( period ), itm_source: this.itmSource, - url: postUrl, } ), } ); @@ -122,8 +121,8 @@ export class PerformanceStatsProvider extends BaseProvider { return Promise.reject( new ContentHelperError( sprintf( /* translators: URL of the published post */ - __( 'The post %s has 0 views, or the Parse.ly API returned no data.', - 'wp-parsely' ), postUrl + __( 'The post %d has 0 views, or the Parse.ly API returned no data.', + 'wp-parsely' ), postId ), ContentHelperErrorCode.ParselyApiReturnedNoData, '' ) ); } @@ -133,8 +132,8 @@ export class PerformanceStatsProvider extends BaseProvider { return Promise.reject( new ContentHelperError( sprintf( /* translators: URL of the published post */ - __( 'Multiple results were returned for the post %s by the Parse.ly API.', - 'wp-parsely' ), postUrl + __( 'Multiple results were returned for the post %d by the Parse.ly API.', + 'wp-parsely' ), postId ), ContentHelperErrorCode.ParselyApiReturnedTooManyResults ) ); } @@ -145,22 +144,21 @@ export class PerformanceStatsProvider extends BaseProvider { /** * Fetches referrer data for the current post from the WordPress REST API. * - * @param {Period} period The period for which to fetch data. - * @param {string} postUrl The post's URL. - * @param {string} totalViews Total post views (including direct views). + * @param {Period} period The period for which to fetch data. + * @param {string|number} postId The post's ID. + * @param {string} totalViews Total post views (including direct views). * * @return {Promise} The post's referrer data. */ private async fetchReferrerDataFromWpEndpoint( - period: Period, postUrl: string, totalViews: string + period: Period, postId: string|number, totalViews: string ): Promise { const response = await this.fetch( { path: addQueryArgs( - '/wp-parsely/v1/referrers/post/detail', { + `/wp-parsely/v2/stats/post/${ postId }/referrers`, { ...getApiPeriodParams( period ), itm_source: this.itmSource, total_views: totalViews, // Needed to calculate direct views. - url: postUrl, } ), } ); diff --git a/src/content-helper/editor-sidebar/related-posts/provider.ts b/src/content-helper/editor-sidebar/related-posts/provider.ts index 6345f4f19..6051c4ca8 100644 --- a/src/content-helper/editor-sidebar/related-posts/provider.ts +++ b/src/content-helper/editor-sidebar/related-posts/provider.ts @@ -146,7 +146,7 @@ export class RelatedPostsProvider extends BaseProvider { */ private async fetchRelatedPostsFromWpEndpoint( query: RelatedPostsApiQuery ): Promise { const response = this.fetch( { - path: addQueryArgs( '/wp-parsely/v1/stats/posts', { + path: addQueryArgs( '/wp-parsely/v2/stats/posts', { ...query.query, itm_source: 'wp-parsely-content-helper', } ), diff --git a/src/content-helper/editor-sidebar/smart-linking/provider.ts b/src/content-helper/editor-sidebar/smart-linking/provider.ts index ce30569f5..4e60e8edf 100644 --- a/src/content-helper/editor-sidebar/smart-linking/provider.ts +++ b/src/content-helper/editor-sidebar/smart-linking/provider.ts @@ -140,7 +140,7 @@ export class SmartLinkingProvider extends BaseProvider { ): Promise { const response = await this.fetch( { method: 'POST', - path: addQueryArgs( '/wp-parsely/v1/content-suggestions/suggest-linked-reference', { + path: addQueryArgs( '/wp-parsely/v2/content-helper/smart-linking/generate', { max_links: maxLinksPerPost, } ), data: { @@ -165,7 +165,7 @@ export class SmartLinkingProvider extends BaseProvider { public async addSmartLink( postID: number, linkSuggestion: SmartLink ): Promise { return await this.fetch( { method: 'POST', - path: `/wp-parsely/v1/smart-linking/${ postID }/add`, + path: `/wp-parsely/v2/content-helper/smart-linking/${ postID }/add`, data: { link: linkSuggestion, }, @@ -195,7 +195,7 @@ export class SmartLinkingProvider extends BaseProvider { return await this.fetch( { method: 'POST', - path: `/wp-parsely/v1/smart-linking/${ postID }/add-multiple`, + path: `/wp-parsely/v2/content-helper/smart-linking/${ postID }/add-multiple`, data: { links: linkSuggestions, }, @@ -230,7 +230,7 @@ export class SmartLinkingProvider extends BaseProvider { return await this.fetch( { method: 'POST', - path: `/wp-parsely/v1/smart-linking/${ postID }/set`, + path: `/wp-parsely/v2/content-helper/smart-linking/${ postID }/set`, data: { links: appliedSmartLinks, }, @@ -249,7 +249,7 @@ export class SmartLinkingProvider extends BaseProvider { public async getSmartLinks( postID: number ): Promise { return await this.fetch( { method: 'GET', - path: `/wp-parsely/v1/smart-linking/${ postID }/get`, + path: `/wp-parsely/v2/content-helper/smart-linking/${ postID }/get`, } ); } @@ -265,7 +265,7 @@ export class SmartLinkingProvider extends BaseProvider { public async getPostTypeByURL( url: string ): Promise { return await this.fetch( { method: 'POST', - path: '/wp-parsely/v1/smart-linking/url-to-post-type', + path: '/wp-parsely/v2/content-helper/smart-linking/url-to-post-type', data: { url, }, diff --git a/src/content-helper/editor-sidebar/smart-linking/smart-linking.tsx b/src/content-helper/editor-sidebar/smart-linking/smart-linking.tsx index bdec814f6..cb40a3558 100644 --- a/src/content-helper/editor-sidebar/smart-linking/smart-linking.tsx +++ b/src/content-helper/editor-sidebar/smart-linking/smart-linking.tsx @@ -53,7 +53,7 @@ const withSettingsProvider = createHigherOrderComponent( ( BlockEdit ) => { return ( diff --git a/src/content-helper/editor-sidebar/title-suggestions/provider.ts b/src/content-helper/editor-sidebar/title-suggestions/provider.ts index c6095bf5e..9b85f4767 100644 --- a/src/content-helper/editor-sidebar/title-suggestions/provider.ts +++ b/src/content-helper/editor-sidebar/title-suggestions/provider.ts @@ -52,13 +52,13 @@ export class TitleSuggestionsProvider extends BaseProvider { public async generateTitles( content: string, limit: number = 3, tone: ToneProp, persona: PersonaProp ): Promise { const response = this.fetch( { method: 'POST', - path: addQueryArgs( '/wp-parsely/v1/content-suggestions/suggest-headline', { + path: addQueryArgs( '/wp-parsely/v2/content-helper/title-suggestions/generate', { limit, tone: getToneLabel( tone ), persona: getPersonaLabel( persona ), } ), data: { - content, + text: content, }, } ); diff --git a/src/content-helper/excerpt-generator/provider.ts b/src/content-helper/excerpt-generator/provider.ts index 6fb4dcaf0..2a5ebaf83 100644 --- a/src/content-helper/excerpt-generator/provider.ts +++ b/src/content-helper/excerpt-generator/provider.ts @@ -51,11 +51,11 @@ export class ExcerptGeneratorProvider extends BaseProvider { return await this.fetch( { method: 'POST', - path: addQueryArgs( '/wp-parsely/v1/content-suggestions/suggest-brief', { + path: addQueryArgs( '/wp-parsely/v2/content-helper/excerpt-generator/generate', { title, } ), data: { - content, + text: content, }, } ); } diff --git a/src/content-helper/post-list-stats/class-post-list-stats.php b/src/content-helper/post-list-stats/class-post-list-stats.php index 42b2452e8..9ea12d9a4 100644 --- a/src/content-helper/post-list-stats/class-post-list-stats.php +++ b/src/content-helper/post-list-stats/class-post-list-stats.php @@ -11,10 +11,9 @@ namespace Parsely\Content_Helper; use DateTime; -use Parsely\Content_Helper\Content_Helper_Feature; use Parsely\Parsely; -use Parsely\RemoteAPI\Base_Endpoint_Remote; -use Parsely\RemoteAPI\Analytics_Posts_API; +use Parsely\Services\Content_API\Content_API_Service; +use Parsely\Services\Content_API\Endpoints\Endpoint_Analytics_Posts; use Parsely\Utils\Utils; use WP_Screen; @@ -26,9 +25,14 @@ * @since 3.7.0 * @since 3.9.0 Renamed FQCN from `Parsely\UI\Admin_Columns_Parsely_Stats` to `Parsely\Content_Helper\Post_List_Stats`. * - * @phpstan-import-type Analytics_Post_API_Params from Analytics_Posts_API - * @phpstan-import-type Analytics_Post from Analytics_Posts_API - * @phpstan-import-type Remote_API_Error from Base_Endpoint_Remote + * @phpstan-import-type Analytics_Posts_API_Params from Endpoint_Analytics_Posts + * @phpstan-import-type Analytics_Post from Endpoint_Analytics_Posts + * + * @phpstan-type Remote_API_Error array{ + * code: int, + * message: string, + * htmlMessage: string, + * } * * @phpstan-type Parsely_Post_Stats array{ * page_views: string, @@ -42,12 +46,13 @@ * } */ class Post_List_Stats extends Content_Helper_Feature { + /** - * Instance of Parsely Analytics Posts API. + * Instance of Content API Service. * - * @var Analytics_Posts_API + * @var Content_API_Service */ - private $analytics_api; + private $content_api; /** * Internal Variable. @@ -72,7 +77,8 @@ class Post_List_Stats extends Content_Helper_Feature { * @param Parsely $parsely Instance of Parsely class. */ public function __construct( Parsely $parsely ) { - $this->parsely = $parsely; + $this->parsely = $parsely; + $this->content_api = $parsely->get_content_api(); } /** @@ -114,12 +120,10 @@ public static function get_style_id(): string { * @since 3.7.0 */ public function run(): void { - $this->analytics_api = new Analytics_Posts_API( $this->parsely ); - if ( ! $this->can_enable_feature( $this->parsely->site_id_is_set(), $this->parsely->api_secret_is_set(), - $this->analytics_api->is_available_to_current_user() + $this->parsely->get_rest_api_controller()->is_available_to_current_user( '/stats/posts' ) ) ) { return; } @@ -225,7 +229,7 @@ public function enqueue_parsely_stats_script_with_data(): void { return; // Avoid calling the API if column is hidden. } - $parsely_stats_response = $this->get_parsely_stats_response( $this->analytics_api ); + $parsely_stats_response = $this->get_parsely_stats_response(); if ( null === $parsely_stats_response ) { return; @@ -267,10 +271,9 @@ public function is_parsely_stats_column_hidden(): bool { * * @since 3.7.0 * - * @param Analytics_Posts_API $analytics_api Instance of Analytics_Posts_API. * @return Parsely_Posts_Stats_Response|null */ - public function get_parsely_stats_response( $analytics_api ) { + public function get_parsely_stats_response(): ?array { if ( ! $this->is_tracked_as_post_type() ) { return null; } @@ -296,12 +299,12 @@ public function get_parsely_stats_response( $analytics_api ) { return null; } - $response = $analytics_api->get_posts_analytics( + $response = $this->content_api->get_posts( array( - 'period_start' => Analytics_Posts_API::ANALYTICS_API_DAYS_LIMIT . 'd', + 'period_start' => Endpoint_Analytics_Posts::MAX_PERIOD, 'pub_date_start' => $date_params['pub_date_start'] ?? '', 'pub_date_end' => $date_params['pub_date_end'] ?? '', - 'limit' => Analytics_Posts_API::MAX_RECORDS_LIMIT, + 'limit' => Endpoint_Analytics_Posts::MAX_LIMIT, 'sort' => 'avg_engaged', // Note: API sends different stats on different sort options. ) ); @@ -322,20 +325,14 @@ public function get_parsely_stats_response( $analytics_api ) { ); } - if ( null === $response ) { - return array( - 'data' => array(), - 'error' => null, - ); - } - /** - * Variable. - * - * @var array + * @var array $parsely_stats_map */ $parsely_stats_map = array(); + /** + * @var Analytics_Post $post_analytics + */ foreach ( $response as $post_analytics ) { $key = $this->get_unique_stats_key_from_analytics( $post_analytics ); @@ -349,9 +346,7 @@ public function get_parsely_stats_response( $analytics_api ) { $engaged_seconds = isset( $metrics['avg_engaged'] ) ? round( $metrics['avg_engaged'] * 60, 2 ) : 0; /** - * Variable. - * - * @var Parsely_Post_Stats + * @var Parsely_Post_Stats $stats */ $stats = array( 'page_views' => Utils::get_formatted_number( (string) $views ) . ' ' . _n( 'page view', 'page views', $views, 'wp-parsely' ), @@ -375,7 +370,7 @@ public function get_parsely_stats_response( $analytics_api ) { * * @since 3.7.0 * - * @return Analytics_Post_API_Params|null + * @return Analytics_Posts_API_Params|null */ private function get_publish_date_params_for_analytics_api() { $published_times = $this->utc_published_times; diff --git a/src/rest-api/class-base-api-controller.php b/src/rest-api/class-base-api-controller.php new file mode 100644 index 000000000..b0553ff21 --- /dev/null +++ b/src/rest-api/class-base-api-controller.php @@ -0,0 +1,204 @@ + + */ + private $endpoints; + + /** + * The Parsely instance. + * + * @since 3.17.0 + * + * @var Parsely + */ + private $parsely; + + /** + * Constructor. + * + * @since 3.17.0 + * + * @param Parsely $parsely The Parsely instance. + */ + public function __construct( Parsely $parsely ) { + $this->parsely = $parsely; + $this->endpoints = array(); + } + + /** + * Initializes the API controller. + * + * This method should be overridden by child classes and used to register + * endpoints. + * + * @since 3.17.0 + * + * @return void + */ + abstract protected function init(): void; + + /** + * Gets the namespace for the API. + * + * This method should be overridden by child classes to define the namespace. + * + * @since 3.17.0 + * + * @return string The namespace. + */ + abstract protected function get_namespace(): string; + + /** + * Gets the version for the API. + * + * This method can be overridden by child classes to define the version. + * + * @since 3.17.0 + * + * @return string The version. + */ + protected function get_version(): string { + return ''; + } + + /** + * Gets the route prefix, which acts as a namespace for the endpoints. + * + * This method can be overridden by child classes to define the route prefix. + * + * @since 3.17.0 + * + * @return string The route prefix. + */ + public static function get_route_prefix(): string { + return ''; + } + + /** + * Returns the full namespace for the API, including the version if defined. + * + * @since 3.17.0 + * + * @return string + */ + public function get_full_namespace(): string { + $namespace = $this->get_namespace(); + + if ( '' !== $this->get_version() ) { + $namespace .= '/' . $this->get_version(); + } + + return $namespace; + } + + /** + * Gets the Parsely instance. + * + * @since 3.17.0 + * + * @return Parsely The Parsely instance. + */ + public function get_parsely(): Parsely { + return $this->parsely; + } + + /** + * Gets the registered endpoints. + * + * @since 3.17.0 + * + * @return Base_Endpoint[] The registered endpoints. + */ + public function get_endpoints(): array { + return $this->endpoints; + } + + /** + * Registers a single endpoint. + * + * @since 3.17.0 + * + * @param Base_Endpoint $endpoint The endpoint to register. + */ + protected function register_endpoint( Base_Endpoint $endpoint ): void { + $this->endpoints[ $endpoint->get_endpoint_slug() ] = $endpoint; + $endpoint->init(); + } + + /** + * Registers multiple endpoints. + * + * @since 3.17.0 + * + * @param Base_Endpoint[] $endpoints The endpoints to register. + */ + protected function register_endpoints( array $endpoints ): void { + foreach ( $endpoints as $endpoint ) { + $this->register_endpoint( $endpoint ); + } + } + + /** + * Prefixes a route with the route prefix. + * + * @since 3.17.0 + * + * @param string $route The route to prefix. + * @return string The prefixed route. + */ + public function prefix_route( string $route ): string { + if ( '' === static::get_route_prefix() ) { + return $route; + } + + return static::get_route_prefix() . '/' . $route; + } + + /** + * Returns a specific endpoint by name. + * + * @since 3.17.0 + * + * @param string $endpoint The endpoint name/path. + * @return Base_Endpoint|null The endpoint object, or null if not found. + */ + protected function get_endpoint( string $endpoint ): ?Base_Endpoint { + return $this->endpoints[ $endpoint ] ?? null; + } + + /** + * Checks if a specific endpoint is available to the current user. + * + * @since 3.17.0 + * + * @param string $endpoint The endpoint to check. + * @return bool True if the controller is available to the current user, false otherwise. + */ + abstract public function is_available_to_current_user( string $endpoint ): bool; +} diff --git a/src/rest-api/class-base-endpoint.php b/src/rest-api/class-base-endpoint.php new file mode 100644 index 000000000..ecea575a6 --- /dev/null +++ b/src/rest-api/class-base-endpoint.php @@ -0,0 +1,307 @@ + + */ + protected $registered_routes = array(); + + /** + * Constructor. + * + * @since 3.17.0 + * + * @param Base_API_Controller $controller The REST API controller. + */ + public function __construct( Base_API_Controller $controller ) { + $this->api_controller = $controller; + $this->parsely = $controller->get_parsely(); + } + + /** + * Initializes the API endpoint, by registering the routes. + * + * Allows for the endpoint to be disabled via the + * `wp_parsely_api_{endpoint}_endpoint_enabled` filter. + * + * @since 3.17.0 + */ + public function init(): void { + /** + * Filter to enable/disable the endpoint. + * + * @return bool + */ + $filter_name = 'wp_parsely_api_' . + Utils::convert_endpoint_to_filter_key( static::get_endpoint_name() ) . + '_endpoint_enabled'; + if ( ! apply_filters( $filter_name, true ) ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound + return; + } + + // Register the routes. + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + /** + * Returns the endpoint name. + * + * This method should be overridden by child classes and used to return the + * endpoint name. + * + * @since 3.17.0 + * + * @return string + */ + abstract public static function get_endpoint_name(): string; + + /** + * Returns the default access capability for the endpoint. + * + * This method can be overridden by child classes to return a different + * default access capability. + * + * @since 3.17.0 + * + * @return string + */ + protected function get_default_access_capability(): string { + return 'publish_posts'; + } + + /** + * Registers the routes for the endpoint. + * + * This method should be overridden by child classes and used to register + * the routes for the endpoint. + * + * @since 3.17.0 + */ + abstract public function register_routes(): void; + + /** + * Registers a REST route. + * + * @since 3.17.0 + * + * @param string $route The route to register. + * @param string[] $methods Array with the allowed methods. + * @param callable $callback Callback function to call when the endpoint is hit. + * @param array $args The endpoint arguments definition. + */ + public function register_rest_route( string $route, array $methods, callable $callback, array $args = array() ): void { + // Trim any possible slashes from the route. + $route = trim( $route, '/' ); + + // Store the route for later reference. + $this->registered_routes[] = $route; + + // Create the full route for the endpoint. + $route = static::get_endpoint_name() . '/' . $route; + + // Register the route. + register_rest_route( + $this->api_controller->get_full_namespace(), + $this->api_controller->prefix_route( $route ), + array( + array( + 'methods' => $methods, + 'callback' => $callback, + 'permission_callback' => array( $this, 'is_available_to_current_user' ), + 'args' => $args, + 'show_in_index' => ! is_wp_error( $this->is_available_to_current_user() ), + ), + ) + ); + } + + /** + * Returns the full endpoint path for a given route. + * + * @since 3.17.0 + * + * @param string $route The route. + * @return string + */ + public function get_full_endpoint( string $route = '' ): string { + $route = trim( $route, '/' ); + + if ( '' !== $route ) { + $route = static::get_endpoint_name() . '/' . $route; + } else { + $route = static::get_endpoint_name(); + } + + return '/' . + $this->api_controller->get_full_namespace() . + '/' . + $this->api_controller->prefix_route( $route ); + } + + /** + * Returns the endpoint slug. + * + * The slug is the endpoint name prefixed with the route prefix, from + * the API controller. + * + * Used as an identifier for the endpoint, when registering routes. + * + * @since 3.17.0 + * + * @return string + */ + public function get_endpoint_slug(): string { + return $this->api_controller->prefix_route( '' ) . static::get_endpoint_name(); + } + + /** + * Returns the registered routes. + * + * @since 3.17.0 + * + * @return array + */ + public function get_registered_routes(): array { + return $this->registered_routes; + } + + /** + * Returns whether the endpoint is available for access by the current + * user. + * + * @since 3.14.0 Replaced `is_public_endpoint`, `user_capability` and `permission_callback()`. + * @since 3.16.0 Added the `$request` parameter. + * @since 3.17.0 Moved to the new API structure. + * + * @param WP_REST_Request|null $request The request object. + * @return WP_Error|bool True if the endpoint is available. + */ + public function is_available_to_current_user( ?WP_REST_Request $request = null ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found + // Validate the API key and secret. + $api_key_validation = $this->validate_site_id_and_secret(); + if ( is_wp_error( $api_key_validation ) ) { + return $api_key_validation; + } + + // Validate the user capability. + $capability = $this->get_default_access_capability(); + return current_user_can( + // phpcs:ignore WordPress.WP.Capabilities.Undetermined + $this->apply_capability_filters( $capability ) + ); + } + + /** + * Returns the user capability allowing access to the endpoint, after having + * applied capability filters. + * + * The default access capability is not passed here by default, to allow for + * a more explicit declaration in child classes. + * + * @since 3.14.0 + * @since 3.17.0 Moved to the new API structure. + * + * @param string $capability The original capability allowing access. + * @return string The capability allowing access after applying the filters. + */ + public function apply_capability_filters( string $capability ): string { + /** + * Filter to change the default user capability for all private endpoints. + * + * @var string + */ + $default_user_capability = apply_filters( + 'wp_parsely_user_capability_for_all_private_apis', + $capability + ); + + /** + * Filter to change the user capability for the specific endpoint. + * + * @var string + */ + $endpoint_specific_user_capability = apply_filters( + 'wp_parsely_user_capability_for_' . + Utils::convert_endpoint_to_filter_key( static::get_endpoint_name() ) . + '_api', + $default_user_capability + ); + + return $endpoint_specific_user_capability; + } + + /** + * Validates that the Site ID and secret are set. + * If the API secret is not required, it will not be validated. + * + * @since 3.13.0 + * @since 3.17.0 Moved to the new API structure and renamed from `validate_apikey_and_secret`. + * + * @param bool $require_api_secret Specifies if the API Secret is required. + * @return WP_Error|bool + */ + public function validate_site_id_and_secret( bool $require_api_secret = true ) { + if ( false === $this->parsely->site_id_is_set() ) { + return new WP_Error( + 'parsely_site_id_not_set', + __( 'A Parse.ly Site ID must be set in site options to use this endpoint', 'wp-parsely' ), + array( 'status' => 403 ) + ); + } + + if ( $require_api_secret && false === $this->parsely->api_secret_is_set() ) { + return new WP_Error( + 'parsely_api_secret_not_set', + __( 'A Parse.ly API Secret must be set in site options to use this endpoint', 'wp-parsely' ), + array( 'status' => 403 ) + ); + } + + return true; + } +} diff --git a/src/rest-api/class-rest-api-controller.php b/src/rest-api/class-rest-api-controller.php new file mode 100644 index 000000000..de83801c8 --- /dev/null +++ b/src/rest-api/class-rest-api-controller.php @@ -0,0 +1,127 @@ +get_parsely() ), + new Stats_Controller( $this->get_parsely() ), + new Settings_Controller( $this->get_parsely() ), + ); + + // Initialize the controllers. + foreach ( $controllers as $controller ) { + $controller->init(); + } + + $this->controllers = $controllers; + } + + /** + * Determines if the specified endpoint is available to the current user. + * + * @since 3.17.0 + * + * @param string $endpoint The endpoint to check. + * @return bool True if the endpoint is available to the current user, false otherwise. + */ + public function is_available_to_current_user( string $endpoint ): bool { + // Remove any forward or trailing slashes. + $endpoint = trim( $endpoint, '/' ); + + // Get the controller for the endpoint. + $controller = $this->get_controller_for_endpoint( $endpoint ); + if ( null === $controller ) { + return false; + } + + // Get the endpoint object. + $endpoint_obj = $controller->get_endpoint( $endpoint ); + if ( null === $endpoint_obj ) { + return false; + } + + // Check if the endpoint is available to the current user. + $is_available = $endpoint_obj->is_available_to_current_user(); + if ( is_wp_error( $is_available ) ) { + return false; + } + + return $is_available; + } + + /** + * Gets the controller for the specified endpoint. + * + * @since 3.17.0 + * + * @param string $endpoint The endpoint to get the controller for. + * @return Base_API_Controller|null The controller for the specified endpoint. + */ + private function get_controller_for_endpoint( string $endpoint ): ?Base_API_Controller { + foreach ( $this->controllers as $controller ) { + if ( null !== $controller->get_endpoint( $endpoint ) ) { + return $controller; + } + } + + return null; + } +} diff --git a/src/rest-api/content-helper/class-content-helper-controller.php b/src/rest-api/content-helper/class-content-helper-controller.php new file mode 100644 index 000000000..872e47c23 --- /dev/null +++ b/src/rest-api/content-helper/class-content-helper-controller.php @@ -0,0 +1,49 @@ +register_endpoints( $endpoints ); + } +} diff --git a/src/rest-api/content-helper/class-endpoint-excerpt-generator.php b/src/rest-api/content-helper/class-endpoint-excerpt-generator.php new file mode 100644 index 000000000..921a7fd43 --- /dev/null +++ b/src/rest-api/content-helper/class-endpoint-excerpt-generator.php @@ -0,0 +1,198 @@ +suggestions_api = $controller->get_parsely()->get_suggestions_api(); + } + + /** + * Returns the name of the endpoint. + * + * @since 3.17.0 + * + * @return string The endpoint name. + */ + public static function get_endpoint_name(): string { + return 'excerpt-generator'; + } + + /** + * Returns the name of the feature associated with the current endpoint. + * + * @since 3.17.0 + * + * @return string The feature name. + */ + public function get_pch_feature_name(): string { + return 'excerpt_suggestions'; + } + + /** + * Registers the routes for the endpoint. + * + * @since 3.17.0 + */ + public function register_routes(): void { + /** + * POST /excerpt-generator/generate + * Generates an excerpt for the given content. + */ + $this->register_rest_route( + 'generate', + array( 'POST' ), + array( $this, 'generate_excerpt' ), + array( + 'text' => array( + 'description' => __( 'The text to generate the excerpt from.', 'wp-parsely' ), + 'type' => 'string', + 'required' => true, + ), + 'title' => array( + 'description' => __( 'The title of the content.', 'wp-parsely' ), + 'type' => 'string', + 'required' => true, + ), + 'persona' => array( + 'description' => __( 'The persona to use for the suggestion.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + 'default' => 'journalist', + ), + 'style' => array( + 'description' => __( 'The style to use for the suggestion.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + 'default' => 'neutral', + ), + 'max_items' => array( + 'description' => __( 'The maximum number of items to generate.', 'wp-parsely' ), + 'type' => 'integer', + 'required' => false, + 'default' => 1, + ), + 'max_characters' => array( + 'description' => __( 'The maximum number of characters to generate.', 'wp-parsely' ), + 'type' => 'integer', + 'required' => false, + 'default' => 160, + ), + ) + ); + } + + /** + * API Endpoint: POST /excerpt-generator/generate + * + * Generates an excerpt for the passed content. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error The response object. + */ + public function generate_excerpt( WP_REST_Request $request ) { + /** + * The post content to be sent to the API. + * + * @var string $post_content + */ + $post_content = $request->get_param( 'text' ); + + /** + * The post title to be sent to the API. + * + * @var string $post_title + */ + $post_title = $request->get_param( 'title' ); + + /** + * The persona to be sent to the API. + * + * @var string $persona + */ + $persona = $request->get_param( 'persona' ); + + /** + * The style to be sent to the API. + * + * @var string $style + */ + $style = $request->get_param( 'style' ); + + /** + * The maximum number of items to generate. + * + * @var int $max_items + */ + $max_items = $request->get_param( 'max_items' ); + + /** + * The maximum number of characters to generate. + * + * @var int $max_characters + */ + $max_characters = $request->get_param( 'max_characters' ); + + $response = $this->suggestions_api->get_brief_suggestions( + $post_title, + $post_content, + array( + 'persona' => $persona, + 'style' => $style, + 'max_items' => $max_items, + 'max_characters' => $max_characters, + ) + ); + + if ( is_wp_error( $response ) ) { + return $response; + } + + // TODO: For now, only return the first suggestion. When the UI is ready to handle multiple suggestions, we can return the entire array. + $response = $response[0] ?? ''; + return new WP_REST_Response( array( 'data' => $response ), 200 ); + } +} diff --git a/src/Endpoints/content-helper/class-smart-linking-endpoint.php b/src/rest-api/content-helper/class-endpoint-smart-linking.php similarity index 68% rename from src/Endpoints/content-helper/class-smart-linking-endpoint.php rename to src/rest-api/content-helper/class-endpoint-smart-linking.php index d52e7e2c0..b2d45735f 100644 --- a/src/Endpoints/content-helper/class-smart-linking-endpoint.php +++ b/src/rest-api/content-helper/class-endpoint-smart-linking.php @@ -1,128 +1,139 @@ get_param( 'post_id' ); - if ( is_numeric( $temp_post_id ) ) { - $post_id = intval( $temp_post_id ); - } - } - - $can_access_pch = Permissions::current_user_can_use_pch_feature( - 'smart_linking', - $this->parsely->get_options()['content_helper'], - $post_id - ); + public function __construct( Content_Helper_Controller $controller ) { + parent::__construct( $controller ); + $this->suggestions_api = $controller->get_parsely()->get_suggestions_api(); + } - // Check if the current user has the smart linking capability. - $has_capability = current_user_can( - // phpcs:ignore WordPress.WP.Capabilities.Undetermined - $this->apply_capability_filters( - Base_Endpoint::DEFAULT_ACCESS_CAPABILITY - ) - ); + /** + * Returns the name of the endpoint. + * + * @since 3.17.0 + * + * @return string The endpoint name. + */ + public static function get_endpoint_name(): string { + return 'smart-linking'; + } - return $can_access_pch && $has_capability; + /** + * Returns the name of the feature associated with the current endpoint. + * + * @since 3.17.0 + * + * @return string The feature name. + */ + public function get_pch_feature_name(): string { + return 'smart_linking'; } /** - * Registers the endpoints. + * Registers the routes for the endpoint. * - * @since 3.16.0 + * @since 3.17.0 */ - public function run(): void { + public function register_routes(): void { /** - * POST /smart-linking/url-to-post-type - * Converts a URL to a post type. + * GET /smart-linking/generate + * Generates smart links for a post. */ - $this->register_endpoint( - static::ENDPOINT . '/url-to-post-type', - 'url_to_post_type', - array( 'POST' ) + $this->register_rest_route( + 'generate', + array( 'POST' ), + array( $this, 'generate_smart_links' ), + array( + 'text' => array( + 'required' => true, + 'type' => 'string', + 'description' => __( 'The text to generate smart links for.', 'wp-parsely' ), + ), + 'max_links' => array( + 'type' => 'integer', + 'description' => __( 'The maximum number of smart links to generate.', 'wp-parsely' ), + 'default' => 10, + ), + 'url_exclusion_list' => array( + 'type' => 'array', + 'description' => __( 'The list of URLs to exclude from the smart links.', 'wp-parsely' ), + 'validate_callback' => array( $this, 'validate_url_exclusion_list' ), + 'default' => array(), + ), + ) ); /** * GET /smart-linking/{post_id}/get * Gets the smart links for a post. */ - $this->register_endpoint_with_args( - static::ENDPOINT . '/(?P\d+)/get', - 'get_smart_links', + $this->register_rest_route_with_post_id( + '/get', array( 'GET' ), - array( - 'post_id' => array( - 'required' => true, - 'description' => __( 'The post ID.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_post_id' ), - ), - ) + array( $this, 'get_smart_links' ) ); /** * POST /smart-linking/{post_id}/add * Adds a smart link to a post. */ - $this->register_endpoint_with_args( - static::ENDPOINT . '/(?P\d+)/add', - 'add_smart_link', + $this->register_rest_route_with_post_id( + '/add', array( 'POST' ), + array( $this, 'add_smart_link' ), array( - 'post_id' => array( - 'required' => true, - 'description' => __( 'The post ID.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_post_id' ), - ), - 'link' => array( + 'link' => array( 'required' => true, - 'type' => 'array', + 'type' => 'object', 'description' => __( 'The smart link data to add.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_smart_link_params' ), + 'validate_callback' => array( $this, 'validate_smart_link_params' ), ), - 'update' => array( + 'update' => array( 'type' => 'boolean', 'description' => __( 'Whether to update the existing smart link.', 'wp-parsely' ), 'default' => false, @@ -134,23 +145,18 @@ public function run(): void { * POST /smart-linking/{post_id}/add-multiple * Adds multiple smart links to a post. */ - $this->register_endpoint_with_args( - static::ENDPOINT . '/(?P\d+)/add-multiple', - 'add_multiple_smart_links', + $this->register_rest_route_with_post_id( + '/add-multiple', array( 'POST' ), + array( $this, 'add_multiple_smart_links' ), array( - 'post_id' => array( - 'required' => true, - 'description' => __( 'The post ID.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_post_id' ), - ), - 'links' => array( + 'links' => array( 'required' => true, 'type' => 'array', 'description' => __( 'The multiple smart links data to add.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_multiple_smart_links' ), + 'validate_callback' => array( $this, 'validate_multiple_smart_links' ), ), - 'update' => array( + 'update' => array( 'type' => 'boolean', 'description' => __( 'Whether to update the existing smart links.', 'wp-parsely' ), 'default' => false, @@ -162,79 +168,84 @@ public function run(): void { * POST /smart-linking/{post_id}/set * Updates the smart links of a given post and removes the ones that are not in the request. */ - $this->register_endpoint_with_args( - static::ENDPOINT . '/(?P\d+)/set', - 'set_smart_links', + $this->register_rest_route_with_post_id( + '/set', array( 'POST' ), + array( $this, 'set_smart_links' ), array( - 'post_id' => array( - 'required' => true, - 'description' => __( 'The post ID.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_post_id' ), - ), - 'links' => array( + 'links' => array( 'required' => true, 'type' => 'array', 'description' => __( 'The smart links data to set.', 'wp-parsely' ), - 'validate_callback' => array( $this, 'private_api_request_validate_multiple_smart_links' ), + 'validate_callback' => array( $this, 'validate_multiple_smart_links' ), ), ) ); + + /** + * POST /smart-linking/url-to-post-type + * Converts a URL to a post type. + */ + $this->register_rest_route( + 'url-to-post-type', + array( 'POST' ), + array( $this, 'url_to_post_type' ) + ); } /** - * API Endpoint: POST /smart-linking/url-to-post-type. + * API Endpoint: GET /smart-linking/generate. * - * Converts a URL to a post type. + * Generates smart links for a post. * * @since 3.16.0 * * @param WP_REST_Request $request The request object. - * @return WP_REST_Response The response object. + * @return WP_REST_Response|WP_Error The response object. */ - public function url_to_post_type( WP_REST_Request $request ): WP_REST_Response { - $url = $request->get_param( 'url' ); - - if ( ! is_string( $url ) ) { - return new WP_REST_Response( - array( - 'error' => array( - 'name' => 'invalid_request', - 'message' => __( 'Invalid request body.', 'wp-parsely' ), - ), - ), - 400 - ); - } + public function generate_smart_links( WP_REST_Request $request ) { + /** + * The text to generate smart links for. + * + * @var string $post_content + */ + $post_content = $request->get_param( 'text' ); - $post_id = 0; - $cache = wp_cache_get( $url, 'wp_parsely_smart_link_url_to_postid' ); + /** + * The maximum number of smart links to generate. + * + * @var int $max_links + */ + $max_links = $request->get_param( 'max_links' ); - if ( is_integer( $cache ) ) { - $post_id = $cache; - } elseif ( function_exists( 'wpcom_vip_url_to_postid' ) ) { - $post_id = wpcom_vip_url_to_postid( $url ); - } else { - // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid - $post_id = url_to_postid( $url ); - wp_cache_set( $url, $post_id, 'wp_parsely_smart_link_url_to_postid' ); - } + /** + * The URL exclusion list. + * + * @var array $url_exclusion_list + */ + $url_exclusion_list = $request->get_param( 'url_exclusion_list' ) ?? array(); - $response = array( - 'data' => array( - 'post_id' => false, - 'post_type' => false, + $response = $this->suggestions_api->get_smart_links( + $post_content, + array( + 'max_items' => $max_links, ), + $url_exclusion_list ); - if ( 0 !== $post_id ) { - $response['data']['post_id'] = $post_id; - $response['data']['post_type'] = get_post_type( $post_id ); + if ( is_wp_error( $response ) ) { + return $response; } - return new WP_REST_Response( $response, 200 ); - } + $smart_links = array_map( + function ( Smart_Link $link ) { + return $link->to_array(); + }, + $response + ); + return new WP_REST_Response( array( 'data' => $smart_links ), 200 ); + } /** * API Endpoint: GET /smart-linking/{post_id}/get. @@ -464,35 +475,87 @@ public function set_smart_links( WP_REST_Request $request ): WP_REST_Response { return new WP_REST_Response( array( 'data' => $response ), 200 ); } + /** - * Validates the post ID parameter. + * API Endpoint: POST /smart-linking/url-to-post-type. * - * The callback sets the post object in the request object if the parameter is valid. + * Converts a URL to a post type. * * @since 3.16.0 - * @access private * - * @param string $param The parameter value. * @param WP_REST_Request $request The request object. - * @return bool Whether the parameter is valid. + * @return WP_REST_Response The response object. */ - public function private_api_request_validate_post_id( string $param, WP_REST_Request $request ): bool { - if ( ! is_numeric( $param ) ) { - return false; + public function url_to_post_type( WP_REST_Request $request ): WP_REST_Response { + $url = $request->get_param( 'url' ); + + if ( ! is_string( $url ) ) { + return new WP_REST_Response( + array( + 'error' => array( + 'name' => 'invalid_request', + 'message' => __( 'Invalid request body.', 'wp-parsely' ), + ), + ), + 400 + ); } - $param = filter_var( $param, FILTER_VALIDATE_INT ); + $post_id = 0; + $cache = wp_cache_get( $url, 'wp_parsely_smart_link_url_to_postid' ); - if ( false === $param ) { - return false; + if ( is_integer( $cache ) ) { + $post_id = $cache; + } elseif ( function_exists( 'wpcom_vip_url_to_postid' ) ) { + $post_id = wpcom_vip_url_to_postid( $url ); + } else { + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid + $post_id = url_to_postid( $url ); + wp_cache_set( $url, $post_id, 'wp_parsely_smart_link_url_to_postid' ); } - // Validate if the post ID exists. - $post = get_post( $param ); - // Set the post attribute in the request. - $request->set_param( 'post', $post ); + $response = array( + 'data' => array( + 'post_id' => false, + 'post_type' => false, + ), + ); - return null !== $post; + if ( 0 !== $post_id ) { + $response['data']['post_id'] = $post_id; + $response['data']['post_type'] = get_post_type( $post_id ); + } + + return new WP_REST_Response( $response, 200 ); + } + + /** + * Validates the URL exclusion list parameter. + * + * The callback sets the URL exclusion list in the request object if the parameter is valid. + * + * @since 3.17.0 + * @access private + * + * @param mixed $param The parameter value. + * @param WP_REST_Request $request The request object. + * @return true|WP_Error Whether the parameter is valid. + */ + public function validate_url_exclusion_list( $param, WP_REST_Request $request ) { + if ( ! is_array( $param ) ) { + return new WP_Error( 'invalid_url_exclusion_list', __( 'The URL exclusion list must be an array.', 'wp-parsely' ) ); + } + + $valid_urls = array_filter( + $param, + function ( $url ) { + return is_string( $url ) && false !== filter_var( $url, FILTER_VALIDATE_URL ); + } + ); + + $request->set_param( 'url_exclusion_list', $valid_urls ); + + return true; } /** @@ -507,7 +570,7 @@ public function private_api_request_validate_post_id( string $param, WP_REST_Req * @param WP_REST_Request $request The request object. * @return bool Whether the parameters are valid. */ - public function private_api_request_validate_smart_link_params( array $params, WP_REST_Request $request ): bool { + public function validate_smart_link_params( array $params, WP_REST_Request $request ): bool { $required_params = array( 'uid', 'href', 'title', 'text', 'offset' ); foreach ( $required_params as $param ) { @@ -566,11 +629,11 @@ public function private_api_request_validate_smart_link_params( array $params, W * @param WP_REST_Request $request The request object. * @return bool Whether the parameter is valid. */ - public function private_api_request_validate_multiple_smart_links( array $param, WP_REST_Request $request ): bool { + public function validate_multiple_smart_links( array $param, WP_REST_Request $request ): bool { $smart_links = array(); foreach ( $param as $link ) { - if ( $this->private_api_request_validate_smart_link_params( $link, $request ) ) { + if ( $this->validate_smart_link_params( $link, $request ) ) { $smart_link = $request->get_param( 'smart_link' ); $smart_links[] = $smart_link; } else { diff --git a/src/rest-api/content-helper/class-endpoint-title-suggestions.php b/src/rest-api/content-helper/class-endpoint-title-suggestions.php new file mode 100644 index 000000000..b737b7566 --- /dev/null +++ b/src/rest-api/content-helper/class-endpoint-title-suggestions.php @@ -0,0 +1,173 @@ +suggestions_api = $controller->get_parsely()->get_suggestions_api(); + } + + /** + * Returns the name of the endpoint. + * + * @since 3.17.0 + * + * @return string The endpoint name. + */ + public static function get_endpoint_name(): string { + return 'title-suggestions'; + } + + /** + * Returns the name of the feature associated with the current endpoint. + * + * @since 3.17.0 + * + * @return string + */ + public function get_pch_feature_name(): string { + return 'title_suggestions'; + } + + /** + * Registers the routes for the endpoint. + * + * @since 3.17.0 + */ + public function register_routes(): void { + /** + * POST /title-suggestions/generate + * Generates titles for the given content. + */ + $this->register_rest_route( + 'generate', + array( 'POST' ), + array( $this, 'generate_titles' ), + array( + 'text' => array( + 'description' => __( 'The content for which to generate titles.', 'wp-parsely' ), + 'required' => true, + 'type' => 'string', + ), + 'limit' => array( + 'description' => __( 'The maximum number of titles to be suggested.', 'wp-parsely' ), + 'required' => false, + 'type' => 'integer', + 'default' => 3, + ), + 'style' => array( + 'description' => __( 'The style of the titles to be suggested.', 'wp-parsely' ), + 'required' => false, + 'type' => 'string', + 'default' => 'neutral', + ), + 'persona' => array( + 'description' => __( 'The persona of the titles to be suggested.', 'wp-parsely' ), + 'required' => false, + 'type' => 'string', + 'default' => 'journalist', + ), + ) + ); + } + + /** + * API Endpoint: POST /title-suggestions/generate + * + * Generates titles for the given content. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error The response object or a WP_Error object on failure. + */ + public function generate_titles( WP_REST_Request $request ) { + /** + * The post content to be sent to the API. + * + * @var string $post_content + */ + $post_content = $request->get_param( 'text' ); + + /** + * The maximum number of titles to generate. + * + * @var int $limit + */ + $limit = $request->get_param( 'limit' ); + + /** + * The style of the titles to generate. + * + * @var string $style + */ + $style = $request->get_param( 'style' ); + + /** + * The tone of the titles to generate. + * + * @var string $persona + */ + $persona = $request->get_param( 'persona' ); + + if ( 0 === $limit ) { + $limit = 3; + } + + $response = $this->suggestions_api->get_title_suggestions( + $post_content, + array( + 'persona' => $persona, + 'style' => $style, + 'max_items' => $limit, + ) + ); + + if ( is_wp_error( $response ) ) { + return $response; + } + + return new WP_REST_Response( array( 'data' => $response ), 200 ); + } +} diff --git a/src/rest-api/content-helper/trait-content-helper-feature.php b/src/rest-api/content-helper/trait-content-helper-feature.php new file mode 100644 index 000000000..383e7c2ce --- /dev/null +++ b/src/rest-api/content-helper/trait-content-helper-feature.php @@ -0,0 +1,68 @@ +get_pch_feature_name(), + $this->parsely->get_options()['content_helper'] + ); + } + + /** + * Checks if the endpoint is available to the current user. + * + * Overrides the method in the Base_Endpoint class to check if the + * current user has permission to use the feature. + * + * @since 3.17.0 + * + * @param WP_REST_Request|null $request The request object. + * @return bool|WP_Error True if the endpoint is available. + */ + public function is_available_to_current_user( WP_REST_Request $request = null ) { + $can_use_feature = $this->is_pch_feature_enabled_for_user(); + + if ( ! $can_use_feature ) { + return new WP_Error( 'ch_access_to_feature_disabled', '', array( 'status' => 403 ) ); + } + + return parent::is_available_to_current_user( $request ); + } +} diff --git a/src/Endpoints/user-meta/class-base-endpoint-user-meta.php b/src/rest-api/settings/class-base-settings-endpoint.php similarity index 64% rename from src/Endpoints/user-meta/class-base-endpoint-user-meta.php rename to src/rest-api/settings/class-base-settings-endpoint.php index 72d1ca9e3..e4c47bf4b 100644 --- a/src/Endpoints/user-meta/class-base-endpoint-user-meta.php +++ b/src/rest-api/settings/class-base-settings-endpoint.php @@ -1,7 +1,6 @@ , default: mixed} */ -abstract class Base_Endpoint_User_Meta extends Base_Endpoint { +abstract class Base_Settings_Endpoint extends Base_Endpoint { /** * The meta entry's default value. Initialized in the constructor. * * @since 3.13.0 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @var array */ @@ -38,6 +41,7 @@ abstract class Base_Endpoint_User_Meta extends Base_Endpoint { * constructor. * * @since 3.13.0 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @var array> */ @@ -47,6 +51,7 @@ abstract class Base_Endpoint_User_Meta extends Base_Endpoint { * The current user's ID. * * @since 3.14.0 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @var int */ @@ -56,6 +61,7 @@ abstract class Base_Endpoint_User_Meta extends Base_Endpoint { * Returns the meta entry's key. * * @since 3.13.0 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @return string The meta entry's key. */ @@ -65,6 +71,7 @@ abstract protected function get_meta_key(): string; * Returns the endpoint's subvalues specifications. * * @since 3.13.0 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @return array */ @@ -74,11 +81,12 @@ abstract protected function get_subvalues_specs(): array; * Constructor. * * @since 3.13.0 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * - * @param Parsely $parsely Parsely instance. + * @param Base_API_Controller $controller The REST API controller. */ - public function __construct( Parsely $parsely ) { - parent::__construct( $parsely ); + public function __construct( Base_API_Controller $controller ) { + parent::__construct( $controller ); $subvalues_specs = $this->get_subvalues_specs(); @@ -89,109 +97,151 @@ public function __construct( Parsely $parsely ) { } /** - * Registers the endpoint's WP REST route. + * Initializes the endpoint and sets the current user ID. * - * @since 3.13.0 + * @since 3.17.0 */ - public function run(): void { - // Initialize the current user ID here, as doing it in the constructor - // is too early. + public function init(): void { + parent::init(); $this->current_user_id = get_current_user_id(); - - $this->register_endpoint( - static::get_route(), - 'process_request', - array( 'GET', 'PUT' ) - ); } /** - * Returns the endpoint's route. - * - * @since 3.13.0 + * Registers the routes for the endpoint. * - * @return string The endpoint's route. + * @since 3.17.0 */ - public static function get_route(): string { - return static::ENDPOINT; + public function register_routes(): void { + /** + * GET settings/{endpoint}/get + * Retrieves the settings for the current user. + */ + $this->register_rest_route( + '/get', + array( 'GET' ), + array( $this, 'get_settings' ) + ); + + /** + * PUT settings/{endpoint}/set + * Updates the settings for the current user. + */ + $this->register_rest_route( + '/set', + array( 'PUT' ), + array( $this, 'set_settings' ) + ); + + /** + * GET|PUT settings/{endpoint} + * Handles direct requests to the endpoint. + */ + $this->register_rest_route( + '/', + array( 'GET', 'PUT' ), + array( $this, 'process_request' ) + ); } /** - * Processes the requests sent to the endpoint. + * API Endpoint: GET|PUT settings/{endpoint}/ * - * @since 3.13.0 + * Processes the requests sent directly to the main endpoint. + * + * @since 3.17.0 * * @param WP_REST_Request $request The request sent to the endpoint. - * @return string The meta entry's value as JSON. + * @return WP_REST_Response|WP_Error The response object. */ - public function process_request( WP_REST_Request $request ): string { + public function process_request( WP_REST_Request $request ) { $request_method = $request->get_method(); // Update the meta entry's value if the request method is PUT. if ( 'PUT' === $request_method ) { - $meta_value = $request->get_json_params(); - $this->set_value( $meta_value ); + return $this->set_settings( $request ); } - return $this->get_value(); + return $this->get_settings(); } /** - * Returns whether the endpoint is available for access by the current - * user. + * API Endpoint: GET settings/{endpoint}/get * - * @since 3.14.0 - * @since 3.16.0 Added the `$request` parameter. + * Retrieves the settings for the current user. * - * @param WP_REST_Request|null $request The request object. - * @return bool - */ - public function is_available_to_current_user( $request = null ): bool { - return current_user_can( 'edit_user', $this->current_user_id ); - } - - /** - * Returns the meta entry's value as JSON. - * - * @since 3.13.0 + * @since 3.17.0 * - * @return string The meta entry's value as JSON. + * @return WP_REST_Response The response object. */ - protected function get_value(): string { - $meta_key = $this->get_meta_key(); - $meta_value = get_user_meta( $this->current_user_id, $meta_key, true ); + public function get_settings(): WP_REST_Response { + $meta_key = $this->get_meta_key(); + $settings = get_user_meta( $this->current_user_id, $meta_key, true ); - if ( ! is_array( $meta_value ) || 0 === count( $meta_value ) ) { - $meta_value = $this->default_value; + if ( ! is_array( $settings ) || 0 === count( $settings ) ) { + $settings = $this->default_value; } - $result = wp_json_encode( $meta_value ); - - return false !== $result ? $result : ''; + return new WP_REST_Response( $settings, 200 ); } /** - * Sets the meta entry's value. + * API Endpoint: PUT settings/{endpoint}/set * - * @since 3.13.0 + * Updates the settings for the current user. * - * @param array $meta_value The value to set the meta entry to. - * @return bool Whether updating the meta entry's value was successful. + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error The response object. */ - protected function set_value( array $meta_value ): bool { + public function set_settings( WP_REST_Request $request ) { + $meta_value = $request->get_json_params(); + + // Validates the settings format. + if ( ! is_array( $meta_value ) ) { // @phpstan-ignore-line + return new WP_Error( + 'ch_settings_invalid_format', + __( 'Settings must be a valid JSON array', 'wp-parsely' ) + ); + } + $sanitized_value = $this->sanitize_value( $meta_value ); + // If the current settings are the same as the new settings, return early. + $current_settings = $this->get_settings(); + if ( $current_settings->get_data() === $sanitized_value ) { + return $current_settings; + } + $update_meta = update_user_meta( $this->current_user_id, $this->get_meta_key(), $sanitized_value ); - if ( false !== $update_meta ) { - return true; + if ( false === $update_meta ) { + return new WP_Error( + 'ch_settings_update_failed', + __( 'Failed to update settings', 'wp-parsely' ) + ); } - return false; + return new WP_REST_Response( $sanitized_value, 200 ); + } + + /** + * Returns whether the endpoint is available for access by the current + * user. + * + * @since 3.14.0 + * @since 3.16.0 Added the `$request` parameter. + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. + * + * @param WP_REST_Request|null $request The request object. + * @return bool + */ + public function is_available_to_current_user( ?WP_REST_Request $request = null ): bool { + return current_user_can( 'edit_user', $this->current_user_id ); } /** @@ -199,6 +249,7 @@ protected function set_value( array $meta_value ): bool { * * @since 3.13.0 * @since 3.14.0 Added support for nested arrays. + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @param array $meta_value The meta value to sanitize. * @param string $parent_key The parent key for the current level of the meta. @@ -246,8 +297,9 @@ protected function sanitize_value( array $meta_value, string $parent_key = '' ): /** * Sanitizes the passed subvalue. * - * @since 3.14.0 Added support for nested arrays. * @since 3.13.0 + * @since 3.14.0 Added support for nested arrays. + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @param string $composite_key The subvalue's key. * @param mixed $value The value to sanitize. @@ -284,41 +336,11 @@ protected function sanitize_subvalue( string $composite_key, $value ) { return $value; } - /** - * Checks if a given composite key is valid. - * - * @since 3.14.3 - * - * @param string|mixed $composite_key The composite key representing the nested path. - * @return bool Whether the key is valid. - */ - protected function is_valid_key( $composite_key ): bool { - if ( ! is_string( $composite_key ) ) { - return false; // Key path is not a string. - } - - $keys = explode( '.', $composite_key ); - $current = $this->valid_subvalues; - - foreach ( $keys as $key ) { - if ( ! is_array( $current ) || ! isset( $current[ $key ] ) ) { - return false; // Key path is invalid. - } - - if ( isset( $current[ $key ]['values'] ) ) { - $current = $current[ $key ]['values']; - } else { - $current = $current[ $key ]; - } - } - - return true; - } - /** * Gets the valid values for a given setting path. * * @since 3.14.3 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @param array $keys The path to the setting. * @return array The valid values for the setting path. @@ -344,6 +366,7 @@ protected function get_valid_values( array $keys ): array { * Gets the default value for a given setting path. * * @since 3.14.3 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @param array $keys The path to the setting. * @return mixed|array|null The default value for the setting path. @@ -370,6 +393,7 @@ protected function get_default( array $keys ) { * Gets the specifications for nested settings based on a composite key. * * @since 3.14.3 + * @since 3.17.0 Moved from Base_Endpoint_User_Meta. * * @param string $composite_key The composite key representing the nested path. * @return array The specifications for the nested path. diff --git a/src/Endpoints/user-meta/class-dashboard-widget-settings-endpoint.php b/src/rest-api/settings/class-endpoint-dashboard-widget-settings.php similarity index 59% rename from src/Endpoints/user-meta/class-dashboard-widget-settings-endpoint.php rename to src/rest-api/settings/class-endpoint-dashboard-widget-settings.php index 32ae65efd..f23707c9b 100644 --- a/src/Endpoints/user-meta/class-dashboard-widget-settings-endpoint.php +++ b/src/rest-api/settings/class-endpoint-dashboard-widget-settings.php @@ -1,30 +1,39 @@ */ diff --git a/src/Endpoints/user-meta/class-editor-sidebar-settings-endpoint.php b/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php similarity index 78% rename from src/Endpoints/user-meta/class-editor-sidebar-settings-endpoint.php rename to src/rest-api/settings/class-endpoint-editor-sidebar-settings.php index 75de86489..850a76519 100644 --- a/src/Endpoints/user-meta/class-editor-sidebar-settings-endpoint.php +++ b/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php @@ -1,30 +1,39 @@ */ diff --git a/src/rest-api/settings/class-settings-controller.php b/src/rest-api/settings/class-settings-controller.php new file mode 100644 index 000000000..930856a66 --- /dev/null +++ b/src/rest-api/settings/class-settings-controller.php @@ -0,0 +1,47 @@ +register_endpoints( $endpoints ); + } +} diff --git a/src/rest-api/stats/class-endpoint-post.php b/src/rest-api/stats/class-endpoint-post.php new file mode 100644 index 000000000..2789d259c --- /dev/null +++ b/src/rest-api/stats/class-endpoint-post.php @@ -0,0 +1,499 @@ +content_api = $this->parsely->get_content_api(); + } + + /** + * Returns the endpoint name. + * + * @since 3.17.0 + * + * @return string The endpoint name. + */ + public static function get_endpoint_name(): string { + return 'post'; + } + + /** + * Registers the routes for the endpoint. + * + * @since 3.17.0 + */ + public function register_routes(): void { + /** + * GET /stats/post/{post_id}/details + * Returns the analytics details of a post. + */ + $this->register_rest_route_with_post_id( + '/details', + array( 'GET' ), + array( $this, 'get_post_details' ), + array_merge( + array( + 'period_start' => array( + 'description' => __( 'The start of the period.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'period_end' => array( + 'description' => __( 'The end of the period.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + ), + $this->get_itm_source_param_args() + ) + ); + + /** + * GET /stats/post/{post_id}/referrers + * Returns the referrers of a post. + */ + $this->register_rest_route_with_post_id( + '/referrers', + array( 'GET' ), + array( $this, 'get_post_referrers' ), + array( + 'period_start' => array( + 'description' => __( 'The start of the period.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'period_end' => array( + 'description' => __( 'The end of the period.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'total_views' => array( + 'description' => __( 'The total views of the post.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + 'default' => '0', + ), + ) + ); + + /** + * GET /stats/post/{post_id}/related + * Returns the related posts of a post. + */ + $this->register_rest_route_with_post_id( + '/related', + array( 'GET' ), + array( $this, 'get_related_posts' ), + $this->get_related_posts_param_args() + ); + } + + /** + * API Endpoint: GET /stats/post/{post_id}/details + * + * Gets the details of a post. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error The response object. + */ + public function get_post_details( WP_REST_Request $request ) { + /** + * The post object. + * + * @var WP_Post $post + */ + $post = $request->get_param( 'post' ); + $permalink = get_permalink( $post->ID ); + + if ( ! is_string( $permalink ) ) { + return new WP_Error( 'invalid_post', __( 'Invalid post.', 'wp-parsely' ), array( 'status' => 404 ) ); + } + + // Set the itm_source parameter. + $this->set_itm_source_from_request( $request ); + + // Get the data from the API. + $analytics_request = $this->content_api->get_post_details( + $permalink, + $request->get_param( 'period_start' ), + $request->get_param( 'period_end' ) + ); + + if ( is_wp_error( $analytics_request ) ) { + return $analytics_request; + } + + $post_data = array(); + + /** + * The analytics data object. + * + * @var array> $analytics_request + */ + foreach ( $analytics_request as $data ) { + $post_data[] = $this->extract_post_data( $data ); + } + + $response_data = array( + 'params' => $request->get_params(), + 'data' => $post_data, + ); + + return new WP_REST_Response( $response_data, 200 ); + } + + /** + * API Endpoint: GET /stats/post/{post_id}/referrers + * + * Gets the referrers of a post. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error The response object. + */ + public function get_post_referrers( WP_REST_Request $request ) { + /** + * The post object. + * + * @var WP_Post $post + */ + $post = $request->get_param( 'post' ); + $permalink = get_permalink( $post->ID ); + + if ( ! is_string( $permalink ) ) { + return new WP_Error( 'invalid_post', __( 'Invalid post.', 'wp-parsely' ), array( 'status' => 404 ) ); + } + + // Set the itm_source parameter. + $this->set_itm_source_from_request( $request ); + + // Get the total views. + $total_views = $request->get_param( 'total_views' ) ?? 0; + + if ( is_string( $total_views ) ) { + $total_views = Utils::convert_to_positive_integer( $total_views ); + } + + $this->total_views = $total_views; + + // Get the data from the API. + $analytics_request = $this->content_api->get_post_referrers( + $permalink, + $request->get_param( 'period_start' ), + $request->get_param( 'period_end' ) + ); + + if ( is_wp_error( $analytics_request ) ) { + return $analytics_request; + } + + /** + * The analytics data object. + * + * @var array $analytics_request + */ + $referrers_types = $this->generate_referrer_types_data( $analytics_request ); + $direct_views = Utils::convert_to_positive_integer( + $referrers_types['direct']['views'] ?? '0' + ); + $referrers_top = $this->generate_referrers_data( 5, $analytics_request, $direct_views ); + + $response_data = array( + 'params' => $request->get_params(), + 'data' => array( + 'top' => $referrers_top, + 'types' => $referrers_types, + ), + ); + + return new WP_REST_Response( $response_data, 200 ); + } + + /** + * API Endpoint: GET /stats/post/{post_id}/related + * + * Gets the related posts of a post. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error The response data. + */ + public function get_related_posts( WP_REST_Request $request ) { + /** + * The post object. + * + * @var WP_Post $post + */ + $post = $request->get_param( 'post' ); + + /** + * The post permalink. + * + * @var string $permalink + */ + $permalink = get_permalink( $post->ID ); + + $related_posts = $this->get_related_posts_of_url( $request, $permalink ); + + $response_data = array( + 'params' => $request->get_params(), + 'data' => $related_posts, + ); + + return new WP_REST_Response( $response_data, 200 ); + } + + /** + * Generates the referrer types data. + * + * Referrer types are: + * - `social`: Views coming from social media. + * - `search`: Views coming from search engines. + * - `other`: Views coming from other referrers, like external websites. + * - `internal`: Views coming from linking pages of the same website. + * + * Returned object properties: + * - `views`: The number of views. + * - `viewsPercentage`: The number of views as a percentage, compared to the + * total views of all referrer types. + * + * @since 3.6.0 + * @since 3.17.0 Moved from the `Referrers_Post_Detail_API_Proxy` class. + * + * @param array $response The response received by the proxy. + * @return array The generated data. + */ + private function generate_referrer_types_data( array $response ): array { + $result = array(); + $total_referrer_views = 0; // Views from all referrer types combined. + + // Set referrer type order as it is displayed in the Parse.ly dashboard. + $referrer_type_keys = array( 'social', 'search', 'other', 'internal', 'direct' ); + foreach ( $referrer_type_keys as $key ) { + $result[ $key ] = array( 'views' => 0 ); + } + + // Set views and views totals. + foreach ( $response as $referrer_data ) { + /** + * @var int $current_views + */ + $current_views = $referrer_data['metrics']['referrers_views'] ?? 0; + $total_referrer_views += $current_views; + + /** + * @var string $current_key + */ + $current_key = $referrer_data['type'] ?? ''; + if ( '' !== $current_key ) { + if ( ! isset( $result[ $current_key ]['views'] ) ) { + $result[ $current_key ] = array( 'views' => 0 ); + } + + $result[ $current_key ]['views'] += $current_views; + } + } + + // Add direct and total views to the object. + $result['direct']['views'] = $this->total_views - $total_referrer_views; + $result['totals'] = array( 'views' => $this->total_views ); + + // Remove referrer types without views. + foreach ( $referrer_type_keys as $key ) { + if ( 0 === $result[ $key ]['views'] ) { + unset( $result[ $key ] ); + } + } + + // Set percentage values and format numbers. + foreach ( $result as $key => $value ) { + // Set and format percentage values. + $result[ $key ]['viewsPercentage'] = $this->get_i18n_percentage( + absint( $value['views'] ), + $this->total_views + ); + + // Format views values. + $result[ $key ]['views'] = number_format_i18n( $result[ $key ]['views'] ); + } + + return $result; + } + + /** + * Generates the top referrers data. + * + * Returned object properties: + * - `views`: The number of views. + * - `viewsPercentage`: The number of views as a percentage, compared to the + * total views of all referrer types. + * - `datasetViewsPercentage`: The number of views as a percentage, compared + * to the total views of the current dataset. + * + * @since 3.6.0 + * @since 3.17.0 Moved from the `Referrers_Post_Detail_API_Proxy` class. + * + * @param int $limit The limit of returned referrers. + * @param array $response The response received by the proxy. + * @param int $direct_views The count of direct views. + * @return array The generated data. + */ + private function generate_referrers_data( + int $limit, + array $response, + int $direct_views + ): array { + $temp_views = array(); + $totals = 0; + $referrer_count = count( $response ); + + // Set views and views totals. + $loop_count = $referrer_count > $limit ? $limit : $referrer_count; + for ( $i = 0; $i < $loop_count; $i++ ) { + $data = $response[ $i ]; + + /** + * @var int $referrer_views + */ + $referrer_views = $data['metrics']['referrers_views'] ?? 0; + $totals += $referrer_views; + if ( isset( $data['name'] ) ) { + $temp_views[ $data['name'] ] = $referrer_views; + } + } + + // If applicable, add the direct views. + if ( isset( $referrer_views ) && $direct_views >= $referrer_views ) { + $temp_views['direct'] = $direct_views; + $totals += $direct_views; + arsort( $temp_views ); + if ( count( $temp_views ) > $limit ) { + $totals -= array_pop( $temp_views ); + } + } + + // Convert temporary array to result object and add totals. + $result = array(); + foreach ( $temp_views as $key => $value ) { + $result[ $key ] = array( 'views' => $value ); + } + $result['totals'] = array( 'views' => $totals ); + + // Set percentage values and format numbers. + foreach ( $result as $key => $value ) { + // Percentage against all referrer views, even those not included + // in the dataset due to the $limit argument. + $result[ $key ]['viewsPercentage'] = $this + ->get_i18n_percentage( absint( $value['views'] ), $this->total_views ); + + // Percentage against the current dataset that is limited due to the + // $limit argument. + $result[ $key ]['datasetViewsPercentage'] = $this + ->get_i18n_percentage( absint( $value['views'] ), $totals ); + + // Format views values. + $result[ $key ]['views'] = number_format_i18n( $result[ $key ]['views'] ); + } + + return $result; + } + + /** + * Returns the passed number compared to the passed total, in an + * internationalized percentage format. + * + * @since 3.6.0 + * @since 3.17.0 Moved from the `Referrers_Post_Detail_API_Proxy` class. + * + * @param int $number The number to be calculated as a percentage. + * @param int $total The total number to compare against. + * @return string|false The internationalized percentage or false on error. + */ + private function get_i18n_percentage( int $number, int $total ) { + if ( 0 === $total ) { + return false; + } + + return number_format_i18n( $number / $total * 100, 2 ); + } +} diff --git a/src/rest-api/stats/class-endpoint-posts.php b/src/rest-api/stats/class-endpoint-posts.php new file mode 100644 index 000000000..0671b9e5e --- /dev/null +++ b/src/rest-api/stats/class-endpoint-posts.php @@ -0,0 +1,280 @@ + + * @see https://docs.parse.ly/api-available-metrics/ + */ + public const SORT_METRICS = array( + 'views', + 'mobile_views', + 'tablet_views', + 'desktop_views', + 'visitors', + 'visitors_new', + 'visitors_returning', + 'engaged_minutes', + 'avg_engaged', + 'avg_engaged_new', + 'avg_engaged_returning', + 'social_interactions', + 'fb_interactions', + 'tw_interactions', + 'pi_interactions', + 'social_referrals', + 'fb_referrals', + 'tw_referrals', + 'pi_referrals', + 'search_refs', + ); + + /** + * The Parse.ly Content API service. + * + * @since 3.17.0 + * + * @var Content_API_Service + */ + public $content_api; + + /** + * Constructor. + * + * @since 3.17.0 + * + * @param Stats_Controller $controller The stats controller. + */ + public function __construct( Stats_Controller $controller ) { + parent::__construct( $controller ); + $this->content_api = $this->parsely->get_content_api(); + } + + /** + * Returns the endpoint name. + * + * @since 3.17.0 + * + * @return string + */ + public static function get_endpoint_name(): string { + return 'posts'; + } + + /** + * Registers the routes for the objects of the controller. + * + * @since 3.17.0 + */ + public function register_routes(): void { + /** + * GET /posts + * Retrieves posts for the given criteria. + */ + $this->register_rest_route( + '/', + array( 'GET' ), + array( $this, 'get_posts' ), + array_merge( + array( + 'period_start' => array( + 'description' => 'The start of the period to query.', + 'type' => 'string', + 'required' => false, + ), + 'period_end' => array( + 'description' => 'The end of the period to query.', + 'type' => 'string', + 'required' => false, + ), + 'pub_date_start' => array( + 'description' => 'The start of the publication date range to query.', + 'type' => 'string', + 'required' => false, + ), + 'pub_date_end' => array( + 'description' => 'The end of the publication date range to query.', + 'type' => 'string', + 'required' => false, + ), + 'limit' => array( + 'description' => 'The number of posts to return.', + 'type' => 'integer', + 'required' => false, + 'default' => self::TOP_POSTS_DEFAULT_LIMIT, + ), + 'sort' => array( + 'description' => 'The sort order of the posts.', + 'type' => 'string', + 'enum' => self::SORT_METRICS, + 'default' => self::SORT_DEFAULT, + 'required' => false, + ), + 'page' => array( + 'description' => 'The page to fetch.', + 'type' => 'integer', + 'required' => false, + 'default' => 1, + ), + 'author' => array( + 'description' => 'Comma-separated list of authors to filter by.', + 'type' => 'string', + 'required' => false, + 'validate_callback' => array( $this, 'validate_max_length_is_5' ), + 'sanitize_callback' => array( $this, 'sanitize_string_to_array' ), + ), + 'section' => array( + 'description' => 'Comma-separated list of sections to filter by.', + 'type' => 'string', + 'required' => false, + 'validate_callback' => array( $this, 'validate_max_length_is_5' ), + 'sanitize_callback' => array( $this, 'sanitize_string_to_array' ), + ), + 'tag' => array( + 'description' => 'Comma-separated list of tags to filter by.', + 'type' => 'string', + 'required' => false, + 'validate_callback' => array( $this, 'validate_max_length_is_5' ), + 'sanitize_callback' => array( $this, 'sanitize_string_to_array' ), + ), + 'segment' => array( + 'description' => 'The segment to filter by.', + 'type' => 'string', + 'required' => false, + ), + ), + $this->get_itm_source_param_args() + ) + ); + } + + /** + * Sanitizes a string to an array, splitting it by commas. + * + * @since 3.17.0 + * + * @param string|array $str The string to sanitize. + * @return array The sanitized array. + */ + public function sanitize_string_to_array( $str ): array { + if ( is_array( $str ) ) { + return $str; + } + + return explode( ',', $str ); + } + + /** + * Validates that the parameter has at most 5 items. + * + * @since 3.17.0 + * + * @param string|array $string_or_array The string or array to validate. + * @return true|WP_Error + */ + public function validate_max_length_is_5( $string_or_array ) { + if ( is_string( $string_or_array ) ) { + $string_or_array = $this->sanitize_string_to_array( $string_or_array ); + } + + if ( count( $string_or_array ) > 5 ) { + return new WP_Error( 'invalid_param', __( 'The parameter must have at most 5 items.', 'wp-parsely' ) ); + } + + return true; + } + + /** + * API Endpoint: GET /stats/posts + * + * Retrieves the posts with the given query parameters. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request. + * @return array|WP_Error|WP_REST_Response + */ + public function get_posts( WP_REST_Request $request ) { + $params = $request->get_params(); + + // Setup the itm_source if it is provided. + $this->set_itm_source_from_request( $request ); + + /** + * The raw analytics data, received by the API. + * + * @var array|WP_Error $analytics_request + */ + $analytics_request = $this->content_api->get_posts( + array( + 'period_start' => $params['period_start'] ?? null, + 'period_end' => $params['period_end'] ?? null, + 'pub_date_start' => $params['pub_date_start'] ?? null, + 'pub_date_end' => $params['pub_date_end'] ?? null, + 'limit' => $params['limit'] ?? self::TOP_POSTS_DEFAULT_LIMIT, + 'sort' => $params['sort'] ?? self::SORT_DEFAULT, + 'page' => $params['page'] ?? 1, + 'author' => $params['author'] ?? null, + 'section' => $params['section'] ?? null, + 'tag' => $params['tag'] ?? null, + 'segment' => $params['segment'] ?? null, + 'itm_source' => $params['itm_source'] ?? null, + ) + ); + + if ( is_wp_error( $analytics_request ) ) { + return $analytics_request; + } + + // Process the data. + $posts = array(); + + /** + * The analytics data object. + * + * @var array> $analytics_request + */ + foreach ( $analytics_request as $item ) { + $posts[] = $this->extract_post_data( $item ); + } + + $response_data = array( + 'params' => $params, + 'data' => $posts, + ); + + return new WP_REST_Response( $response_data, 200 ); + } +} diff --git a/src/rest-api/stats/class-endpoint-related.php b/src/rest-api/stats/class-endpoint-related.php new file mode 100644 index 000000000..1f4526c8f --- /dev/null +++ b/src/rest-api/stats/class-endpoint-related.php @@ -0,0 +1,121 @@ +content_api = $this->parsely->get_content_api(); + } + + /** + * Returns the endpoint name. + * + * @since 3.17.0 + * + * @return string + */ + public static function get_endpoint_name(): string { + return 'related'; + } + + /** + * Registers the routes for the endpoint. + * + * @since 3.17.0 + */ + public function register_routes(): void { + /** + * GET /related + * Gets related posts. + */ + $this->register_rest_route( + '/', + array( 'GET' ), + array( $this, 'get_related_posts' ), + array( + 'url' => array( + 'description' => __( 'The URL of the post.', 'wp-parsely' ), + 'type' => 'string', + 'required' => true, + ), + $this->get_related_posts_param_args(), + ) + ); + } + + /** + * API Endpoint: GET /stats/related + * + * Gets related posts for a given URL. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error + */ + public function get_related_posts( WP_REST_Request $request ) { + $url = $request->get_param( 'url' ); + + $related_posts = $this->get_related_posts_of_url( $request, $url ); + + if ( is_wp_error( $related_posts ) ) { + return $related_posts; + } + + return new WP_REST_Response( array( 'data' => $related_posts ), 200 ); + } + + /** + * Returns whether the endpoint is available for access by the current + * user. + * + * @since 3.17.0 + * + * @param WP_REST_Request|null $request The request object. + * @return bool|WP_Error + */ + public function is_available_to_current_user( ?WP_REST_Request $request = null ) { + return $this->validate_site_id_and_secret( false ); + } +} diff --git a/src/rest-api/stats/class-stats-controller.php b/src/rest-api/stats/class-stats-controller.php new file mode 100644 index 000000000..c1981984d --- /dev/null +++ b/src/rest-api/stats/class-stats-controller.php @@ -0,0 +1,48 @@ +register_endpoints( $endpoints ); + } +} diff --git a/src/rest-api/stats/trait-post-data.php b/src/rest-api/stats/trait-post-data.php new file mode 100644 index 000000000..374333c63 --- /dev/null +++ b/src/rest-api/stats/trait-post-data.php @@ -0,0 +1,146 @@ +itm_source = $source; + } + + /** + * Sets the itm_source value from the request, if it exists. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + */ + private function set_itm_source_from_request( WP_REST_Request $request ): void { + $source = $request->get_param( 'itm_source' ); + if ( null !== $source ) { + $this->set_itm_source( $source ); + } + } + + /** + * Returns the itm_source parameter arguments, to be used in the REST API + * route registration. + * + * @since 3.17.0 + * + * @return array + */ + private function get_itm_source_param_args(): array { + return array( + 'itm_source' => array( + 'description' => __( 'The source of the item.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + ); + } + + /** + * Extracts the post data from the passed object. + * + * Should only be used with endpoints that return post data. + * + * @since 3.10.0 + * @since 3.17.0 Moved from the `Base_API_Proxy` class. + * + * @param array $item The object to extract the data from. + * @return array The extracted data. + */ + protected function extract_post_data( array $item ): array { + $data = array(); + + if ( isset( $item['author'] ) ) { + $data['author'] = $item['author']; + } + + if ( isset( $item['metrics']['views'] ) ) { + $data['views'] = number_format_i18n( $item['metrics']['views'] ); + } + + if ( isset( $item['metrics']['visitors'] ) ) { + $data['visitors'] = number_format_i18n( $item['metrics']['visitors'] ); + } + + // The avg_engaged metric can be in different locations depending on the + // endpoint and passed sort/url parameters. + $avg_engaged = $item['metrics']['avg_engaged'] ?? $item['avg_engaged'] ?? null; + if ( null !== $avg_engaged ) { + $data['avgEngaged'] = Utils::get_formatted_duration( (float) $avg_engaged ); + } + + if ( isset( $item['pub_date'] ) ) { + $data['date'] = wp_date( Utils::get_date_format(), strtotime( $item['pub_date'] ) ); + } + + if ( isset( $item['title'] ) ) { + $data['title'] = $item['title']; + } + + if ( isset( $item['url'] ) ) { + $site_id = $this->parsely->get_site_id(); + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid + $post_id = url_to_postid( $item['url'] ); // 0 if the post cannot be found. + + $post_url = Parsely::get_url_with_itm_source( $item['url'], null ); + if ( Utils::parsely_is_https_supported() ) { + $post_url = str_replace( 'http://', 'https://', $post_url ); + } + + $data['rawUrl'] = $post_url; + $data['dashUrl'] = Parsely::get_dash_url( $site_id, $post_url ); + $data['id'] = Parsely::get_url_with_itm_source( $post_url, null ); // Unique. + $data['postId'] = $post_id; // Might not be unique. + $data['url'] = Parsely::get_url_with_itm_source( $post_url, $this->itm_source ); + + // Set thumbnail URL, falling back to the Parse.ly thumbnail if needed. + $thumbnail_url = get_the_post_thumbnail_url( $post_id, 'thumbnail' ); + if ( false !== $thumbnail_url ) { + $data['thumbnailUrl'] = $thumbnail_url; + } elseif ( isset( $item['thumb_url_medium'] ) ) { + $data['thumbnailUrl'] = $item['thumb_url_medium']; + } + } + + return $data; + } +} diff --git a/src/rest-api/stats/trait-related-posts.php b/src/rest-api/stats/trait-related-posts.php new file mode 100644 index 000000000..c165388de --- /dev/null +++ b/src/rest-api/stats/trait-related-posts.php @@ -0,0 +1,155 @@ + + */ + private function get_related_posts_param_args(): array { + return array_merge( + array( + 'sort' => array( + 'description' => __( 'The sort order.', 'wp-parsely' ), + 'type' => 'string', + 'enum' => array( '_score', 'pub_date' ), + 'required' => false, + 'default' => '_score', + ), + 'limit' => array( + 'description' => __( 'The number of related posts to return.', 'wp-parsely' ), + 'type' => 'integer', + 'required' => false, + 'default' => 10, + ), + 'pub_date_start' => array( + 'description' => __( 'The start of the publication date.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'pub_date_end' => array( + 'description' => __( 'The end of the publication date.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'page' => array( + 'description' => __( 'The page number.', 'wp-parsely' ), + 'type' => 'integer', + 'required' => false, + 'default' => 1, + ), + 'section' => array( + 'description' => __( 'The section of the post.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'tag' => array( + 'description' => __( 'The tag of the post.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + 'author' => array( + 'description' => __( 'The author of the post.', 'wp-parsely' ), + 'type' => 'string', + 'required' => false, + ), + ), + $this->get_itm_source_param_args() + ); + } + + /** + * Get related posts for a given URL. + * + * @since 3.17.0 + * + * @param WP_REST_Request $request The request object. + * @param string $url The URL to get related posts for. + * @return array|WP_Error + */ + public function get_related_posts_of_url( WP_REST_Request $request, string $url ) { + // Set the itm_source parameter. + $this->set_itm_source_from_request( $request ); + + /** + * The raw related posts data, received by the API. + * + * @var array>|WP_Error $related_posts_request + */ + $related_posts_request = $this->content_api->get_related_posts_with_url( + $url, + array( + 'url' => $url, + 'sort' => $request->get_param( 'sort' ), + 'limit' => $request->get_param( 'limit' ), + 'pub_date_start' => $request->get_param( 'pub_date_start' ), + 'pub_date_end' => $request->get_param( 'pub_date_end' ), + 'page' => $request->get_param( 'page' ), + 'section' => $request->get_param( 'section' ), + 'tag' => $request->get_param( 'tag' ), + 'author' => $request->get_param( 'author' ), + ) + ); + + if ( is_wp_error( $related_posts_request ) ) { + return $related_posts_request; + } + + $itm_source = $this->itm_source; + + $related_posts = array_map( + static function ( array $item ) use ( $itm_source ) { + return array( + 'image_url' => $item['image_url'], + 'thumb_url_medium' => $item['thumb_url_medium'], + 'title' => $item['title'], + 'url' => Parsely::get_url_with_itm_source( $item['url'], $itm_source ), + ); + }, + $related_posts_request + ); + + return $related_posts; + } +} diff --git a/src/rest-api/trait-use-post-id-parameter.php b/src/rest-api/trait-use-post-id-parameter.php new file mode 100644 index 000000000..39047a2f7 --- /dev/null +++ b/src/rest-api/trait-use-post-id-parameter.php @@ -0,0 +1,89 @@ + $methods The HTTP methods. + * @param callable $callback The callback function. + * @param array $args The route arguments. + */ + public function register_rest_route_with_post_id( + string $route, + array $methods, + callable $callback, + array $args = array() + ): void { + // Append the post_id parameter to the route. + $route = '/(?P\d+)/' . trim( $route, '/' ); + + // Add the post_id parameter to the args. + $args = array_merge( + $args, + array( + 'post_id' => array( + 'description' => __( 'The ID of the post.', 'wp-parsely' ), + 'type' => 'integer', + 'required' => true, + 'validate_callback' => array( $this, 'validate_post_id' ), + ), + ) + ); + + // Register the route. + $this->register_rest_route( $route, $methods, $callback, $args ); + } + + /** + * Validates the post ID parameter. + * + * The callback sets the post object in the request object if the parameter is valid. + * + * @since 3.16.0 + * @since 3.17.0 Moved from the `Smart_Linking_Endpoint` class. + * @access private + * + * @param string $param The parameter value. + * @param WP_REST_Request $request The request object. + * @return bool Whether the parameter is valid. + */ + public function validate_post_id( string $param, WP_REST_Request $request ): bool { + if ( ! is_numeric( $param ) ) { + return false; + } + + $param = filter_var( $param, FILTER_VALIDATE_INT ); + + if ( false === $param ) { + return false; + } + + // Validate if the post ID exists. + $post = get_post( $param ); + + // Set the post attribute in the request. + $request->set_param( 'post', $post ); + + return null !== $post; + } +} diff --git a/src/services/class-base-api-service.php b/src/services/class-base-api-service.php new file mode 100644 index 000000000..4a1697e68 --- /dev/null +++ b/src/services/class-base-api-service.php @@ -0,0 +1,133 @@ + + */ + protected $endpoints; + + /** + * The Parsely instance. + * + * @since 3.17.0 + * + * @var Parsely + */ + private $parsely; + + + /** + * Initializes the class. + * + * @since 3.17.0 + * + * @param Parsely $parsely The Parsely instance. + */ + public function __construct( Parsely $parsely ) { + $this->parsely = $parsely; + $this->register_endpoints(); + } + + /** + * Registers an endpoint with the service. + * + * @since 3.17.0 + * + * @param Base_Service_Endpoint $endpoint The endpoint to register. + */ + protected function register_endpoint( Base_Service_Endpoint $endpoint ): void { + $this->endpoints[ $endpoint->get_endpoint() ] = $endpoint; + } + + /** + * Registers a cached endpoint with the service. + * + * @since 3.17.0 + * + * @param Base_Service_Endpoint $endpoint The endpoint to register. + * @param int $ttl The time-to-live for the cache, in seconds. + */ + protected function register_cached_endpoint( Base_Service_Endpoint $endpoint, int $ttl ): void { + $this->endpoints[ $endpoint->get_endpoint() ] = new Cached_Service_Endpoint( $endpoint, $ttl ); + } + + /** + * Gets an endpoint by name. + * + * @since 3.17.0 + * + * @param string $endpoint The name of the endpoint. + * @return Base_Service_Endpoint The endpoint. + */ + public function get_endpoint( string $endpoint ): Base_Service_Endpoint { + return $this->endpoints[ $endpoint ]; + } + + /** + * Returns the base URL for the API service. + * + * This method should be overridden in the child class to return the base URL + * for the API service. + * + * @since 3.17.0 + * + * @return string + */ + abstract public static function get_base_url(): string; + + /** + * Registers the endpoints for the service. + * + * This method should be overridden in the child class to register the + * endpoints for the service. + * + * @since 3.17.0 + */ + abstract protected function register_endpoints(): void; + + /** + * Returns the API URL for the service. + * + * @since 3.17.0 + * + * @return string + */ + public function get_api_url(): string { + return static::get_base_url(); + } + + /** + * Returns the Parsely instance. + * + * @since 3.17.0 + * + * @return Parsely + */ + public function get_parsely(): Parsely { + return $this->parsely; + } +} diff --git a/src/services/class-base-service-endpoint.php b/src/services/class-base-service-endpoint.php new file mode 100644 index 000000000..2077c5778 --- /dev/null +++ b/src/services/class-base-service-endpoint.php @@ -0,0 +1,260 @@ +, + * body: string, + * response: array{ + * code: int|false, + * message: string|false, + * }, + * cookies: array, + * http_response: \WP_HTTP_Requests_Response|null, + * } + * + * @phpstan-import-type WP_HTTP_Request_Args from Parsely + */ +abstract class Base_Service_Endpoint { + /** + * The API service that this endpoint belongs to. + * + * @since 3.17.0 + * + * @var Base_API_Service + */ + protected $api_service; + + /** + * Flag to truncate the content of the request body. + * + * If set to true, the content of the request body will be truncated to a maximum length. + * + * @since 3.14.1 + * @since 3.17.0 Moved to the Base_Service_Endpoint class. + * + * @var bool + */ + protected const TRUNCATE_CONTENT = false; + + /** + * The maximum length of the content of the request body. + * + * @since 3.14.1 + * @since 3.17.0 Moved to the Base_Service_Endpoint class. + * + * @var int + */ + protected const TRUNCATE_CONTENT_LENGTH = 25000; + + /** + * Initializes the class. + * + * @since 3.17.0 + * + * @param Base_API_Service $api_service The API service that this endpoint belongs to. + */ + public function __construct( Base_API_Service $api_service ) { + $this->api_service = $api_service; + } + + /** + * Returns the headers to send with the request. + * + * @since 3.17.0 + * + * @return array The headers to send with the request. + */ + protected function get_headers(): array { + return array( + 'Content-Type' => 'application/json', + ); + } + + /** + * Returns the request options for the remote API request. + * + * @since 3.17.0 + * + * @param string $method The HTTP method to use for the request. + * @return WP_HTTP_Request_Args The request options for the remote API request. + */ + protected function get_request_options( string $method ): array { + $options = array( + 'headers' => $this->get_headers(), + 'method' => $method, + ); + + return $options; + } + + /** + * Returns the common query arguments to send to the remote API. + * + * This can be used for setting common query arguments that are shared + * across multiple endpoints, such as the API key. + * + * @since 3.17.0 + * + * @param array $args Additional query arguments to send to the remote API. + * @return array The query arguments to send to the remote API. + */ + protected function get_query_args( array $args = array() ): array { + return $args; + } + + /** + * Executes the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API. + */ + abstract public function call( array $args = array() ); + + /** + * Returns the endpoint for the API request. + * + * This should be the path to the endpoint, not the full URL. + * Override this method in the child class to return the endpoint. + * + * @since 3.17.0 + * + * @return string The endpoint for the API request. + */ + abstract public function get_endpoint(): string; + + /** + * Returns the full URL for the API request, including the endpoint and query arguments. + * + * @since 3.17.0 + * + * @param array $query_args The query arguments to send to the remote API. + * @return string The full URL for the API request. + */ + public function get_endpoint_url( array $query_args = array() ): string { + // Get the base URL from the API service. + $base_url = $this->api_service->get_api_url(); + + // Append the endpoint to the base URL. + $base_url .= $this->get_endpoint(); + + // Append any necessary query arguments. + $endpoint = add_query_arg( $this->get_query_args( $query_args ), $base_url ); + + return $endpoint; + } + + /** + * Sends a request to the remote API. + * + * @since 3.17.0 + * + * @param string $method The HTTP method to use for the request. + * @param array $query_args The query arguments to send to the remote API. + * @param array $data The data to send in the request body. + * @return WP_Error|array The response from the remote API. + */ + protected function request( string $method, array $query_args = array(), array $data = array() ) { + // Get the URL to send the request to. + $request_url = $this->get_endpoint_url( $query_args ); + + // Build the request options. + $request_options = $this->get_request_options( $method ); + + if ( count( $data ) > 0 ) { + if ( true === static::TRUNCATE_CONTENT ) { + $data = $this->truncate_array_content( $data ); + } + + $request_options['body'] = wp_json_encode( $data ); + if ( false === $request_options['body'] ) { + return new WP_Error( 400, __( 'Unable to encode request body', 'wp-parsely' ) ); + } + } + + /** @var WP_HTTP_Response|WP_Error $response */ + $response = wp_safe_remote_request( $request_url, $request_options ); + + return $this->process_response( $response ); + } + + /** + * Processes the response from the remote API. + * + * @since 3.17.0 + * + * @param WP_HTTP_Response|WP_Error $response The response from the remote API. + * @return array|WP_Error The processed response. + */ + protected function process_response( $response ) { + if ( is_wp_error( $response ) ) { + /** @var WP_Error $response */ + return $response; + } + + $body = wp_remote_retrieve_body( $response ); + $decoded = json_decode( $body, true ); + + if ( ! is_array( $decoded ) ) { + return new WP_Error( 400, __( 'Unable to decode upstream API response', 'wp-parsely' ) ); + } + + return $decoded; + } + + /** + * Returns the Parsely instance. + * + * @since 3.17.0 + * + * @return Parsely The Parsely instance. + */ + public function get_parsely(): Parsely { + return $this->api_service->get_parsely(); + } + + /** + * Truncates the content of an array to a maximum length. + * + * @since 3.14.1 + * @since 3.17.0 Moved to the Base_Service_Endpoint class. + * + * @param string|array|mixed $content The content to truncate. + * @return string|array|mixed The truncated content. + */ + private function truncate_array_content( $content ) { + if ( is_array( $content ) ) { + // If the content is an array, iterate over its elements. + foreach ( $content as $key => $value ) { + // Recursively process/truncate each element of the array. + $content[ $key ] = $this->truncate_array_content( $value ); + } + return $content; + } elseif ( is_string( $content ) ) { + // Check if the string length exceeds the maximum and truncate if necessary. + if ( mb_strlen( $content ) > self::TRUNCATE_CONTENT_LENGTH ) { + return mb_substr( $content, 0, self::TRUNCATE_CONTENT_LENGTH ); + } + return $content; + } + return $content; + } +} diff --git a/src/services/class-cached-service-endpoint.php b/src/services/class-cached-service-endpoint.php new file mode 100644 index 000000000..debdb63d9 --- /dev/null +++ b/src/services/class-cached-service-endpoint.php @@ -0,0 +1,165 @@ +service_endpoint = $service_endpoint; + $this->cache_ttl = $cache_ttl; + + parent::__construct( $service_endpoint->api_service ); + } + + /** + * Returns the cache key for the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return string The cache key for the API request. + */ + private function get_cache_key( array $args ): string { + $api_service = $this->service_endpoint->api_service; + + $cache_key = 'parsely_api_' . + wp_hash( $api_service->get_api_url() ) . '_' . + wp_hash( $this->get_endpoint() ) . '_' . + wp_hash( (string) wp_json_encode( $args ) ); + + return $cache_key; + } + + /** + * Executes the API request, caching the response. + * + * If the response is already cached, it will be returned from the cache, + * otherwise the API request will be made and the response will be cached. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API. + */ + public function call( array $args = array() ) { + $cache_key = $this->get_cache_key( $args ); + $cache = wp_cache_get( $cache_key, self::CACHE_GROUP ); + + if ( false !== $cache ) { + // @phpstan-ignore-next-line + return $cache; + } + + $response = $this->service_endpoint->call( $args ); + + if ( ! is_wp_error( $response ) ) { + wp_cache_set( $cache_key, $response, self::CACHE_GROUP, $this->cache_ttl ); // phpcs:ignore + } + + return $response; + } + + /** + * Returns the endpoint for the API request. + * + * @since 3.17.0 + * + * @return string The endpoint for the API request. + */ + public function get_endpoint(): string { + return $this->service_endpoint->get_endpoint(); + } + + /** + * Returns the uncached endpoint for the API request. + * + * @since 3.17.0 + * + * @return Base_Service_Endpoint The uncached endpoint for the API request. + */ + public function get_uncached_endpoint(): Base_Service_Endpoint { + return $this->service_endpoint; + } + + /** + * Returns the request options for the remote API request. + * + * Gets the request options from the uncached service endpoint. + * + * @since 3.17.0 + * + * @param string $method The HTTP method to use for the request. + * @return WP_HTTP_Request_Args The request options for the remote API request. + */ + protected function get_request_options( string $method ): array { + return $this->service_endpoint->get_request_options( $method ); + } + + /** + * Returns the common query arguments to send to the remote API. + * + * Gets the query arguments from the uncached service endpoint. + * + * @since 3.17.0 + * + * @param array $args Additional query arguments to send to the remote API. + * @return array The query arguments to send to the remote API. + */ + protected function get_query_args( array $args = array() ): array { + return $this->service_endpoint->get_query_args( $args ); + } +} diff --git a/src/services/content-api/class-content-api-service.php b/src/services/content-api/class-content-api-service.php new file mode 100644 index 000000000..83ceeb825 --- /dev/null +++ b/src/services/content-api/class-content-api-service.php @@ -0,0 +1,234 @@ + $endpoints + */ + $endpoints = array( + new Endpoints\Endpoint_Validate( $this ), + ); + + foreach ( $endpoints as $endpoint ) { + $this->register_endpoint( $endpoint ); + } + + /** + * The cached endpoints. + * + * The second element in the array is the time-to-live for the cache, in seconds. + * + * @var array $cached_endpoints + */ + $cached_endpoints = array( + array( new Endpoints\Endpoint_Analytics_Posts( $this ), 300 ), // 5 minutes. + array( new Endpoints\Endpoint_Related( $this ), 600 ), // 10 minutes. + array( new Endpoints\Endpoint_Referrers_Post_Detail( $this ), 300 ), // 5 minutes. + array( new Endpoints\Endpoint_Analytics_Post_Details( $this ), 300 ), // 5 minutes. + ); + + foreach ( $cached_endpoints as $cached_endpoint ) { + $this->register_cached_endpoint( $cached_endpoint[0], $cached_endpoint[1] ); + } + } + + /** + * Returns the post’s metadata, as well as total views and visitors in the metrics field. + * + * By default, this returns the total pageviews on the link for the last 90 days. + * + * @since 3.17.0 + * + * @link https://docs.parse.ly/api-analytics-endpoint/#2-get-analytics-post-detail + * + * @param string $url The URL of the post. + * @param string|null $period_start The start date of the period to get the data for. + * @param string|null $period_end The end date of the period to get the data for. + * @return array|WP_Error Returns the post details or a WP_Error object in case of an error. + */ + public function get_post_details( + string $url, + string $period_start = null, + string $period_end = null + ) { + /** @var Endpoints\Endpoint_Analytics_Post_Details $endpoint */ + $endpoint = $this->get_endpoint( '/analytics/post/detail' ); + + $args = array( + 'url' => $url, + 'period_start' => $period_start, + 'period_end' => $period_end, + ); + + return $endpoint->call( $args ); + } + + /** + * Returns the referrers for a given post URL. + * + * @since 3.17.0 + * + * @link https://docs.parse.ly/api-referrers-endpoint/#3-get-referrers-post-detail + * + * @param string $url The URL of the post. + * @param string|null $period_start The start date of the period to get the data for. + * @param string|null $period_end The end date of the period to get the data for. + * @return array|WP_Error Returns the referrers or a WP_Error object in case of an error. + */ + public function get_post_referrers( + string $url, + string $period_start = null, + string $period_end = null + ) { + /** @var Endpoints\Endpoint_Referrers_Post_Detail $endpoint */ + $endpoint = $this->get_endpoint( '/referrers/post/detail' ); + + $args = array( + 'url' => $url, + 'period_start' => $period_start, + 'period_end' => $period_end, + ); + + return $endpoint->call( $args ); + } + + /** + * Returns the related posts for a given URL. + * + * @since 3.17.0 + * + * @link https://docs.parse.ly/content-recommendations/#h-get-related + * + * @param string $url The URL of the post. + * @param array $params The parameters to pass to the API request. + * @return array|WP_Error Returns the related posts or a WP_Error object in case of an error. + */ + public function get_related_posts_with_url( string $url, array $params = array() ) { + /** @var Endpoints\Endpoint_Related $endpoint */ + $endpoint = $this->get_endpoint( '/related' ); + + $args = array( + 'url' => $url, + ); + + // Merge the optional params. + $args = array_merge( $params, $args ); + + return $endpoint->call( $args ); + } + + /** + * Returns the related posts for a given UUID. + * + * @since 3.17.0 + * + * @link https://docs.parse.ly/content-recommendations/#h-get-related + * + * @param string $uuid The UUID of the user. + * @param array $params The parameters to pass to the API request. + * @return array|WP_Error Returns the related posts or a WP_Error object in case of an error. + */ + public function get_related_posts_with_uuid( string $uuid, array $params = array() ) { + /** @var Endpoints\Endpoint_Related $endpoint */ + $endpoint = $this->get_endpoint( '/related' ); + + $args = array( + 'uuid' => $uuid, + ); + + // Merge the optional params. + $args = array_merge( $params, $args ); + + return $endpoint->call( $args ); + } + + /** + * Returns the posts analytics. + * + * @since 3.17.0 + * + * @link https://docs.parse.ly/api-analytics-endpoint/#1-get-analytics-posts + * + * @param array $params The parameters to pass to the API request. + * @return array|WP_Error Returns the posts analytics or a WP_Error object in case of an error. + */ + public function get_posts( array $params = array() ) { + /** @var Endpoints\Endpoint_Analytics_Posts $endpoint */ + $endpoint = $this->get_endpoint( '/analytics/posts' ); + + return $endpoint->call( $params ); + } + + /** + * Validates the Parse.ly API credentials. + * + * The API will return a 200 response if the credentials are valid and a 401 response if they are not. + * + * @since 3.17.0 + * + * @param string $api_key The API key to validate. + * @param string $secret_key The secret key to validate. + * @return bool|WP_Error Returns true if the credentials are valid, false otherwise. + */ + public function validate_credentials( string $api_key, string $secret_key ) { + /** @var Endpoints\Endpoint_Validate $endpoint */ + $endpoint = $this->get_endpoint( '/validate/secret' ); + + $args = array( + 'apikey' => $api_key, + 'secret' => $secret_key, + ); + + $response = $endpoint->call( $args ); + + if ( is_wp_error( $response ) ) { + /** @var WP_Error $response */ + return $response; + } + + if ( true === $response['success'] ) { + return true; + } + + return false; + } +} diff --git a/src/services/content-api/endpoints/class-content-api-base-endpoint.php b/src/services/content-api/endpoints/class-content-api-base-endpoint.php new file mode 100644 index 000000000..4a4692fac --- /dev/null +++ b/src/services/content-api/endpoints/class-content-api-base-endpoint.php @@ -0,0 +1,89 @@ +, + * } + * + * @phpstan-type Content_API_Error_Response array{ + * code?: int, + * message?: string, + * } + * + * @phpstan-type Content_API_Response = Content_API_Valid_Response|Content_API_Error_Response + * + * @phpstan-import-type WP_HTTP_Response from Base_Service_Endpoint + */ +abstract class Content_API_Base_Endpoint extends Base_Service_Endpoint { + /** + * Returns the common query arguments to send to the remote API. + * + * This method append the API key and secret to the query arguments. + * + * @since 3.17.0 + * + * @param array $args Additional query arguments to send to the remote API. + * @return array The query arguments to send to the remote API. + */ + protected function get_query_args( array $args = array() ): array { + $query_args = parent::get_query_args( $args ); + + // Set up the API key and secret. + $query_args['apikey'] = $this->get_parsely()->get_site_id(); + if ( $this->get_parsely()->api_secret_is_set() ) { + $query_args['secret'] = $this->get_parsely()->get_api_secret(); + } + + return $query_args; + } + + /** + * Processes the response from the remote API. + * + * @since 3.17.0 + * + * @param WP_HTTP_Response|WP_Error $response The response from the remote API. + * @return array|WP_Error The processed response. + */ + protected function process_response( $response ) { + $response = parent::process_response( $response ); + + if ( is_wp_error( $response ) ) { + /** @var WP_Error $response */ + return $response; + } + + if ( ! isset( $response['data'] ) ) { + /** @var Content_API_Error_Response $response */ + return new WP_Error( + $response['code'] ?? 400, + $response['message'] ?? __( 'Unable to read data from upstream API', 'wp-parsely' ), + array( 'status' => $response['code'] ?? 400 ) + ); + } + + if ( ! is_array( $response['data'] ) ) { + return new WP_Error( 400, __( 'Unable to parse data from upstream API', 'wp-parsely' ) ); + } + + /** @var Content_API_Valid_Response $response */ + return $response['data']; + } +} diff --git a/src/services/content-api/endpoints/class-endpoint-analytics-post-details.php b/src/services/content-api/endpoints/class-endpoint-analytics-post-details.php new file mode 100644 index 000000000..54d26d3ae --- /dev/null +++ b/src/services/content-api/endpoints/class-endpoint-analytics-post-details.php @@ -0,0 +1,54 @@ + $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API request. + */ + public function call( array $args = array() ) { + $query_args = array( + 'url' => $args['url'], + 'period_start' => $args['period_start'], + 'period_end' => $args['period_end'], + ); + + // Filter out the empty values. + $query_args = array_filter( $query_args ); + + return $this->request( 'GET', $query_args ); + } +} diff --git a/src/services/content-api/endpoints/class-endpoint-analytics-posts.php b/src/services/content-api/endpoints/class-endpoint-analytics-posts.php new file mode 100644 index 000000000..b8ebc6168 --- /dev/null +++ b/src/services/content-api/endpoints/class-endpoint-analytics-posts.php @@ -0,0 +1,182 @@ +, + * } + * + * @phpstan-type Analytics_Post array{ + * title?: string, + * url?: string, + * link?: string, + * author?: string, + * authors?: string[], + * section?: string, + * tags?: string[], + * metrics?: Analytics_Post_Metrics, + * full_content_word_count?: int, + * image_url?: string, + * metadata?: string, + * pub_date?: string, + * thumb_url_medium?: string, + * } + * + * @phpstan-type Analytics_Post_Metrics array{ + * avg_engaged?: float, + * views?: int, + * visitors?: int, + * } + */ +class Endpoint_Analytics_Posts extends Content_API_Base_Endpoint { + private const MAX_RECORDS_LIMIT = 2000; + private const ANALYTICS_API_DAYS_LIMIT = 7; + + /** + * Maximum limit for the number of records to return, to be + * used in the limit parameter. + * + * @since 3.17.0 + * + * @var string + */ + public const MAX_LIMIT = 'max'; + + /** + * Maximum period for the API request, to be used in the period_start parameter. + * + * @since 3.17.0 + * + * @var string + */ + public const MAX_PERIOD = 'max_days'; + + /** + * Returns the endpoint for the API request. + * + * @since 3.17.0 + * + * @return string + */ + public function get_endpoint(): string { + return '/analytics/posts'; + } + + /** + * Returns the endpoint URL for the API request. + * + * This method appends the author, tag, and section parameters to the + * endpoint URL, if they are set. Since the Parse.ly API needs a key for + * every value (e.g. tag=tag1&tag=tag2), we need to append them manually. + * + * @since 3.17.0 + * + * @param array $query_args The arguments to pass to the API request. + * @return string The endpoint URL for the API request. + */ + public function get_endpoint_url( array $query_args = array() ): string { + // Store the author, tag, and section parameters. + /** @var array $authors */ + $authors = $query_args['author'] ?? array(); + + /** @var array $tags */ + $tags = $query_args['tag'] ?? array(); + + /** @var array $sections */ + $sections = $query_args['section'] ?? array(); + + // Remove the author, tag, and section parameters from the query args. + unset( $query_args['author'] ); + unset( $query_args['tag'] ); + unset( $query_args['section'] ); + + // Generate the endpoint URL. + $endpoint_url = parent::get_endpoint_url( $query_args ); + + // Append the author, tag, and section parameters to the endpoint URL. + $endpoint_url = $this->append_multiple_params_to_url( $endpoint_url, $authors, 'author' ); + $endpoint_url = $this->append_multiple_params_to_url( $endpoint_url, $tags, 'tag' ); + $endpoint_url = $this->append_multiple_params_to_url( $endpoint_url, $sections, 'section' ); + + return $endpoint_url; + } + + /** + * Executes the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API request. + */ + public function call( array $args = array() ) { + // Filter out the empty values. + $query_args = array_filter( $args ); + + // If the period_start is set to 'max_days', set it to the maximum days limit. + if ( isset( $query_args['period_start'] ) && self::MAX_PERIOD === $query_args['period_start'] ) { + $query_args['period_start'] = self::ANALYTICS_API_DAYS_LIMIT . 'd'; + } + + // If the limit is set to 'max' or greater than the maximum records limit, + // set it to the maximum records limit. + if ( isset( $query_args['limit'] ) && ( + self::MAX_LIMIT === $query_args['limit'] || $query_args['limit'] > self::MAX_RECORDS_LIMIT ) + ) { + $query_args['limit'] = self::MAX_RECORDS_LIMIT; + } + + return $this->request( 'GET', $query_args ); + } + + + /** + * Appends multiple parameters to the URL. + * + * This is required because the Parsely API requires the multiple values for the author, tag, + * and section parameters to share the same key. + * + * @since 3.17.0 + * + * @param string $url The URL to append the parameters to. + * @param array $params The parameters to append. + * @param string $param_name The name of the parameter. + * @return string The URL with the appended parameters. + */ + protected function append_multiple_params_to_url( string $url, array $params, string $param_name ): string { + foreach ( $params as $param ) { + $param = rawurlencode( $param ); + if ( strpos( $url, $param_name . '=' ) === false ) { + $url = add_query_arg( $param_name, $param, $url ); + } else { + $url .= '&' . $param_name . '=' . $param; + } + } + + return $url; + } +} diff --git a/src/services/content-api/endpoints/class-endpoint-referrers-post-detail.php b/src/services/content-api/endpoints/class-endpoint-referrers-post-detail.php new file mode 100644 index 000000000..1c233fedd --- /dev/null +++ b/src/services/content-api/endpoints/class-endpoint-referrers-post-detail.php @@ -0,0 +1,54 @@ + $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API request. + */ + public function call( array $args = array() ) { + $query_args = array( + 'url' => $args['url'], + 'period_start' => $args['period_start'], + 'period_end' => $args['period_end'], + ); + + // Filter out the empty values. + $query_args = array_filter( $query_args ); + + return $this->request( 'GET', $query_args ); + } +} diff --git a/src/services/content-api/endpoints/class-endpoint-related.php b/src/services/content-api/endpoints/class-endpoint-related.php new file mode 100644 index 000000000..cd547ae84 --- /dev/null +++ b/src/services/content-api/endpoints/class-endpoint-related.php @@ -0,0 +1,53 @@ + $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API request. + */ + public function call( array $args = array() ) { + // Filter out the empty values. + $args = array_filter( $args ); + + // When the URL is provided, the UUID cannot be provided. + if ( isset( $args['uuid'] ) && isset( $args['url'] ) ) { + unset( $args['uuid'] ); + } + + return $this->request( 'GET', $args ); + } +} diff --git a/src/services/content-api/endpoints/class-endpoint-validate.php b/src/services/content-api/endpoints/class-endpoint-validate.php new file mode 100644 index 000000000..8167c837d --- /dev/null +++ b/src/services/content-api/endpoints/class-endpoint-validate.php @@ -0,0 +1,112 @@ + $args The query arguments to send to the remote API. + * @return array The query arguments for the API request. + */ + public function get_query_args( array $args = array() ): array { + return $args; + } + + /** + * Queries the Parse.ly API credentials validation endpoint. + * + * The API will return a 200 response if the credentials are valid and a 403 + * response if they are not. + * + * @since 3.17.0 + * + * @param string $api_key The API key to validate. + * @param string $secret_key The secret key to validate. + * @return array|WP_Error The response from the remote API, or a WP_Error object if the response is an error. + */ + private function api_validate_credentials( string $api_key, string $secret_key ) { + $query = array( + 'apikey' => $api_key, + 'secret' => $secret_key, + ); + + $response = $this->request( 'GET', $query ); + + if ( is_wp_error( $response ) ) { + return $response; + } + + if ( false === $response['success'] ) { + return new WP_Error( + $response['code'] ?? 403, + $response['message'] ?? __( 'Unable to validate the API credentials', 'wp-parsely' ) + ); + } + + return $response; + } + + /** + * Processes the response from the remote API. + * + * @since 3.17.0 + * + * @param WP_HTTP_Response|WP_Error $response The response from the remote API. + * @return array|WP_Error The processed response. + */ + protected function process_response( $response ) { + return Base_Service_Endpoint::process_response( $response ); + } + + /** + * Executes the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API request. + */ + public function call( array $args = array() ) { + /** @var string $api_key */ + $api_key = $args['apikey']; + /** @var string $secret */ + $secret = $args['secret']; + + return $this->api_validate_credentials( $api_key, $secret ); + } +} diff --git a/src/services/suggestions-api/class-suggestions-api-service.php b/src/services/suggestions-api/class-suggestions-api-service.php new file mode 100644 index 000000000..8f7245467 --- /dev/null +++ b/src/services/suggestions-api/class-suggestions-api-service.php @@ -0,0 +1,115 @@ +register_endpoint( $endpoint ); + } + } + + /** + * Gets the first brief (meta description) for a given content using the + * Parse.ly Content Suggestion API. + * + * @since 3.13.0 + * @since 3.17.0 Updated to use the new API service. + * + * @param string $title The title of the content. + * @param string $content The query arguments to send to the remote API. + * @param Endpoint_Suggest_Brief_Options $options The options to pass to the API request. + * @return array|WP_Error The response from the remote API, or a WP_Error + * object if the response is an error. + */ + public function get_brief_suggestions( string $title, string $content, $options = array() ) { + /** @var Endpoints\Endpoint_Suggest_Brief $endpoint */ + $endpoint = $this->get_endpoint( '/suggest-brief' ); + + return $endpoint->get_suggestion( $title, $content, $options ); + } + + /** + * Gets titles (headlines) for a given content using the Parse.ly Content + * Suggestion API. + * + * @since 3.13.0 + * @since 3.17.0 Updated to use the new API service. + * + * @param string $content The query arguments to send to the remote API. + * @param Endpoint_Suggest_Headline_Options $options The options to pass to the API request. + * @return array|WP_Error The response from the remote API, or a WP_Error + * object if the response is an error. + */ + public function get_title_suggestions( string $content, $options = array() ) { + /** @var Endpoints\Endpoint_Suggest_Headline $endpoint */ + $endpoint = $this->get_endpoint( '/suggest-headline' ); + + return $endpoint->get_headlines( $content, $options ); + } + + /** + * Gets suggested smart links for the given content. + * + * @since 3.14.0 + * @since 3.17.0 Updated to use the new API service. + * + * @param string $content The content to generate links for. + * @param Endpoint_Suggest_Linked_Reference_Options $options The options to pass to the API request. + * @param array $url_exclusion_list A list of URLs to exclude from the suggestions. + * + * @return array|WP_Error The response from the remote API, or a WP_Error + * object if the response is an error. + */ + public function get_smart_links( string $content, $options = array(), array $url_exclusion_list = array() ) { + /** @var Endpoints\Endpoint_Suggest_Linked_Reference $endpoint */ + $endpoint = $this->get_endpoint( '/suggest-linked-reference' ); + + return $endpoint->get_links( $content, $options, $url_exclusion_list ); + } +} diff --git a/src/services/suggestions-api/endpoints/class-endpoint-suggest-brief.php b/src/services/suggestions-api/endpoints/class-endpoint-suggest-brief.php new file mode 100644 index 000000000..8e0d3a20c --- /dev/null +++ b/src/services/suggestions-api/endpoints/class-endpoint-suggest-brief.php @@ -0,0 +1,93 @@ +|WP_Error The response from the remote API, or a WP_Error + * object if the response is an error. + */ + public function get_suggestion( + string $title, + string $content, + $options = array() + ) { + $request_body = array( + 'output_config' => array( + 'persona' => $options['persona'] ?? 'journalist', + 'style' => $options['style'] ?? 'neutral', + 'max_characters' => $options['max_characters'] ?? 160, + 'max_items' => $options['max_items'] ?? 1, + ), + 'title' => $title, + 'text' => wp_strip_all_tags( $content ), + ); + + /** @var array|WP_Error $response */ + $response = $this->request( 'POST', array(), $request_body ); + + return $response; + } + + /** + * Executes the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API. + */ + public function call( array $args = array() ) { + /** @var string $title */ + $title = $args['title'] ?? ''; + /** @var string $content */ + $content = $args['content'] ?? ''; + /** @var Endpoint_Suggest_Brief_Options $options */ + $options = $args['options'] ?? array(); + + return $this->get_suggestion( $title, $content, $options ); + } +} diff --git a/src/services/suggestions-api/endpoints/class-endpoint-suggest-headline.php b/src/services/suggestions-api/endpoints/class-endpoint-suggest-headline.php new file mode 100644 index 000000000..09b3e7c27 --- /dev/null +++ b/src/services/suggestions-api/endpoints/class-endpoint-suggest-headline.php @@ -0,0 +1,96 @@ + + * } + */ +class Endpoint_Suggest_Headline extends Suggestions_API_Base_Endpoint { + /** + * Returns the endpoint for the API request. + * + * @since 3.17.0 + * + * @return string The endpoint for the API request. + */ + public function get_endpoint(): string { + return '/suggest-headline'; + } + + /** + * Gets titles (headlines) for a given content using the Parse.ly Content + * Suggestion API. + * + * @since 3.13.0 + * @since 3.17.0 Updated to use the new API service. + * + * @param string $content The query arguments to send to the remote API. + * @param Endpoint_Suggest_Headline_Options $options The options to pass to the API request. + * @return array|WP_Error The response from the remote API, or a WP_Error + * object if the response is an error. + */ + public function get_headlines( + string $content, + $options = array() + ) { + $request_body = array( + 'output_config' => array( + 'persona' => $options['persona'] ?? 'journalist', + 'style' => $options['style'] ?? 'neutral', + 'max_items' => $options['max_items'] ?? 1, + ), + 'text' => wp_strip_all_tags( $content ), + ); + + /** @var array|WP_Error $response */ + $response = $this->request( 'POST', array(), $request_body ); + + return $response; + } + + /** + * Executes the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API. + */ + public function call( array $args = array() ) { + /** @var string $title */ + $title = $args['title'] ?? ''; + /** @var string $content */ + $content = $args['content'] ?? ''; + /** @var Endpoint_Suggest_Headline_Options $options */ + $options = $args['options'] ?? array(); + + return $this->get_headlines( $content, $options ); + } +} diff --git a/src/services/suggestions-api/endpoints/class-endpoint-suggest-linked-reference.php b/src/services/suggestions-api/endpoints/class-endpoint-suggest-linked-reference.php new file mode 100644 index 000000000..cb27e628b --- /dev/null +++ b/src/services/suggestions-api/endpoints/class-endpoint-suggest-linked-reference.php @@ -0,0 +1,117 @@ + + * } + */ +class Endpoint_Suggest_Linked_Reference extends Suggestions_API_Base_Endpoint { + /** + * Returns the endpoint for the API request. + * + * @since 3.17.0 + * + * @return string The endpoint for the API request. + */ + public function get_endpoint(): string { + return '/suggest-linked-reference'; + } + + /** + * Gets suggested smart links for the given content using the Parse.ly + * Content Suggestion API. + * + * @since 3.14.0 + * @since 3.17.0 Updated to use the new API service. + * + * @param string $content The content to generate links for. + * @param Endpoint_Suggest_Linked_Reference_Options $options The options to pass to the API request. + * @param array $url_exclusion_list A list of URLs to exclude from the suggestions. + * @return array|WP_Error The response from the remote API, or a WP_Error + * object if the response is an error. + */ + public function get_links( + string $content, + $options = array(), + array $url_exclusion_list = array() + ) { + $request_body = array( + 'output_config' => array( + 'max_link_words' => $options['max_link_words'] ?? 4, + 'max_items' => $options['max_items'] ?? 10, + ), + 'text' => wp_strip_all_tags( $content ), + ); + + if ( count( $url_exclusion_list ) > 0 ) { + $request_body['url_exclusion_list'] = $url_exclusion_list; + } + + $response = $this->request( 'POST', array(), $request_body ); + + if ( is_wp_error( $response ) ) { + return $response; + } + + // Convert the links to Smart_Link objects. + $links = array(); + foreach ( $response as $link ) { + $link = apply_filters( 'wp_parsely_suggest_linked_reference_link', $link ); + $link_obj = new Smart_Link( + esc_url( $link['canonical_url'] ), + esc_attr( $link['title'] ), + wp_kses_post( $link['text'] ), + $link['offset'] + ); + $links[] = $link_obj; + } + + return $links; + } + + /** + * Executes the API request. + * + * @since 3.17.0 + * + * @param array $args The arguments to pass to the API request. + * @return WP_Error|array The response from the API. + */ + public function call( array $args = array() ) { + /** @var string $content */ + $content = $args['content'] ?? ''; + /** @var Endpoint_Suggest_Linked_Reference_Options $options */ + $options = $args['options'] ?? array(); + /** @var string[] $url_exclusion_list */ + $url_exclusion_list = $args['url_exclusion_list'] ?? array(); + + return $this->get_links( $content, $options, $url_exclusion_list ); + } +} diff --git a/src/services/suggestions-api/endpoints/class-suggestions-api-base-endpoint.php b/src/services/suggestions-api/endpoints/class-suggestions-api-base-endpoint.php new file mode 100644 index 000000000..79c7e2cb3 --- /dev/null +++ b/src/services/suggestions-api/endpoints/class-suggestions-api-base-endpoint.php @@ -0,0 +1,123 @@ + $method, + 'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ), + 'data_format' => 'body', + 'timeout' => 60, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout + 'body' => '{}', + ); + + // Add API key to request headers. + if ( $this->get_parsely()->api_secret_is_set() ) { + $options['headers']['X-APIKEY-SECRET'] = $this->get_parsely()->get_api_secret(); + } + + return $options; + } + + /** + * Returns the common query arguments to send to the remote API. + * + * This method appends the API key and secret to the query arguments. + * + * @since 3.17.0 + * + * @param array $args Additional query arguments to send to the remote API. + * @return array The query arguments to send to the remote API. + */ + protected function get_query_args( array $args = array() ): array { + $query_args = parent::get_query_args( $args ); + + // Set up the API key and secret. + $query_args['apikey'] = $this->get_parsely()->get_site_id(); + + return $query_args; + } + + /** + * Processes the response from the remote API. + * + * @since 3.17.0 + * + * @param WP_HTTP_Response|WP_Error $response The response from the remote API. + * @return array|WP_Error The processed response. + */ + protected function process_response( $response ) { + if ( is_wp_error( $response ) ) { + /** @var WP_Error $response */ + return $response; + } + + // Handle any errors returned by the API. + if ( 200 !== $response['response']['code'] ) { + $error = json_decode( wp_remote_retrieve_body( $response ), true ); + + if ( ! is_array( $error ) ) { + return new WP_Error( + 400, + __( 'Unable to decode upstream API error', 'wp-parsely' ) + ); + } + + return new WP_Error( $error['error'], $error['detail'] ); + } + + $body = wp_remote_retrieve_body( $response ); + $decoded = json_decode( $body, true ); + + if ( ! is_array( $decoded ) ) { + return new WP_Error( 400, __( 'Unable to decode upstream API response', 'wp-parsely' ) ); + } + + if ( ! is_array( $decoded['result'] ) ) { + return new WP_Error( 400, __( 'Unable to parse data from upstream API', 'wp-parsely' ) ); + } + + return $decoded['result']; + } +} diff --git a/tests/Integration/ContentHelper/ContentHelperDashboardWidgetTest.php b/tests/Integration/ContentHelper/ContentHelperDashboardWidgetTest.php index cfb9f5d8e..7109879c3 100644 --- a/tests/Integration/ContentHelper/ContentHelperDashboardWidgetTest.php +++ b/tests/Integration/ContentHelper/ContentHelperDashboardWidgetTest.php @@ -11,16 +11,48 @@ use Parsely\Content_Helper\Dashboard_Widget; use Parsely\Parsely; +use Parsely\Tests\Integration\TestCase; /** * Integration Tests for the PCH Dashboard Widget. */ final class ContentHelperDashboardWidgetTest extends ContentHelperFeatureTest { + /** + * Internal variable. + * + * @since 3.17.0 + * + * @var Parsely $parsely Holds the Parsely object. + */ + private static $parsely; + /** * Setup method called before each test. + * + * @since 3.17.0 */ public function set_up(): void { - $GLOBALS['parsely'] = new Parsely(); + parent::set_up(); + + self::$parsely = new Parsely(); + self::$parsely->get_rest_api_controller()->init(); + + TestCase::set_options( + array( + 'apikey' => 'test_apikey', + 'api_secret' => 'test_secret', + ) + ); + } + + /** + * Teardown method called after each test. + * + * @since 3.17.0 + */ + public function tear_down(): void { + parent::tear_down(); + TestCase::set_options(); } /** @@ -44,8 +76,8 @@ protected function assert_enqueued_status( string $user_role, array $additional_args = array() ): void { - $feature = new Dashboard_Widget( $GLOBALS['parsely'] ); - $this->set_current_user_to( $user_login, $user_role ); + $feature = new Dashboard_Widget( self::$parsely ); + self::set_current_user_to( $user_login, $user_role ); parent::set_filters( $feature::get_feature_filter_name(), @@ -85,11 +117,8 @@ protected function assert_enqueued_status( * @covers \Parsely\Content_Helper\Dashboard_Widget::get_script_id * @covers \Parsely\Content_Helper\Dashboard_Widget::get_style_id * @covers \Parsely\Content_Helper\Dashboard_Widget::run - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info * * @group content-helper */ @@ -112,11 +141,9 @@ public function test_assets_do_not_get_enqueued_when_user_has_not_enough_capabil * @covers \Parsely\Content_Helper\Dashboard_Widget::get_script_id * @covers \Parsely\Content_Helper\Dashboard_Widget::get_style_id * @covers \Parsely\Content_Helper\Dashboard_Widget::run - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ diff --git a/tests/Integration/ContentHelper/ContentHelperFeatureTest.php b/tests/Integration/ContentHelper/ContentHelperFeatureTest.php index 977a968ba..45f4700c5 100644 --- a/tests/Integration/ContentHelper/ContentHelperFeatureTest.php +++ b/tests/Integration/ContentHelper/ContentHelperFeatureTest.php @@ -61,7 +61,7 @@ protected function assert_enqueued_status_default( string $user_login, string $user_role ): void { - $this->set_current_user_to( $user_login, $user_role ); + self::set_current_user_to( $user_login, $user_role ); self::set_filters( $feature::get_feature_filter_name(), @@ -172,7 +172,6 @@ protected static function deregister_feature_assets_and_run( * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_credentials_not_set_message * @uses \Parsely\Content_Helper\Content_Helper_Feature::inject_inline_scripts - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -184,7 +183,7 @@ protected static function deregister_feature_assets_and_run( * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -229,7 +228,6 @@ public function test_assets_get_enqueued_by_default(): void { * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_credentials_not_set_message * @uses \Parsely\Content_Helper\Content_Helper_Feature::inject_inline_scripts - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -241,7 +239,7 @@ public function test_assets_get_enqueued_by_default(): void { * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -277,7 +275,6 @@ public function test_assets_get_enqueued_when_global_filter_is_true(): void { * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -286,7 +283,7 @@ public function test_assets_get_enqueued_when_global_filter_is_true(): void { * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -322,7 +319,6 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_false(): v * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -331,7 +327,7 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_false(): v * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -377,7 +373,6 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_invalid(): * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_credentials_not_set_message * @uses \Parsely\Content_Helper\Content_Helper_Feature::inject_inline_scripts - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -389,7 +384,7 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_invalid(): * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -425,7 +420,6 @@ public function test_assets_get_enqueued_when_feature_filter_is_true(): void { * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -434,7 +428,7 @@ public function test_assets_get_enqueued_when_feature_filter_is_true(): void { * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -470,7 +464,6 @@ public function test_assets_do_not_get_enqueued_when_feature_filter_is_false(): * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -479,7 +472,7 @@ public function test_assets_do_not_get_enqueued_when_feature_filter_is_false(): * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -524,7 +517,6 @@ public function test_assets_do_not_get_enqueued_when_feature_filter_is_invalid() * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_credentials_not_set_message * @uses \Parsely\Content_Helper\Content_Helper_Feature::inject_inline_scripts - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -536,7 +528,7 @@ public function test_assets_do_not_get_enqueued_when_feature_filter_is_invalid() * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -579,7 +571,6 @@ public function test_assets_get_enqueued_when_both_filters_are_true(): void { * @covers \Parsely\Content_Helper\Post_List_Stats::is_tracked_as_post_type * @covers \Parsely\Content_Helper\Post_List_Stats::run * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -588,7 +579,7 @@ public function test_assets_get_enqueued_when_both_filters_are_true(): void { * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -624,7 +615,6 @@ public function test_assets_do_not_get_enqueued_when_both_filters_are_false(): v * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -633,7 +623,7 @@ public function test_assets_do_not_get_enqueued_when_both_filters_are_false(): v * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -669,7 +659,6 @@ public function test_assets_do_not_get_enqueued_when_both_filters_are_invalid(): * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -678,7 +667,7 @@ public function test_assets_do_not_get_enqueued_when_both_filters_are_invalid(): * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -723,7 +712,6 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_true_and_f * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_credentials_not_set_message * @uses \Parsely\Content_Helper\Content_Helper_Feature::inject_inline_scripts - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -735,7 +723,7 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_true_and_f * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -772,7 +760,6 @@ public function test_assets_get_enqueued_when_global_filter_is_false_and_feature * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -781,7 +768,7 @@ public function test_assets_get_enqueued_when_global_filter_is_false_and_feature * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ @@ -826,7 +813,6 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_true_and_f * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_credentials_not_set_message * @uses \Parsely\Content_Helper\Content_Helper_Feature::inject_inline_scripts - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::allow_parsely_remote_requests * @uses \Parsely\Parsely::api_secret_is_set @@ -838,7 +824,7 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_true_and_f * @uses \Parsely\Parsely::set_managed_options * @uses \Parsely\Parsely::site_id_is_set * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @uses \Parsely\Utils::get_asset_info + * @uses \Parsely\Utils\Utils::get_asset_info * * @group content-helper */ diff --git a/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php b/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php index 7ea57fc8c..276d27c37 100644 --- a/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php +++ b/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php @@ -12,8 +12,10 @@ use Mockery; use Parsely\Content_Helper\Post_List_Stats; use Parsely\Parsely; -use Parsely\RemoteAPI\Analytics_Posts_API; +use Parsely\Services\Content_API\Content_API_Service; +use Parsely\Services\Content_API\Endpoints\Endpoint_Analytics_Posts; use Parsely\Tests\Integration\TestCase; +use ReflectionProperty; use WP_Error; use WP_Post; use WP_Scripts; @@ -23,11 +25,17 @@ * * @since 3.7.0 * - * @phpstan-import-type Analytics_Post_API_Params from Analytics_Posts_API - * @phpstan-import-type Analytics_Post from Analytics_Posts_API + * @phpstan-import-type Analytics_Post from Endpoint_Analytics_Posts * @phpstan-import-type Parsely_Posts_Stats_Response from Post_List_Stats */ final class ContentHelperPostListStatsTest extends ContentHelperFeatureTest { + /** + * The Parsely instance. + * + * @var Parsely + */ + private static $parsely; + /** * Internal variable. * @@ -51,6 +59,9 @@ final class ContentHelperPostListStatsTest extends ContentHelperFeatureTest { public function set_up(): void { parent::set_up(); + self::$parsely = new Parsely(); + self::$parsely->get_rest_api_controller()->init(); + $this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%' ); $this->set_current_user_to_admin(); } @@ -85,7 +96,7 @@ protected function assert_enqueued_status( string $user_role, array $additional_args = array() ): void { - $this->set_current_user_to( $user_login, $user_role ); + self::set_current_user_to( $user_login, $user_role ); parent::set_filters( Post_List_Stats::get_feature_filter_name(), @@ -121,13 +132,11 @@ protected function assert_enqueued_status( * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user * @covers \Parsely\Utils\Utils::convert_endpoint_to_filter_key * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::api_secret_is_set * @uses \Parsely\Parsely::get_options * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * * @group content-helper */ @@ -150,13 +159,11 @@ public function test_assets_do_not_get_enqueued_when_user_has_not_enough_capabil * @covers \Parsely\Content_Helper\Post_List_Stats::is_tracked_as_post_type * @covers \Parsely\Content_Helper\Post_List_Stats::run * @covers \Parsely\Content_Helper\Post_List_Stats::set_current_screen - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user * @covers \Parsely\Utils\Utils::convert_endpoint_to_filter_key * @uses \Parsely\Parsely::__construct * @uses \Parsely\Parsely::api_secret_is_set * @uses \Parsely\Parsely::get_options * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Endpoints\Base_Endpoint::__construct * * @group content-helper */ @@ -754,7 +761,7 @@ public function test_script_of_parsely_stats_admin_column_on_valid_posts_and_val * @return Post_List_Stats */ private function mock_parsely_stats_response( ?array $return_value ): Post_List_Stats { - $obj = Mockery::mock( Post_List_Stats::class, array( new Parsely() ) )->makePartial(); + $obj = Mockery::mock( Post_List_Stats::class, array( self::$parsely ) )->makePartial(); $obj->shouldReceive( 'get_parsely_stats_response' )->once()->andReturn( $return_value ); $obj->run(); @@ -785,7 +792,7 @@ public function test_should_not_call_parsely_api_on_empty_api_secret_and_hidden_ * @return Post_List_Stats */ private function mock_is_parsely_stats_column_hidden( bool $return_value = false ): Post_List_Stats { - $obj = Mockery::mock( Post_List_Stats::class, array( new Parsely() ) )->makePartial(); + $obj = Mockery::mock( Post_List_Stats::class, array( self::$parsely ) )->makePartial(); $obj->shouldReceive( 'is_parsely_stats_column_hidden' )->once()->andReturn( $return_value ); $obj->run(); @@ -1251,7 +1258,7 @@ public function test_parsely_stats_response_on_valid_hierarchal_post_type_and_ha * @param array $posts Available Posts. * @param string $post_type Type of the post. * @param array|WP_Error|null $api_response Mocked response that we return on calling API. - * @param Analytics_Post_API_Params|null $api_params API Parameters. + * @param array|null $api_params API Parameters. * @return Parsely_Posts_Stats_Response|null */ private function get_parsely_stats_response( @@ -1266,9 +1273,13 @@ private function get_parsely_stats_response( $this->show_content_on_parsely_stats_column( $posts, $post_type ); ob_get_clean(); // Discard output to keep console clean while running tests. - $api = Mockery::mock( Analytics_Posts_API::class, array( new Parsely() ) )->makePartial(); + if ( null === $api_response ) { + $api_response = self::$parsely_api_empty_response; + } + + $api = Mockery::mock( Content_API_Service::class, array( self::$parsely ) )->makePartial(); if ( ! is_null( $api_params ) ) { - $api->shouldReceive( 'get_posts_analytics' ) + $api->shouldReceive( 'get_posts' ) ->once() ->withArgs( array( @@ -1276,8 +1287,8 @@ private function get_parsely_stats_response( $api_params, // Params which will not change. array( - 'period_start' => Analytics_Posts_API::ANALYTICS_API_DAYS_LIMIT . 'd', - 'limit' => 2000, + 'period_start' => Endpoint_Analytics_Posts::MAX_PERIOD, + 'limit' => Endpoint_Analytics_Posts::MAX_LIMIT, 'sort' => 'avg_engaged', ) ), @@ -1285,10 +1296,15 @@ private function get_parsely_stats_response( ) ->andReturn( $api_response ); } else { - $api->shouldReceive( 'get_posts_analytics' )->once()->andReturn( $api_response ); + $api->shouldReceive( 'get_posts' )->once()->andReturn( $api_response ); } - return $obj->get_parsely_stats_response( $api ); + // Replace the original API with the mock, using reflection. + $api_reflection = new ReflectionProperty( $obj, 'content_api' ); + $api_reflection->setAccessible( true ); + $api_reflection->setValue( $obj, $api ); + + return $obj->get_parsely_stats_response(); } /** @@ -1309,7 +1325,7 @@ private function assert_hooks_for_parsely_stats_response( $assert_type = true ): * @return Post_List_Stats */ private function init_post_list_stats(): Post_List_Stats { - $obj = new Post_List_Stats( new Parsely() ); + $obj = new Post_List_Stats( self::$parsely ); $obj->run(); return $obj; diff --git a/tests/Integration/Endpoints/Proxy/AnalyticsPostsProxyEndpointTest.php b/tests/Integration/Endpoints/Proxy/AnalyticsPostsProxyEndpointTest.php deleted file mode 100644 index b0a7c366b..000000000 --- a/tests/Integration/Endpoints/Proxy/AnalyticsPostsProxyEndpointTest.php +++ /dev/null @@ -1,264 +0,0 @@ -dispatch( - new WP_REST_Request( 'GET', self::$route ) - ); - /** - * Variable. - * - * @var WP_Error - */ - $error = $response->as_error(); - - self::assertSame( 401, $response->get_status() ); - self::assertSame( 'rest_forbidden', $error->get_error_code() ); - self::assertSame( - 'Sorry, you are not allowed to do that.', - $error->get_error_message() - ); - } - - /** - * Verifies that calling `GET /wp-parsely/v1/stats/posts` returns an - * error and does not perform a remote call when the Site ID is not populated - * in site options. - * - * @covers \Parsely\Endpoints\Analytics_Posts_API_Proxy::get_items - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::__construct - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::run - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - */ - public function test_get_items_fails_when_site_id_is_not_set(): void { - $this->set_current_user_to_admin(); - parent::run_test_get_items_fails_without_site_id_set(); - } - - /** - * Verifies that calling `GET /wp-parsely/v1/stats/posts` returns an - * error and does not perform a remote call when the API Secret is not - * populated in site options. - * - * @covers \Parsely\Endpoints\Analytics_Posts_API_Proxy::get_items - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::__construct - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::run - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - */ - public function test_get_items_fails_when_api_secret_is_not_set(): void { - $this->set_current_user_to_admin(); - parent::run_test_get_items_fails_without_api_secret_set(); - } - - /** - * Verifies default user capability filter. - * - * @covers \Parsely\Endpoints\Analytics_Posts_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user - */ - public function test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(): void { - parent::run_test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(); - } - - /** - * Verifies endpoint specific user capability filter. - * - * @covers \Parsely\Endpoints\Analytics_Posts_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user - */ - public function test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed(): void { - parent::run_test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed( 'analytics_posts' ); - } - - /** - * Verifies that calls to `GET /wp-parsely/v1/stats/posts` return - * results in the expected format. - * - * @covers \Parsely\Endpoints\Analytics_Posts_API_Proxy::get_items - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::__construct - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::generate_data - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Analytics_Posts_API_Proxy::run - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_site_id - * @uses \Parsely\Parsely::get_api_secret - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_api_url - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_items - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_request_options - */ - public function test_get_items(): void { - $this->set_current_user_to_admin(); - TestCase::set_options( - array( - 'apikey' => 'example.com', - 'api_secret' => 'test', - ) - ); - - $dispatched = 0; - $date_format = Utils::get_date_format(); - - add_filter( - 'pre_http_request', - function () use ( &$dispatched ): array { - $dispatched++; - return array( - 'body' => '{"data":[ - { - "author": "Aakash Shah", - "metrics": {"views": 142}, - "pub_date": "2020-04-06T13:30:58", - "thumb_url_medium": "https://images.parsely.com/XCmTXuOf8yVbUYTxj2abQ4RSDkM=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/06/Web-Analytics-Tool.png%3Fw%3D150%26h%3D150%26crop%3D1", - "title": "9 Types of Web Analytics Tools \u2014 And How to Know Which Ones You Really Need", - "url": "https://blog.parse.ly/web-analytics-software-tools/?itm_source=parsely-api" - }, - { - "author": "Stephanie Schwartz and Andrew Butler", - "metrics": {"views": 40}, - "pub_date": "2021-04-30T20:30:24", - "thumb_url_medium": "https://images.parsely.com/ap3YSufqxnLpz6zzQshoks3snXI=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/05/pexels-brett-jordan-998501-1024x768-2.jpeg%3Fw%3D150%26h%3D150%26crop%3D1", - "title": "5 Tagging Best Practices For Getting the Most Out of Your Content Strategy", - "url": "https://blog.parse.ly/5-tagging-best-practices-content-strategy/?itm_source=parsely-api" - } - ]}', - ); - } - ); - - $rest_request = new WP_REST_Request( 'GET', '/wp-parsely/v1/stats/posts' ); - $rest_request->set_param( 'itm_source', 'wp-parsely-content-helper' ); - - $response = rest_get_server()->dispatch( $rest_request ); - - self::assertSame( 1, $dispatched ); - self::assertSame( 200, $response->get_status() ); - self::assertEquals( - (object) array( - 'data' => array( - (object) array( - 'author' => 'Aakash Shah', - 'date' => wp_date( $date_format, strtotime( '2020-04-06T13:30:58' ) ), - 'id' => 'https://blog.parse.ly/web-analytics-software-tools/', - 'dashUrl' => PARSELY::DASHBOARD_BASE_URL . '/example.com/find?url=https%3A%2F%2Fblog.parse.ly%2Fweb-analytics-software-tools%2F', - 'thumbnailUrl' => 'https://images.parsely.com/XCmTXuOf8yVbUYTxj2abQ4RSDkM=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/06/Web-Analytics-Tool.png%3Fw%3D150%26h%3D150%26crop%3D1', - 'title' => '9 Types of Web Analytics Tools — And How to Know Which Ones You Really Need', - 'url' => 'https://blog.parse.ly/web-analytics-software-tools/?itm_source=wp-parsely-content-helper', - 'views' => '142', - 'postId' => 0, - 'rawUrl' => 'https://blog.parse.ly/web-analytics-software-tools/', - ), - (object) array( - 'author' => 'Stephanie Schwartz and Andrew Butler', - 'date' => wp_date( $date_format, strtotime( '2021-04-30T20:30:24' ) ), - 'id' => 'https://blog.parse.ly/5-tagging-best-practices-content-strategy/', - 'dashUrl' => PARSELY::DASHBOARD_BASE_URL . '/example.com/find?url=https%3A%2F%2Fblog.parse.ly%2F5-tagging-best-practices-content-strategy%2F', - 'thumbnailUrl' => 'https://images.parsely.com/ap3YSufqxnLpz6zzQshoks3snXI=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/05/pexels-brett-jordan-998501-1024x768-2.jpeg%3Fw%3D150%26h%3D150%26crop%3D1', - 'title' => '5 Tagging Best Practices For Getting the Most Out of Your Content Strategy', - 'url' => 'https://blog.parse.ly/5-tagging-best-practices-content-strategy/?itm_source=wp-parsely-content-helper', - 'views' => '40', - 'postId' => 0, - 'rawUrl' => 'https://blog.parse.ly/5-tagging-best-practices-content-strategy/', - ), - ), - ), - $response->get_data() - ); - } -} diff --git a/tests/Integration/Endpoints/Proxy/BaseProxyEndpointTest.php b/tests/Integration/Endpoints/Proxy/BaseProxyEndpointTest.php deleted file mode 100644 index 208e0abaa..000000000 --- a/tests/Integration/Endpoints/Proxy/BaseProxyEndpointTest.php +++ /dev/null @@ -1,245 +0,0 @@ -wp_rest_server_global_backup = $GLOBALS['wp_rest_server'] ?? null; - $endpoint = $this->get_endpoint(); - $this->rest_api_init_proxy = static function () use ( $endpoint ) { - $endpoint->run(); - }; - add_action( 'rest_api_init', $this->rest_api_init_proxy ); - } - - /** - * Teardown method called after each test. - * - * Resets globals. - */ - public function tear_down(): void { - parent::tear_down(); - remove_action( 'rest_api_init', $this->rest_api_init_proxy ); - - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound - $GLOBALS['wp_rest_server'] = $this->wp_rest_server_global_backup; - } - - /** - * Verifies that the route is registered. - * - * @param array $methods The methods supported by the route. - */ - public function run_test_register_routes_by_default( - array $methods = array( 'GET' => true ) - ): void { - $routes = rest_get_server()->get_routes(); - self::assertArrayHasKey( self::$route, $routes ); - self::assertCount( 1, $routes[ self::$route ] ); - self::assertSame( $methods, $routes[ self::$route ][0]['methods'] ); - } - - /** - * Verifies that the route is not registered when the respective filter is - * set to false. - */ - public function run_test_do_not_register_route_when_proxy_is_disabled(): void { - // Override some setup steps in order to set the filter to false. - remove_action( 'rest_api_init', $this->rest_api_init_proxy ); - $endpoint = $this->get_endpoint(); - $this->rest_api_init_proxy = static function () use ( $endpoint ) { - add_filter( 'wp_parsely_enable_' . self::$filter_key . '_api_proxy', '__return_false' ); - $endpoint->run(); - }; - add_action( 'rest_api_init', $this->rest_api_init_proxy ); - - $routes = rest_get_server()->get_routes(); - self::assertFalse( array_key_exists( self::$route, $routes ) ); - } - - /** - * Verifies that calls return an error and do not perform a remote call when - * the Site ID is not populated in site options. - * - * @param WP_REST_Request|null $request The request object to be used. - */ - public function run_test_get_items_fails_without_site_id_set( - ?WP_REST_Request $request = null - ): void { - $this->run_test_get_items_fails( - array( 'apikey' => '' ), - 'parsely_site_id_not_set', - 'A Parse.ly Site ID must be set in site options to use this endpoint', - $request - ); - } - - /** - * Verifies that calls return an error and do not perform a remote call when - * the API Secret is not populated in site options. - * - * @param WP_REST_Request|null $request The request object to be used. - */ - public function run_test_get_items_fails_without_api_secret_set( - ?WP_REST_Request $request = null - ): void { - $this->run_test_get_items_fails( - array( - 'apikey' => 'example.com', - 'api_secret' => '', - ), - 'parsely_api_secret_not_set', - 'A Parse.ly API Secret must be set in site options to use this endpoint', - $request - ); - } - - /** - * Verifies that attempting to get items under the given conditions will - * fail. - * - * @param array $options The WordPress options to be set. - * @param string $expected_error_code The expected error code. - * @param string $expected_error_message The expected error message. - * @param WP_REST_Request|null $request The request object to be used. - */ - private function run_test_get_items_fails( - array $options, - string $expected_error_code, - string $expected_error_message, - ?WP_REST_Request $request = null - ): void { - TestCase::set_options( $options ); - if ( null === $request ) { - $request = new WP_REST_Request( 'GET', self::$route ); - } - - $response = rest_get_server()->dispatch( $request ); - /** - * Variable. - * - * @var WP_Error - */ - $error = $response->as_error(); - self::assertSame( 403, $response->get_status() ); - self::assertSame( $expected_error_code, $error->get_error_code() ); - self::assertSame( $expected_error_message, $error->get_error_message() ); - } - - /** - * Verifies default user capability filter. - */ - public function run_test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(): void { - $this->set_current_user_to_contributor(); - add_filter( - 'wp_parsely_user_capability_for_all_private_apis', - function () { - return 'edit_posts'; - } - ); - - self::assertTrue( static::get_endpoint()->is_available_to_current_user() ); - } - - /** - * Verifies endpoint specific user capability filter. - * - * @param string|null $filter_key The key to use for the filter. - */ - public function run_test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed( - $filter_key = null - ): void { - $this->set_current_user_to_contributor(); - $filter_key = $filter_key ?? static::$filter_key; - - add_filter( - 'wp_parsely_user_capability_for_' . $filter_key . '_api', - function () { - return 'edit_posts'; - } - ); - - self::assertTrue( static::get_endpoint()->is_available_to_current_user() ); - } -} diff --git a/tests/Integration/Endpoints/Proxy/ReferrersPostDetailProxyEndpointTest.php b/tests/Integration/Endpoints/Proxy/ReferrersPostDetailProxyEndpointTest.php deleted file mode 100644 index 38ec499a4..000000000 --- a/tests/Integration/Endpoints/Proxy/ReferrersPostDetailProxyEndpointTest.php +++ /dev/null @@ -1,305 +0,0 @@ -set_current_user_to_admin(); - parent::run_test_get_items_fails_without_site_id_set(); - } - - /** - * Verifies that calling `GET /wp-parsely/v1/referrers/post/detail` returns - * an error and does not perform a remote call when the Site ID is not - * populated in site options. - * - * @covers \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::get_items - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::__construct - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::run - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - */ - public function test_get_items_fails_when_api_secret_is_not_set(): void { - $this->set_current_user_to_admin(); - parent::run_test_get_items_fails_without_api_secret_set(); - } - - /** - * Verifies default user capability filter. - * - * @covers \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Referrers_Post_Detail_API::is_available_to_current_user - */ - public function test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(): void { - parent::run_test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(); - } - - /** - * Verifies endpoint specific user capability filter. - * - * @covers \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Referrers_Post_Detail_API::is_available_to_current_user - */ - public function test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed(): void { - parent::run_test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed(); - } - - /** - * Verifies that calls to `GET /wp-parsely/v1/referrers/post/detail` return - * results in the expected format. - * - * @covers \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::get_items - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::__construct - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::generate_data - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Referrers_Post_Detail_API_Proxy::run - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_site_id - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_api_url - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_items - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_request_options - */ - public function test_get_items(): void { - $this->set_current_user_to_admin(); - TestCase::set_options( - array( - 'apikey' => 'example.com', - 'api_secret' => 'test', - ) - ); - - $dispatched = 0; - - add_filter( - 'pre_http_request', - function () use ( &$dispatched ): array { - $dispatched++; - return array( - 'body' => '{"data":[ - { - "metrics": {"referrers_views": 1500}, - "name": "google", - "type": "search" - }, - { - "metrics": {"referrers_views": 100}, - "name": "blog.parse.ly", - "type": "internal" - }, - { - "metrics": {"referrers_views": 50}, - "name": "bing", - "type": "search" - }, - { - "metrics": {"referrers_views": 30}, - "name": "facebook.com", - "type": "social" - }, - { - "metrics": {"referrers_views": 10}, - "name": "okt.to", - "type": "other" - }, - { - "metrics": {"referrers_views": 10}, - "name": "yandex", - "type": "search" - }, - { - "metrics": {"referrers_views": 10}, - "name": "parse.ly", - "type": "internal" - }, - { - "metrics": {"referrers_views": 10}, - "name": "yahoo!", - "type": "search" - }, - { - "metrics": {"referrers_views": 5}, - "name": "site1.com", - "type": "other" - }, - { - "metrics": {"referrers_views": 5}, - "name": "link.site2.com", - "type": "other" - } - ]}', - ); - } - ); - - $expected_top = (object) array( - 'direct' => (object) array( - 'views' => '770', - 'viewsPercentage' => '30.80', - 'datasetViewsPercentage' => '31.43', - ), - 'google' => (object) array( - 'views' => '1,500', - 'viewsPercentage' => '60.00', - 'datasetViewsPercentage' => '61.22', - ), - 'blog.parse.ly' => (object) array( - 'views' => '100', - 'viewsPercentage' => '4.00', - 'datasetViewsPercentage' => '4.08', - ), - 'bing' => (object) array( - 'views' => '50', - 'viewsPercentage' => '2.00', - 'datasetViewsPercentage' => '2.04', - ), - 'facebook.com' => (object) array( - 'views' => '30', - 'viewsPercentage' => '1.20', - 'datasetViewsPercentage' => '1.22', - ), - 'totals' => (object) array( - 'views' => '2,450', - 'viewsPercentage' => '98.00', - 'datasetViewsPercentage' => '100.00', - ), - ); - - $expected_types = (object) array( - 'social' => (object) array( - 'views' => '30', - 'viewsPercentage' => '1.20', - ), - 'search' => (object) array( - 'views' => '1,570', - 'viewsPercentage' => '62.80', - ), - 'other' => (object) array( - 'views' => '20', - 'viewsPercentage' => '0.80', - ), - 'internal' => (object) array( - 'views' => '110', - 'viewsPercentage' => '4.40', - ), - 'direct' => (object) array( - 'views' => '770', - 'viewsPercentage' => '30.80', - ), - 'totals' => (object) array( - 'views' => '2,500', - 'viewsPercentage' => '100.00', - ), - ); - - $request = new WP_REST_Request( 'GET', self::$route ); - $request->set_param( 'total_views', '2,500' ); - - $response = rest_get_server()->dispatch( $request ); - - self::assertSame( 1, $dispatched ); - self::assertSame( 200, $response->get_status() ); - self::assertEquals( - (object) array( - 'data' => array( - 'top' => $expected_top, - 'types' => $expected_types, - ), - ), - $response->get_data() - ); - } -} diff --git a/tests/Integration/Endpoints/Proxy/RelatedProxyEndpointTest.php b/tests/Integration/Endpoints/Proxy/RelatedProxyEndpointTest.php deleted file mode 100644 index 7584fa597..000000000 --- a/tests/Integration/Endpoints/Proxy/RelatedProxyEndpointTest.php +++ /dev/null @@ -1,162 +0,0 @@ - 'example.com' ) ); - - $dispatched = 0; - - add_filter( - 'pre_http_request', - function () use ( &$dispatched ): array { - $dispatched++; - return array( - 'body' => '{"data":[ - { - "image_url":"https:\/\/example.com\/img.png", - "thumb_url_medium":"https:\/\/example.com\/thumb.png", - "title":"something", - "url":"https:\/\/example.com" - }, - { - "image_url":"https:\/\/example.com\/img2.png", - "thumb_url_medium":"https:\/\/example.com\/thumb2.png", - "title":"something2", - "url":"https:\/\/example.com\/2" - } - ]}', - ); - } - ); - - $response = rest_get_server()->dispatch( new WP_REST_Request( 'GET', '/wp-parsely/v1/related' ) ); - - self::assertSame( 1, $dispatched ); - self::assertSame( 200, $response->get_status() ); - self::assertEquals( - (object) array( - 'data' => array( - (object) array( - 'image_url' => 'https://example.com/img.png', - 'thumb_url_medium' => 'https://example.com/thumb.png', - 'title' => 'something', - 'url' => 'https://example.com', - ), - (object) array( - 'image_url' => 'https://example.com/img2.png', - 'thumb_url_medium' => 'https://example.com/thumb2.png', - 'title' => 'something2', - 'url' => 'https://example.com/2', - ), - ), - ), - $response->get_data() - ); - } -} diff --git a/tests/Integration/Endpoints/Proxy/StatsPostDetailProxyEndpointTest.php b/tests/Integration/Endpoints/Proxy/StatsPostDetailProxyEndpointTest.php deleted file mode 100644 index c442d098a..000000000 --- a/tests/Integration/Endpoints/Proxy/StatsPostDetailProxyEndpointTest.php +++ /dev/null @@ -1,206 +0,0 @@ -set_current_user_to_admin(); - parent::run_test_get_items_fails_without_site_id_set(); - } - - /** - * Verifies that calling `GET /wp-parsely/v1/analytics/post/detail` returns - * an error and does not perform a remote call when the Site ID is not - * populated in site options. - * - * @covers \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::get_items - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::__construct - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::run - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - */ - public function test_get_items_fails_when_api_secret_is_not_set(): void { - $this->set_current_user_to_admin(); - parent::run_test_get_items_fails_without_api_secret_set(); - } - - /** - * Verifies default user capability filter. - * - * @covers \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - */ - public function test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(): void { - parent::run_test_user_is_allowed_to_make_proxy_api_call_if_default_user_capability_is_changed(); - } - - /** - * Verifies endpoint specific user capability filter. - * - * @covers \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - */ - public function test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed(): void { - parent::run_test_user_is_allowed_to_make_proxy_api_call_if_endpoint_specific_user_capability_is_changed( 'analytics_post_detail' ); - } - - /** - * Verifies that calls to `GET /wp-parsely/v1/analytics/post/detail` return - * results in the expected format. - * - * @covers \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::get_items - * @uses \Parsely\Endpoints\Base_API_Proxy::get_data - * @uses \Parsely\Endpoints\Base_API_Proxy::register_endpoint - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::__construct - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::generate_data - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::is_available_to_current_user - * @uses \Parsely\Endpoints\Analytics_Post_Detail_API_Proxy::run - * @uses \Parsely\Parsely::site_id_is_missing - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_site_id - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_api_url - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_items - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_request_options - */ - public function test_get_items(): void { - $this->set_current_user_to_admin(); - TestCase::set_options( - array( - 'apikey' => 'example.com', - 'api_secret' => 'test', - ) - ); - - $dispatched = 0; - - add_filter( - 'pre_http_request', - function () use ( &$dispatched ): array { - $dispatched++; - return array( - 'body' => ' - {"data":[{ - "avg_engaged": 1.911, - "metrics": { - "views": 2158, - "visitors": 1537 - }, - "url": "https://example.com" - }]} - ', - ); - } - ); - - $response = rest_get_server()->dispatch( new WP_REST_Request( 'GET', '/wp-parsely/v1/stats/post/detail' ) ); - - self::assertSame( 1, $dispatched ); - self::assertSame( 200, $response->get_status() ); - self::assertEquals( - (object) array( - 'data' => array( - (object) array( - 'avgEngaged' => '1:55', - 'dashUrl' => Parsely::DASHBOARD_BASE_URL . '/example.com/find?url=https%3A%2F%2Fexample.com', - 'id' => 'https://example.com', - 'postId' => 0, - 'url' => 'https://example.com', - 'views' => '2,158', - 'visitors' => '1,537', - 'rawUrl' => 'https://example.com', - ), - ), - ), - $response->get_data() - ); - } -} diff --git a/tests/Integration/Endpoints/RestMetadataTest.php b/tests/Integration/Endpoints/RestMetadataTest.php index 226e1071c..23854b34c 100644 --- a/tests/Integration/Endpoints/RestMetadataTest.php +++ b/tests/Integration/Endpoints/RestMetadataTest.php @@ -14,7 +14,6 @@ use Parsely\Endpoints\Rest_Metadata; use Parsely\Tests\Integration\TestCase; - /** * Integration Tests for the REST API Metadata Endpoint. */ diff --git a/tests/Integration/Endpoints/UserMeta/BaseUserMetaEndpointTest.php b/tests/Integration/Endpoints/UserMeta/BaseUserMetaEndpointTest.php deleted file mode 100644 index c2ad8ec40..000000000 --- a/tests/Integration/Endpoints/UserMeta/BaseUserMetaEndpointTest.php +++ /dev/null @@ -1,169 +0,0 @@ - - */ - protected $default_value = array(); - - /** - * Generates a JSON string for the passed period, metric, and extra data. - * - * @since 3.13.0 - * - * @param string|null $metric The Metric value. - * @param string|null $period The Period value. - * @param array $extra_data Any Extra key/value pairs to add. - * @return string The generated JSON string. - */ - abstract protected function generate_json( - ?string $metric = null, - ?string $period = null, - array $extra_data = array() - ): string; - - /** - * Verifies that the endpoint returns the correct default value. - * - * @since 3.13.0 - */ - public function run_test_endpoint_returns_value_on_get_request(): void { - $this->set_current_user_to_admin(); - - $value = rest_do_request( - new WP_REST_Request( - 'GET', - self::$route - ) - )->get_data(); - - $expected = $this->wp_json_encode( - $this->default_value - ); - - self::assertSame( $expected, $value ); - } - - /** - * Provides data for testing PUT requests. - * - * @since 3.13.0 - * @return iterable - */ - public function provide_put_requests_data(): iterable { - $default_value = $this->generate_json( 'views', '7d' ); - $valid_value = $this->generate_json( 'avg_engaged', '1h' ); - - // Valid non-default value. It should be returned unmodified. - yield 'valid period and metric values' => array( - 'test_data' => $valid_value, - 'expected' => $valid_value, - ); - - // Missing or problematic keys. Defaults should be used for the missing or problematic keys. - yield 'valid period value, no metric value' => array( - 'test_data' => $this->generate_json( null, '1h' ), - 'expected' => $this->generate_json( 'views', '1h' ), - ); - yield 'valid metric value, no period value' => array( - 'test_data' => $this->generate_json( 'avg_engaged' ), - 'expected' => $this->generate_json( 'avg_engaged', '7d' ), - ); - yield 'no values' => array( - 'test_data' => $this->generate_json(), - 'expected' => $default_value, - ); - - // Invalid values. They should be adjusted to their defaults. - yield 'invalid period value' => array( - 'test_data' => $this->generate_json( 'avg_engaged', 'invalid' ), - 'expected' => $this->generate_json( 'avg_engaged', '7d' ), - ); - yield 'invalid metric value' => array( - 'test_data' => $this->generate_json( 'invalid', '1h' ), - 'expected' => $this->generate_json( 'views', '1h' ), - ); - yield 'invalid period and metric values' => array( - 'test_data' => $this->generate_json( 'invalid', 'invalid' ), - 'expected' => $default_value, - ); - - // Invalid extra data passed. Any such data should be discarded. - yield 'invalid additional value' => array( - 'test_data' => $this->generate_json( - 'avg_engaged', - '1h', - array( 'invalid' ) - ), - 'expected' => $valid_value, - ); - yield 'invalid additional key/value pair' => array( - 'test_data' => $this->generate_json( - 'avg_engaged', - '1h', - array( 'invalid_key' => 'invalid_value' ) - ), - 'expected' => $valid_value, - ); - } - - /** - * Sends a PUT request to the endpoint. - * - * @since 3.13.0 - * - * @param string $data The data to be sent in the request. - * @return string The response returned by the endpoint. - */ - protected function send_put_request( string $data ): string { - $this->set_current_user_to_admin(); - $result = $this->send_wp_rest_request( 'PUT', self::$route, $data ); - - if ( ! is_string( $result ) ) { - return ''; - } - - return $result; - } - - /** - * Verifies that the route is not registered when the respective filter is - * set to false. - * - * @since 3.16.0 - */ - public function run_test_do_not_register_route_when_proxy_is_disabled(): void { - // Override some setup steps in order to set the filter to false. - remove_action( 'rest_api_init', $this->rest_api_init_proxy ); - $endpoint = $this->get_endpoint(); - $this->rest_api_init_proxy = static function () use ( $endpoint ) { - add_filter( 'wp_parsely_enable_' . self::$filter_key . '_api_proxy', '__return_false' ); - $endpoint->run(); - }; - add_action( 'rest_api_init', $this->rest_api_init_proxy ); - - $routes = rest_get_server()->get_routes(); - self::assertFalse( array_key_exists( self::$route, $routes ) ); - } -} diff --git a/tests/Integration/Endpoints/UserMeta/DashboardWidgetSettingsEndpointTest.php b/tests/Integration/Endpoints/UserMeta/DashboardWidgetSettingsEndpointTest.php deleted file mode 100644 index 7af087282..000000000 --- a/tests/Integration/Endpoints/UserMeta/DashboardWidgetSettingsEndpointTest.php +++ /dev/null @@ -1,204 +0,0 @@ - - */ - protected $default_value = array( - 'Metric' => 'views', - 'Period' => '7d', - ); - - /** - * Initializes all required values for the test. - * - * @since 3.13.0 - */ - public static function initialize(): void { - $route = Dashboard_Widget_Settings_Endpoint::get_route(); - - self::$route = '/wp-parsely/v1' . $route; - self::$filter_key = Utils::convert_endpoint_to_filter_key( $route ); - } - - /** - * Returns the endpoint to be used in tests. - * - * @since 3.13.0 - * - * @return Base_Endpoint_User_Meta The endpoint to be used in tests. - */ - public function get_endpoint(): Base_Endpoint_User_Meta { - return new Dashboard_Widget_Settings_Endpoint( new Parsely() ); - } - - /** - * Verifies that the route is registered. - * - * @since 3.13.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_route - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user - * @uses \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_subvalues_specs - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_register_routes_by_default(): void { - parent::run_test_register_routes_by_default( - array( - 'GET' => true, - 'PUT' => true, - ) - ); - } - - /** - * Verifies that the route is not registered when the endpoint filter is set - * to false. - * - * @since 3.13.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_route - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @uses \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_subvalues_specs - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_verify_that_route_is_not_registered_when_endpoint_is_disabled(): void { - parent::run_test_do_not_register_route_when_proxy_is_disabled(); - } - - /** - * Verifies that the endpoint returns the correct default settings. - * - * @since 3.13.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_value - * @covers \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::process_request - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_meta_key - * @uses \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_route - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_endpoint_returns_value_on_get_request(): void { - parent::run_test_endpoint_returns_value_on_get_request(); - } - - /** - * Verifies that the endpoint can correctly handle PUT requests. - * - * @since 3.13.0 - * - * @param string $test_data The data to send in the PUT request. - * @param string $expected The expected value of the setting after the PUT request. - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_value - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::sanitize_subvalue - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::sanitize_value - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::set_value - * @covers \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::process_request - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_meta_key - * @uses \Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint::get_route - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * - * @dataProvider provide_put_requests_data - */ - public function test_endpoint_correctly_handles_put_requests( - string $test_data, - string $expected - ): void { - $value = $this->send_put_request( $test_data ); - self::assertSame( $expected, $value ); - } - - /** - * Generates a JSON string for the passed period, metric, and extra data. - * - * @since 3.13.0 - * - * @param string|null $metric The Metric value. - * @param string|null $period The Period value. - * @param array $extra_data Any Extra key/value pairs to add. - * @return string The generated JSON string. - */ - protected function generate_json( - ?string $metric = null, - ?string $period = null, - array $extra_data = array() - ): string { - $array = $this->default_value; - unset( $array['Metric'], $array['Period'] ); - - if ( null !== $metric ) { - $array['Metric'] = $metric; - } - - if ( null !== $period ) { - $array['Period'] = $period; - } - - ksort( $array ); - - return $this->wp_json_encode( array_merge( $array, $extra_data ) ); - } -} diff --git a/tests/Integration/Endpoints/UserMeta/EditorSidebarSettingsEndpointTest.php b/tests/Integration/Endpoints/UserMeta/EditorSidebarSettingsEndpointTest.php deleted file mode 100644 index 00071489b..000000000 --- a/tests/Integration/Endpoints/UserMeta/EditorSidebarSettingsEndpointTest.php +++ /dev/null @@ -1,309 +0,0 @@ - - */ - protected $default_value = array( - 'InitialTabName' => 'tools', - 'PerformanceStats' => array( - 'Period' => '7d', - 'VisibleDataPoints' => array( 'views', 'visitors', 'avgEngaged', 'recirculation' ), - 'VisiblePanels' => array( 'overview', 'categories', 'referrers' ), - ), - 'RelatedPosts' => array( - 'FilterBy' => 'unavailable', - 'FilterValue' => '', - 'Metric' => 'views', - 'Open' => false, - 'Period' => '7d', - ), - 'SmartLinking' => array( - 'MaxLinks' => 10, - 'MaxLinkWords' => 4, - 'Open' => false, - ), - 'TitleSuggestions' => array( - 'Open' => false, - 'Persona' => 'journalist', - 'Tone' => 'neutral', - ), - ); - - /** - * Initializes all required values for the test. - * - * @since 3.13.0 - */ - public static function initialize(): void { - $route = Editor_Sidebar_Settings_Endpoint::get_route(); - - self::$route = '/wp-parsely/v1' . $route; - self::$filter_key = Utils::convert_endpoint_to_filter_key( $route ); - } - - /** - * Returns the endpoint to be used in tests. - * - * @since 3.13.0 - * - * @return Base_Endpoint_User_Meta The endpoint to be used in tests. - */ - public function get_endpoint(): Base_Endpoint_User_Meta { - return new Editor_Sidebar_Settings_Endpoint( new Parsely() ); - } - - /** - * Verifies that the route is registered. - * - * @since 3.13.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_route - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_subvalues_specs - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_register_routes_by_default(): void { - parent::run_test_register_routes_by_default( - array( - 'GET' => true, - 'PUT' => true, - ) - ); - } - - /** - * Verifies that the route is not registered when the endpoint filter is set - * to false. - * - * @since 3.13.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_route - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_subvalues_specs - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_verify_that_route_is_not_registered_when_endpoint_is_disabled(): void { - parent::run_test_do_not_register_route_when_proxy_is_disabled(); - } - - /** - * Verifies that the endpoint returns the correct default settings. - * - * @since 3.13.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_value - * @covers \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::process_request - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_meta_key - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_route - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_endpoint_returns_value_on_get_request(): void { - parent::run_test_endpoint_returns_value_on_get_request(); - } - - /** - * Verifies that the endpoint can correctly handle PUT requests. - * - * @since 3.13.0 - * - * @param string $test_data The data to send in the PUT request. - * @param string $expected The expected value of the setting after the PUT request. - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_value - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::sanitize_subvalue - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::sanitize_value - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::set_value - * @covers \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_subvalues_specs - * @covers \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::process_request - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_default - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_nested_specs - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_valid_values - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_valid_key - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_meta_key - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_route - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - * @dataProvider provide_put_requests_data - */ - public function test_endpoint_correctly_handles_put_requests( - string $test_data, - string $expected - ): void { - $value = $this->send_put_request( $test_data ); - self::assertSame( $expected, $value ); - } - - /** - * Tests that the endpoint can correctly handle PUT requests with valid - * nested PerformanceStats values. - * - * @since 3.14.0 - * - * @covers \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::sanitize_subvalue - * @uses \Parsely\Endpoints\Base_Endpoint::__construct() - * @uses \Parsely\Endpoints\Base_Endpoint::register_endpoint() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::__construct() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_route() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_value() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::is_available_to_current_user() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::process_request() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::run() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::sanitize_value() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::set_value() - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_meta_key() - * @uses \Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint::get_subvalues_specs() - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_nested_specs - * @uses \Parsely\Endpoints\User_Meta\Base_Endpoint_User_Meta::get_valid_values - * @uses \Parsely\Parsely::__construct() - * @uses \Parsely\Parsely::allow_parsely_remote_requests() - * @uses \Parsely\Parsely::are_credentials_managed() - * @uses \Parsely\Parsely::set_managed_options() - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key() - */ - public function test_valid_nested_performance_stats_settings_period(): void { - $this->set_current_user_to_admin(); - - $value = $this->send_put_request( - $this->generate_json( - 'views', - '7d', - array( - 'PerformanceStats' => array( - 'Period' => '1h', - 'VisibleDataPoints' => array( 'views', 'avgEngaged', 'recirculation' ), - 'VisiblePanels' => array( 'overview', 'referrers' ), - ), - ) - ) - ); - - $expected = $this->wp_json_encode( - array_merge( - $this->default_value, - array( - 'PerformanceStats' => array( - 'Period' => '1h', - 'VisibleDataPoints' => array( 'views', 'avgEngaged', 'recirculation' ), - 'VisiblePanels' => array( 'overview', 'referrers' ), - ), - ) - ) - ); - - self::assertSame( $expected, $value ); - } - - /** - * Generates a JSON string for the passed period, metric, and extra data. - * - * @since 3.13.0 - * - * @param string|null $metric The RelatedPostsMetric value. - * @param string|null $period The RelatedPostsPeriod value. - * @param array $extra_data Any Extra key/value pairs to add. - * @return string The generated JSON string. - */ - protected function generate_json( - ?string $metric = null, - ?string $period = null, - array $extra_data = array() - ): string { - $array = $this->default_value; - assert( is_array( $array['RelatedPosts'] ) ); - - unset( $array['RelatedPosts']['Metric'], $array['RelatedPosts']['Period'] ); - - if ( null !== $metric ) { - $array['RelatedPosts']['Metric'] = $metric; - } - - if ( null !== $period ) { - $array['RelatedPosts']['Period'] = $period; - } - - $merged_array = array_merge( $array, $extra_data ); - - $this->ksortRecursive( $merged_array, SORT_NATURAL | SORT_FLAG_CASE ); - - return $this->wp_json_encode( $merged_array ); - } - - /** - * Recursively sorts an array by key using a specified sort flag. - * - * @since 3.14.3 - * - * @param array &$unsorted_array The array to be sorted, passed by reference. - * @param int $sort_flags Optional sorting flags. Defaults to SORT_REGULAR. - */ - private function ksortRecursive( array &$unsorted_array, int $sort_flags = SORT_REGULAR ): void { - ksort( $unsorted_array, $sort_flags ); - foreach ( $unsorted_array as &$value ) { - if ( is_array( $value ) ) { - $this->ksortRecursive( $value, $sort_flags ); - } - } - } -} diff --git a/tests/Integration/RemoteAPI/AnalyticsPostsRemoteAPITest.php b/tests/Integration/RemoteAPI/AnalyticsPostsRemoteAPITest.php deleted file mode 100644 index 8eb7dc105..000000000 --- a/tests/Integration/RemoteAPI/AnalyticsPostsRemoteAPITest.php +++ /dev/null @@ -1,128 +0,0 @@ - - */ - public function data_api_url(): iterable { - yield 'Basic (Expected data)' => array( - array( - 'apikey' => 'my-key', - 'limit' => 5, - ), - Parsely::PUBLIC_API_BASE_URL . '/analytics/posts?apikey=my-key&limit=5', - ); - } - - /** - * Verifies default user capability filter. - * - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::apply_capability_filters - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_user_is_allowed_to_make_api_call_if_default_user_capability_is_changed(): void { - $this->set_current_user_to_contributor(); - add_filter( - 'wp_parsely_user_capability_for_all_private_apis', - function () { - return 'edit_posts'; - } - ); - - $api = new Analytics_Posts_API( new Parsely() ); - - self::assertTrue( $api->is_available_to_current_user() ); - } - - /** - * Verifies endpoint specific user capability filter. - * - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::apply_capability_filters - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_user_is_allowed_to_make_api_call_if_endpoint_specific_user_capability_is_changed(): void { - $this->set_current_user_to_contributor(); - add_filter( - 'wp_parsely_user_capability_for_analytics_posts_api', - function () { - return 'edit_posts'; - } - ); - - $api = new Analytics_Posts_API( new Parsely() ); - - self::assertTrue( $api->is_available_to_current_user() ); - } - - /** - * Verifies that the endpoint specific user capability filter has more priority than the default capability filter. - * - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Endpoints\Base_Endpoint::apply_capability_filters - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key - */ - public function test_endpoint_specific_user_capability_filter_have_more_priority_than_default(): void { - $this->set_current_user_to_contributor(); - - add_filter( - 'wp_parsely_user_capability_for_all_private_apis', - function () { - return 'publish_posts'; - } - ); - - add_filter( - 'wp_parsely_user_capability_for_analytics_posts_api', - function () { - return 'edit_posts'; - } - ); - - $api = new Analytics_Posts_API( new Parsely() ); - - self::assertTrue( $api->is_available_to_current_user() ); - } -} diff --git a/tests/Integration/RemoteAPI/BaseRemoteAPITest.php b/tests/Integration/RemoteAPI/BaseRemoteAPITest.php deleted file mode 100644 index 6f978d11c..000000000 --- a/tests/Integration/RemoteAPI/BaseRemoteAPITest.php +++ /dev/null @@ -1,163 +0,0 @@ - - */ - abstract public function data_api_url(): iterable; - - /** - * Runs once before all tests. - */ - public static function set_up_before_class(): void { - static::initialize(); - } - - /** - * Verifies the basic generation of the API URL. - * - * @dataProvider data_api_url - * @covers \Parsely\RemoteAPI\Related_API::get_api_url - * @covers \Parsely\RemoteAPI\Analytics_Posts_API::get_api_url - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Parsely::api_secret_is_set - * @uses \Parsely\Parsely::get_managed_credentials - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Parsely::get_site_id - * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::validate_required_constraints - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_api_url - * - * @param array $query Test query arguments. - * @param string $url Expected generated URL. - */ - public function test_api_url( array $query, string $url ): void { - self::set_options( array( 'apikey' => 'my-key' ) ); - self::assertSame( $url, self::$remote_api->get_api_url( $query ) ); - } - - /** - * Verifies that the cache is used instead of the api when there's a cache - * hit. - * - * @covers \Parsely\RemoteAPI\Remote_API_Cache::get_items - * @covers \Parsely\RemoteAPI\Remote_API_Cache::__construct - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_endpoint - */ - public function test_remote_api_cache_returns_cached_value(): void { - $api_mock = $this->getMockBuilder( get_class( self::$remote_api ) ) - ->disableOriginalConstructor() - ->getMock(); - - // If this method is called, that means our cache did not hit as expected. - $api_mock->expects( self::never() )->method( 'get_items' ); - $api_mock->method( 'get_endpoint' )->willReturn( self::$remote_api->get_endpoint() ); // Passing call to non-mock method. - - $cache_key = 'parsely_api_' . wp_hash( self::$remote_api->get_endpoint() ) . '_' . wp_hash( $this->wp_json_encode( array() ) ); - - $object_cache = $this->createMock( Cache::class ); - $object_cache->method( 'get' ) - ->willReturn( (object) array( 'cache_hit' => true ) ); - - $object_cache->expects( self::once() ) - ->method( 'get' ) - ->with( - self::equalTo( $cache_key ), - self::equalTo( 'wp-parsely' ), - self::equalTo( false ), - self::isNull() - ); - - /** - * Variable. - * - * @var Remote_API_Cache - */ - $remote_api_cache = $this->getMockBuilder( Remote_API_Cache::class ) - ->setConstructorArgs( array( $api_mock, $object_cache ) ) - ->setMethodsExcept( array( 'get_items' ) ) - ->getMock(); - - self::assertEquals( (object) array( 'cache_hit' => true ), $remote_api_cache->get_items( array() ) ); - } - - /** - * Verifies that when the cache misses, the api is used instead and the - * resultant value is cached. - * - * @covers \Parsely\RemoteAPI\Remote_API_Cache::get_items - * @covers \Parsely\RemoteAPI\Remote_API_Cache::__construct - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_endpoint - */ - public function test_caching_decorator_returns_uncached_value(): void { - $api_mock = $this->getMockBuilder( get_class( self::$remote_api ) ) - ->disableOriginalConstructor() - ->getMock(); - - $api_mock->method( 'get_items' ) - ->willReturn( (object) array( 'cache_hit' => false ) ); - - // If this method is _NOT_ called, that means our cache did not miss as expected. - $api_mock->expects( self::once() )->method( 'get_items' ); - $api_mock->method( 'get_endpoint' )->willReturn( self::$remote_api->get_endpoint() ); // Passing call to non-mock method. - - $cache_key = 'parsely_api_' . wp_hash( self::$remote_api->get_endpoint() ) . '_' . wp_hash( $this->wp_json_encode( array() ) ); - - $object_cache = $this->createMock( Cache::class ); - $object_cache->method( 'get' ) - ->willReturn( false ); - - $object_cache->expects( self::once() ) - ->method( 'get' ) - ->with( - self::equalTo( $cache_key ), - self::equalTo( 'wp-parsely' ), - self::equalTo( false ), - self::isNull() - ); - - /** - * Variable. - * - * @var Remote_API_Cache - */ - $remote_api_cache = $this->getMockBuilder( Remote_API_Cache::class ) - ->setConstructorArgs( array( $api_mock, $object_cache ) ) - ->setMethodsExcept( array( 'get_items' ) ) - ->getMock(); - - self::assertEquals( (object) array( 'cache_hit' => false ), $remote_api_cache->get_items( array() ) ); - } -} diff --git a/tests/Integration/RemoteAPI/ContentSuggestions/BaseContentSuggestionsAPITest.php b/tests/Integration/RemoteAPI/ContentSuggestions/BaseContentSuggestionsAPITest.php deleted file mode 100644 index 708b08a6c..000000000 --- a/tests/Integration/RemoteAPI/ContentSuggestions/BaseContentSuggestionsAPITest.php +++ /dev/null @@ -1,129 +0,0 @@ - 'my-key', - 'api_secret' => 'my-secret', - ) - ); - - $request_options = self::$remote_api->get_request_options(); - - // Ensure that $request_options is an array and 'headers' key exists. - self::assertIsArray( $request_options ); - self::assertArrayHasKey( 'headers', $request_options ); - - $headers = $request_options['headers']; - self::assertIsArray( $headers ); // Ensures $headers is indeed an array. - - // Verify the Content-Type header is present and its value is application/json. - self::assertArrayHasKey( 'Content-Type', $headers ); - self::assertEquals( 'application/json; charset=utf-8', $headers['Content-Type'] ); - - // Verify the API key is present in the headers and its value matches the one set in the options. - self::assertArrayHasKey( 'X-APIKEY-SECRET', $headers ); - self::assertEquals( 'my-secret', $headers['X-APIKEY-SECRET'] ); - } - - /** - * Verifies that the truncate function is properly truncated long content on the body array. - * - * @since 3.14.1 - * - * @covers \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::truncate_array_content - */ - public function test_truncate_body_content(): void { - /** - * @var Content_Suggestions_Base_API $remote_api - */ - $remote_api = self::$remote_api; - - $body = array( - 'output_params' => array( - 'some_param' => true, - 'other_param' => 'Hello', - 'recursive' => array( - 'key' => 'value', - ), - ), - 'text' => $this->generate_content_with_length( 30000 ), - 'something' => 'else', - ); - - $truncated_array = $remote_api->truncate_array_content( $body ); - - self::assertIsArray( $truncated_array ); - self::assertArrayHasKey( 'output_params', $truncated_array ); - self::assertArrayHasKey( 'text', $truncated_array ); - self::assertLessThanOrEqual( 25000, strlen( $truncated_array['text'] ) ); - - // Assert that the truncated text is the beginning of the original text. - self::assertStringStartsWith( $truncated_array['text'], $body['text'] ); - - // Assert that the other keys are the same in both arrays. - self::assertEquals( $body['output_params'], $truncated_array['output_params'] ); - self::assertEquals( $body['something'], $truncated_array['something'] ); - } - - /** - * Generate content with a specific length. - * - * @since 3.14.1 - * - * @param int $length Length of the generated content. - * - * @return string The generated content. - */ - private function generate_content_with_length( int $length ): string { - $words = array( 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit' ); - $string = ''; - $current_length = 0; - while ( $current_length < $length ) { - $word = $words[ array_rand( $words ) ]; - if ( $current_length > 0 ) { - if ( $current_length + strlen( $word ) + 1 > $length ) { - break; - } - $string .= ' '; - ++$current_length; - } - $string .= $word; - $current_length += strlen( $word ); - } - return $string; - } -} diff --git a/tests/Integration/RemoteAPI/ContentSuggestions/SuggestBriefAPITest.php b/tests/Integration/RemoteAPI/ContentSuggestions/SuggestBriefAPITest.php deleted file mode 100644 index 6c3ab62e1..000000000 --- a/tests/Integration/RemoteAPI/ContentSuggestions/SuggestBriefAPITest.php +++ /dev/null @@ -1,137 +0,0 @@ - - */ - public function data_api_url(): iterable { - yield 'Basic (Expected data)' => array( - array( - 'apikey' => 'my-key', - ), - Parsely::PUBLIC_SUGGESTIONS_API_BASE_URL . - '/suggest-brief?apikey=my-key', - ); - } - - - /** - * Mocks a successful HTTP response to the Content Suggestion suggest-brief - * API endpoint. - * - * @since 3.13.0 - * - * @param string $response The response to mock. - * @param array $args The arguments passed to the HTTP request. - * @param string $url The URL of the HTTP request. - * @return array|false The mocked response. - * - * @phpstan-ignore-next-line - */ - public function mock_successful_suggest_brief_response( - string $response, - array $args, - string $url - ) { - if ( ! str_contains( $url, 'suggest-brief' ) ) { - return false; - } - - $response = array( - 'result' => array( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - ), - ); - - return array( - 'headers' => array(), - 'cookies' => array(), - 'filename' => null, - 'response' => array( - 'code' => 200, - 'message' => 'OK', - ), - 'status_code' => 200, - 'success' => true, - 'body' => $this->wp_json_encode( $response ), - ); - } - - /** - * Tests getting meta description from the API with some generic content. - * - * @since 3.13.0 - * - * @covers \Parsely\RemoteAPI\ContentSuggestions\Suggest_Brief_API::get_suggestion - * @uses \Parsely\Parsely::api_secret_is_set() - * @uses \Parsely\Parsely::get_managed_credentials() - * @uses \Parsely\Parsely::get_options() - * @uses \Parsely\Parsely::get_site_id() - * @uses \Parsely\Parsely::set_default_track_as_values() - * @uses \Parsely\Parsely::site_id_is_set() - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::validate_required_constraints() - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_api_url() - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_request_options() - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::post_request() - */ - public function test_get_suggestion(): void { - $title = 'Lorem Ipsum is a random title'; - $content = '

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

'; - $persona = 'journalist'; - $style = 'neutral'; - - // Mock API result. - add_filter( 'pre_http_request', array( $this, 'mock_successful_suggest_brief_response' ), 10, 3 ); - - // Test getting meta description. - $brief = self::$suggest_brief_api->get_suggestion( $title, $content, $persona, $style ); - - self::assertIsString( $brief ); - self::assertEquals( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', $brief ); - - // Remove mock. - remove_filter( 'pre_http_request', array( $this, 'mock_successful_suggest_brief_response' ) ); - } -} diff --git a/tests/Integration/RemoteAPI/RelatedRemoteAPITest.php b/tests/Integration/RemoteAPI/RelatedRemoteAPITest.php deleted file mode 100644 index 52c4ab80d..000000000 --- a/tests/Integration/RemoteAPI/RelatedRemoteAPITest.php +++ /dev/null @@ -1,94 +0,0 @@ - - */ - public function data_api_url(): iterable { - yield 'Basic (Expected data)' => array( - array( - 'apikey' => 'my-key', - 'pub_date_start' => '7d', - 'sort' => 'score', - 'limit' => 5, - ), - Parsely::PUBLIC_API_BASE_URL . '/related?apikey=my-key&limit=5&pub_date_start=7d&sort=score', - ); - - yield 'published_within value of 0' => array( - array( - 'apikey' => 'my-key', - 'sort' => 'score', - 'limit' => 5, - ), - Parsely::PUBLIC_API_BASE_URL . '/related?apikey=my-key&limit=5&sort=score', - ); - - yield 'Sort on publish date' => array( - array( - 'apikey' => 'my-key', - 'sort' => 'pub_date', - 'limit' => 5, - ), - Parsely::PUBLIC_API_BASE_URL . '/related?apikey=my-key&limit=5&sort=pub_date', - ); - - yield 'Rank by relevance only' => array( - array( - 'apikey' => 'my-key', - 'sort' => 'score', - 'limit' => 5, - ), - Parsely::PUBLIC_API_BASE_URL . '/related?apikey=my-key&limit=5&sort=score', - ); - } - - /** - * Verifies that the endpoint does not have filters that check user capability. - * - * @covers \Parsely\RemoteAPI\Related_API::is_available_to_current_user - * @uses \Parsely\Endpoints\Base_Endpoint::__construct - * @uses \Parsely\Parsely::get_managed_credentials - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::set_managed_options - */ - public function test_related_endpoint_does_not_have_user_capability_filters(): void { - $api = new Related_API( new Parsely() ); - - self::assertTrue( $api->is_available_to_current_user() ); - $this->assert_wp_hooks_availability( - array( - 'wp_parsely_user_capability_for_all_private_apis', - 'wp_parsely_user_capability_for_related_api', - ), - false - ); - } -} diff --git a/tests/Integration/RestAPI/BaseAPIControllerTest.php b/tests/Integration/RestAPI/BaseAPIControllerTest.php new file mode 100644 index 000000000..4211b10bb --- /dev/null +++ b/tests/Integration/RestAPI/BaseAPIControllerTest.php @@ -0,0 +1,270 @@ +test_controller = new class($parsely) extends Base_API_Controller { + /** + * Gets the namespace for the API. + * + * @since 3.17.0 + * + * @return string The namespace. + */ + protected function get_namespace(): string { + return 'test'; + } + + /** + * Gets the route prefix, which acts as a namespace for the endpoints. + * + * @since 3.17.0 + * + * @return string The route prefix. + */ + public static function get_route_prefix(): string { + return 'test'; + } + + /** + * Gets the version for the API. + * + * @since 3.17.0 + * + * @return string The version. + */ + protected function get_version(): string { + return 'v1'; + } + + /** + * Initializes the test controller. + * + * @since 3.17.0 + */ + protected function init(): void {} + + /** + * Exposes the protected method for testing. + * + * @since 3.17.0 + * + * @param Base_Endpoint[] $endpoints The endpoints to register. + */ + public function testable_register_endpoints( array $endpoints ): void { + $this->register_endpoints( $endpoints ); + } + + /** + * Exposes the protected method for testing. + * + * @since 3.17.0 + * + * @param Base_Endpoint $endpoint The endpoint to register. + */ + public function testable_register_endpoint( Base_Endpoint $endpoint ): void { + $this->register_endpoint( $endpoint ); + } + + /** + * Checks if a specific endpoint is available to the current user. + * + * @since 3.17.0 + * + * @param string $endpoint The endpoint to check. + * @return bool True if the controller is available to the current user, false otherwise. + */ + public function is_available_to_current_user( string $endpoint ): bool { + return true; + } + }; + } + + /** + * Tests the get_namespace method. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::__construct + */ + public function test_get_namespace(): void { + self::assertEquals( 'test/v1', $this->test_controller->get_full_namespace() ); + } + + /** + * Tests the prefix_route method. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_API_Controller::__construct + */ + public function test_prefix_route(): void { + self::assertEquals( 'test/my-route', $this->test_controller->prefix_route( 'my-route' ) ); + $parsely = self::createMock( Parsely::class ); + + $controller_without_prefix = new class($parsely) extends Base_API_Controller { + /** + * Initialize the test controller. + * + * @since 3.17.0 + */ + protected function init(): void {} + + /** + * Get the namespace for the API. + * + * @since 3.17.0 + * + * @return string The namespace. + */ + protected function get_namespace(): string { + return 'test'; + } + + /** + * Checks if a specific endpoint is available to the current user. + * + * @since 3.17.0 + * + * @param string $endpoint The endpoint to check. + * @return bool True if the controller is available to the current user, false otherwise. + */ + public function is_available_to_current_user( string $endpoint ): bool { + return true; + } + }; + + self::assertEquals( 'my-route', $controller_without_prefix->prefix_route( 'my-route' ) ); + } + + /** + * Tests that endpoints are registered correctly. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_API_Controller::register_endpoint + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::register_endpoint + */ + public function test_register_endpoint(): void { + $endpoint = self::createMock( Base_Endpoint::class ); + $endpoint->expects( self::once() ) + ->method( 'get_endpoint_slug' ) + ->willReturn( 'test' ); + + $this->test_controller->testable_register_endpoint( $endpoint ); // @phpstan-ignore-line + + $endpoints = $this->test_controller->get_endpoints(); + self::assertCount( 1, $endpoints ); + self::assertSame( $endpoint, $endpoints['test'] ); + } + + /** + * Tests that multiple endpoints are registered correctly using a helper method. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_API_Controller::register_endpoints + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::register_endpoint + * @uses \Parsely\REST_API\Base_API_Controller::register_endpoints + */ + public function test_register_multiple_endpoints(): void { + $endpoint1 = self::createMock( Base_Endpoint::class ); + $endpoint1->expects( self::once() ) + ->method( 'get_endpoint_slug' ) + ->willReturn( 'test1' ); + + $endpoint2 = self::createMock( Base_Endpoint::class ); + $endpoint2->expects( self::once() ) + ->method( 'get_endpoint_slug' ) + ->willReturn( 'test2' ); + + + $this->test_controller->testable_register_endpoints( array( $endpoint1, $endpoint2 ) ); // @phpstan-ignore-line + + $endpoints = $this->test_controller->get_endpoints(); + + self::assertCount( 2, $endpoints ); + self::assertSame( $endpoint1, $endpoints['test1'] ); + self::assertSame( $endpoint2, $endpoints['test2'] ); + } + + /** + * Tests that the get_endpoint_slug method returns the correct value. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_Endpoint::get_endpoint_slug + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_endpoint_slug + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_get_endpoint_slug(): void { + // Create a mocked endpoint. + $endpoint = new class( $this->test_controller ) extends Base_Endpoint { + /** + * Get the endpoint name. + * + * @since 3.17.0 + * + * @return string The endpoint name. + */ + public static function get_endpoint_name(): string { + return 'test-endpoint'; + } + + /** + * Register the routes for the endpoints. + * + * @since 3.17.0 + */ + public function register_routes(): void {} + }; + + $this->test_controller->testable_register_endpoint( $endpoint ); // @phpstan-ignore-line + + self::assertEquals( 'test/test-endpoint', $endpoint->get_endpoint_slug() ); + } +} diff --git a/tests/Integration/RestAPI/BaseEndpointTest.php b/tests/Integration/RestAPI/BaseEndpointTest.php new file mode 100644 index 000000000..29544e51a --- /dev/null +++ b/tests/Integration/RestAPI/BaseEndpointTest.php @@ -0,0 +1,447 @@ + $data The data for the test. + * @param string $data_name The name of the data. + */ + public function __construct( $name = null, array $data = array(), $data_name = '' ) { + // Create Parsely class, if not already created (by an inherited class). + if ( null === $this->parsely ) { + $this->parsely = new Parsely(); + } + + // Create API controller, if not already created (by an inherited class). + if ( null === $this->api_controller ) { + $this->api_controller = new REST_API_Controller( $this->parsely ); + } + + parent::__construct( $name, $data, $data_name ); + } + + /** + * Setup method called before each test. + * + * @since 3.17.0 + */ + public function set_up(): void { + parent::set_up(); + TestCase::set_options(); + $this->set_current_user_to_admin(); + + $this->wp_rest_server_global_backup = $GLOBALS['wp_rest_server'] ?? null; + + // Create a concrete class for testing purposes. + $this->test_endpoint = new class($this->api_controller) extends Base_Endpoint { + + /** + * Gets the endpoint name. + * + * @since 3.17.0 + * + * @return string + */ + public static function get_endpoint_name(): string { + return 'test'; + } + + /** + * Registers the test route. + * + * @since 3.17.0 + */ + public function register_routes(): void { + $this->register_rest_route( + '/test-route', + array( 'GET' ), + array( $this, 'get_test_data' ) + ); + } + + /** + * Gets test data. + * + * @since 3.17.0 + * + * @return array + */ + public function get_test_data(): array { + return array( 'data' => 'test' ); + } + }; + + $this->initialize_rest_endpoint(); + } + + /** + * Tears down the test environment. + * + * @since 3.17.0 + */ + public function tear_down(): void { + remove_action( 'plugins_loaded', $this->rest_api_init_proxy ); + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound + $GLOBALS['wp_rest_server'] = $this->wp_rest_server_global_backup; + + parent::tear_down(); + } + + /** + * Returns the test endpoint instance. + * + * @since 3.17.0 + * + * @return Base_Endpoint + */ + public function get_endpoint(): Base_Endpoint { + return $this->test_endpoint; + } + + /** + * Tests that the route is correctly registered in WordPress. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_Endpoint::init + * @covers \Parsely\REST_API\Base_Endpoint::register_routes + * @covers \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + */ + public function test_route_is_registered(): void { + $routes = rest_get_server()->get_routes(); + + // Check that the namespace route is registered. + $expected_namespace = '/' . $this->api_controller->get_full_namespace(); + self::assertArrayHasKey( $expected_namespace, $routes ); + + // Check that the test route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( 'test-route' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the correct method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'GET', $route_data[0]['methods'] ); + } + + /** + * Tests that the route is correctly registered in WordPress, depending on the filter. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_Endpoint::init + * @covers \Parsely\REST_API\Base_Endpoint::register_routes + * @covers \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @covers \Parsely\REST_API\Base_Endpoint::get_registered_routes + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Base_API_Controller::get_route_prefix + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_endpoint_name + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_endpoint_is_registered_based_on_filter(): void { + $filter_name = 'wp_parsely_api_' . + \Parsely\Utils\Utils::convert_endpoint_to_filter_key( $this->get_endpoint()::get_endpoint_name() ) . + '_endpoint_enabled'; + + // Test when the filter allows the endpoint to be enabled. + add_filter( $filter_name, '__return_true' ); + $this->get_endpoint()->init(); + $routes = rest_get_server()->get_routes(); + $registered_routes = $this->get_endpoint()->get_registered_routes(); + + // Assert that the routes are registered when the filter returns true. + foreach ( $registered_routes as $route ) { + self::assertArrayHasKey( $this->get_endpoint()->get_full_endpoint( $route ), $routes ); + } + + // Reset the environment. + $this->tear_down(); + + // Now test when the filter disables the endpoint. + remove_all_filters( $filter_name ); + add_filter( $filter_name, '__return_false' ); + $this->get_endpoint()->init(); + $routes = rest_get_server()->get_routes(); + $registered_routes = $this->get_endpoint()->get_registered_routes(); + + // Assert that the route is NOT registered when the filter returns false. + foreach ( $registered_routes as $route ) { + self::assertArrayNotHasKey( $this->get_endpoint()->get_full_endpoint( $route ), $routes ); + } + } + + /** + * Tests is_available_to_current_user returns WP_Error if API key or secret is not set. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @covers \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_is_available_to_current_user_returns_error_site_id_not_set(): void { + TestCase::set_options( + array( + 'apikey' => '', + 'api_secret' => '', + ) + ); + + $result = $this->get_endpoint()->is_available_to_current_user(); + + self::assertInstanceOf( WP_Error::class, $result ); + self::assertEquals( 'parsely_site_id_not_set', $result->get_error_code() ); + } + + /** + * Tests is_available_to_current_user returns WP_Error if API key or secret is not set. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @covers \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_is_available_to_current_user_returns_error_api_secret_not_set(): void { + TestCase::set_options( + array( + 'apikey' => 'test-apikey', + 'api_secret' => '', + ) + ); + + $result = $this->get_endpoint()->is_available_to_current_user(); + + self::assertInstanceOf( WP_Error::class, $result ); + self::assertEquals( 'parsely_api_secret_not_set', $result->get_error_code() ); + } + + /** + * Tests apply_capability_filters method. + * + * @covers \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + */ + public function test_apply_capability_filters(): void { + add_filter( + 'wp_parsely_user_capability_for_all_private_apis', + function () { + return 'edit_posts'; + } + ); + + $result = $this->get_endpoint()->apply_capability_filters( 'publish_posts' ); + self::assertEquals( 'edit_posts', $result ); + } + + /** + * Tests validate_apikey_and_secret returns true when API key and secret are set. + * + * @covers \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_validate_site_id_and_secret_returns_true(): void { + TestCase::set_options( + array( + 'apikey' => 'test-apikey', + 'api_secret' => 'test-secret', + ) + ); + + $result = $this->get_endpoint()->validate_site_id_and_secret(); + + self::assertTrue( $result ); + } + + /** + * Initializes the REST endpoint. + * + * @since 3.17.0 + */ + protected function initialize_rest_endpoint(): void { + // Initialize the endpoint when the plugins are loaded. + $this->rest_api_init_proxy = function () { + $this->get_endpoint()->init(); + }; + add_action( 'plugins_loaded', $this->rest_api_init_proxy ); + + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + do_action( 'plugins_loaded' ); + } +} diff --git a/tests/Integration/RestAPI/ContentHelper/ContentHelperControllerTest.php b/tests/Integration/RestAPI/ContentHelper/ContentHelperControllerTest.php new file mode 100644 index 000000000..29f4300f4 --- /dev/null +++ b/tests/Integration/RestAPI/ContentHelper/ContentHelperControllerTest.php @@ -0,0 +1,106 @@ +content_helper_controller = new Content_Helper_Controller( $parsely ); + } + + /** + * Tests the constructor sets up the correct namespace and version. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Controller::__construct + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_full_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + */ + public function test_constructor_sets_up_namespace_and_version(): void { + self::assertEquals( 'wp-parsely/v2', $this->content_helper_controller->get_full_namespace() ); + } + + /** + * Tests that the route prefix is set correctly. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Controller::ROUTE_PREFIX + */ + public function test_route_prefix(): void { + self::assertEquals( 'content-helper', $this->content_helper_controller::get_route_prefix() ); + } + + /** + * Tests that the init method registers the correct endpoints. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Controller::init + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_endpoints + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::register_endpoint + * @uses \Parsely\REST_API\Base_API_Controller::register_endpoints + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Content_Helper\Endpoint_Excerpt_Generator::__construct + * @uses \Parsely\REST_API\Content_Helper\Endpoint_Excerpt_Generator::get_endpoint_name + * @uses \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::__construct + * @uses \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::get_endpoint_name + * @uses \Parsely\REST_API\Content_Helper\Endpoint_Title_Suggestions::__construct + * @uses \Parsely\REST_API\Content_Helper\Endpoint_Title_Suggestions::get_endpoint_name + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_init_registers_endpoints(): void { + $this->content_helper_controller->init(); + $endpoints = $this->content_helper_controller->get_endpoints(); + + self::assertCount( 3, $endpoints ); + + self::assertInstanceOf( Endpoint_Smart_Linking::class, $endpoints['content-helper/smart-linking'] ); + self::assertInstanceOf( Endpoint_Excerpt_Generator::class, $endpoints['content-helper/excerpt-generator'] ); + self::assertInstanceOf( Endpoint_Title_Suggestions::class, $endpoints['content-helper/title-suggestions'] ); + } +} diff --git a/tests/Integration/RestAPI/ContentHelper/ContentHelperFeatureTestTrait.php b/tests/Integration/RestAPI/ContentHelper/ContentHelperFeatureTestTrait.php new file mode 100644 index 000000000..1493ee0ca --- /dev/null +++ b/tests/Integration/RestAPI/ContentHelper/ContentHelperFeatureTestTrait.php @@ -0,0 +1,289 @@ +enable_feature(); + $this->set_current_user_to_admin(); + + // Assert that the endpoint is available to the current user. + self::assertTrue( $this->get_endpoint()->is_available_to_current_user( new WP_REST_Request() ) ); + } + + /** + * Tests that the endpoint is not available to the current user. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Feature::is_available_to_current_user + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_is_available_to_current_user_returns_error_if_feature_disabled(): void { + $this->disable_feature(); + $this->set_current_user_to_admin(); + + // Assert that the endpoint is not available to the current user. + self::assertInstanceOf( WP_Error::class, $this->get_endpoint()->is_available_to_current_user( new WP_REST_Request() ) ); + } + + /** + * Tests that the endpoint is available to the current user, since the user has the required role. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Feature::is_available_to_current_user + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_is_available_to_current_user_returns_true_if_has_permissions(): void { + $this->set_feature_options( + array( + 'enabled' => true, + 'allowed_user_roles' => array( 'administrator' ), + ) + ); + + // Assert that the endpoint is available to the current user. + $this->set_current_user_to_admin(); + self::assertTrue( $this->get_endpoint()->is_available_to_current_user( new WP_REST_Request() ) ); + + // Assert that the endpoint is not available to the current user. + $this->set_current_user_to_contributor(); + self::assertInstanceOf( WP_Error::class, $this->get_endpoint()->is_available_to_current_user( new WP_REST_Request() ) ); + } + + /** + * Tests that the endpoint is not available to the current user, since the user does not have the + * required role. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Feature::is_available_to_current_user + * @uses \Parsely\Parsely::__construct + * @uses \Parsely\Parsely::allow_parsely_remote_requests + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::are_credentials_managed + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::set_managed_options + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_is_available_to_current_user_returns_error_if_no_permissions(): void { + $this->set_current_user_to_contributor(); + + $this->set_feature_options( + array( + 'enabled' => true, + 'allowed_user_roles' => array( 'administrator' ), + ) + ); + + // Assert that the endpoint is not available to the current user. + self::assertInstanceOf( WP_Error::class, $this->get_endpoint()->is_available_to_current_user( new WP_REST_Request() ) ); + } + + + /** + * Tests that the endpoint is not available to the current user, since the user is not logged in. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Content_Helper_Feature::is_available_to_current_user + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_is_available_to_current_user_returns_error_if_no_user(): void { + $this->enable_feature(); + // Set the current user to a non-logged in user. + wp_set_current_user( 0 ); + + // Assert that the endpoint is not available to the current user. + self::assertInstanceOf( WP_Error::class, $this->get_endpoint()->is_available_to_current_user( new WP_REST_Request() ) ); + } + + /** + * You need to implement this method in your test class + * to return the endpoint instance being tested. + * + * @since 3.17.0 + * + * @return Base_Endpoint + */ + abstract protected function get_endpoint(): Base_Endpoint; + + /** + * Sets the specific feature options. + * + * @since 3.17.0 + * + * @param array $options The options to set. + */ + private function set_feature_options( array $options ): void { + $feature_name = $this->get_endpoint()->get_pch_feature_name(); + + TestCase::set_options( + array( + 'apikey' => 'test', + 'api_secret' => 'test', + 'content_helper' => array( + 'ai_features_enabled' => true, + $feature_name => $options, + ), + ) + ); + } + + /** + * Disables the specific feature. + * + * @since 3.17.0 + */ + private function disable_feature(): void { + $this->set_feature_options( + array( + 'enabled' => false, + 'allowed_user_roles' => array(), + ) + ); + } + + /** + * Enables the specific feature. + * + * @since 3.17.0 + */ + private function enable_feature(): void { + $valid_roles = array_keys( Permissions::get_user_roles_with_edit_posts_cap() ); + + $this->set_feature_options( + array( + 'enabled' => true, + 'allowed_user_roles' => $valid_roles, + ) + ); + } + + /** + * Sets the current user to an administrator. + * + * @since 3.17.0 + */ + abstract protected function set_current_user_to_admin(): void; + + /** + * Sets the current user to a contributor. + * + * @since 3.17.0 + */ + abstract protected function set_current_user_to_contributor(): void; +} diff --git a/tests/Integration/RestAPI/ContentHelper/EndpointExcerptGeneratorTest.php b/tests/Integration/RestAPI/ContentHelper/EndpointExcerptGeneratorTest.php new file mode 100644 index 000000000..17a12ebd3 --- /dev/null +++ b/tests/Integration/RestAPI/ContentHelper/EndpointExcerptGeneratorTest.php @@ -0,0 +1,203 @@ +api_controller = new Content_Helper_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Excerpt_Generator( $this->api_controller ); + + parent::set_up(); + } + + /** + * Gets the test endpoint instance. + * + * @since 3.17.0 + * + * @return Endpoint_Excerpt_Generator + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Tests that the endpoint is correctly registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Excerpt_Generator::register_routes + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + do_action( 'plugins_loaded' ); + $routes = rest_get_server()->get_routes(); + + // Check that the excerpt-generator/generate route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( 'generate' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the POST method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'POST', $route_data[0]['methods'] ); + } + + /** + * Tests that the generate_excerpt method returns a valid response. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Excerpt_Generator::generate_excerpt + * @uses \Parsely\Parsely::get_suggestions_api + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Services\Base_API_Service::__construct + * @uses \Parsely\Services\Base_API_Service::register_endpoint + * @uses \Parsely\Services\Base_Service_Endpoint::__construct + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Brief::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Headline::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Linked_Reference::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Suggestions_API_Service::register_endpoints + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_generate_excerpt_returns_valid_response(): void { + // Mock the Suggest_Brief_API to control the response. + $mock_suggestions_api = $this->createMock( Suggestions_API_Service::class ); + $mock_suggestions_api->expects( self::once() ) + ->method( 'get_brief_suggestions' ) + ->willReturn( array( array( 'summary' => 'This is a test excerpt.' ) ) ); + + self::set_protected_property( $this->get_endpoint(), 'suggestions_api', $mock_suggestions_api ); + + // Create a mock request. + $request = new WP_REST_Request( 'POST', '/excerpt-generator/generate' ); + $request->set_param( 'text', 'Test content' ); + $request->set_param( 'title', 'Test title' ); + $request->set_param( 'persona', 'journalist' ); + $request->set_param( 'style', 'neutral' ); + + // Call the generate_excerpt method. + $response = $this->get_endpoint()->generate_excerpt( $request ); + + // Assert that the response is a WP_REST_Response and contains the correct data. + self::assertInstanceOf( WP_REST_Response::class, $response ); + + /** + * The response data. + * + * @var array> $data The response data. + */ + $data = $response->get_data(); + self::assertArrayHasKey( 'data', $data ); + self::assertEquals( 'This is a test excerpt.', $data['data']['summary'] ); + } + + /** + * Tests that the generate_excerpt method returns an error if Suggest_Brief_API fails. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Excerpt_Generator::generate_excerpt + * @uses \Parsely\Parsely::get_suggestions_api + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Services\Base_API_Service::__construct + * @uses \Parsely\Services\Base_API_Service::register_endpoint + * @uses \Parsely\Services\Base_Service_Endpoint::__construct + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Brief::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Headline::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Linked_Reference::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Suggestions_API_Service::register_endpoints + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_generate_excerpt_returns_error_on_failure(): void { + // Mock the Suggest_Brief_API to simulate a failure. + $mock_suggestions_api = $this->createMock( Suggestions_API_Service::class ); + $mock_suggestions_api->expects( self::once() ) + ->method( 'get_brief_suggestions' ) + ->willReturn( new WP_Error( 'api_error', 'API request failed' ) ); + + self::set_protected_property( $this->get_endpoint(), 'suggestions_api', $mock_suggestions_api ); + + // Create a mock request. + $request = new WP_REST_Request( 'POST', '/excerpt-generator/generate' ); + $request->set_param( 'text', 'Test content' ); + $request->set_param( 'title', 'Test title' ); + $request->set_param( 'persona', 'journalist' ); + $request->set_param( 'style', 'neutral' ); + + // Call the generate_excerpt method. + $response = $this->get_endpoint()->generate_excerpt( $request ); + + // Assert that the response is a WP_Error. + self::assertInstanceOf( WP_Error::class, $response ); + self::assertEquals( 'api_error', $response->get_error_code() ); + } +} diff --git a/tests/Integration/RestAPI/ContentHelper/EndpointSmartLinkingTest.php b/tests/Integration/RestAPI/ContentHelper/EndpointSmartLinkingTest.php new file mode 100644 index 000000000..6e17109ee --- /dev/null +++ b/tests/Integration/RestAPI/ContentHelper/EndpointSmartLinkingTest.php @@ -0,0 +1,429 @@ +api_controller = new Content_Helper_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Smart_Linking( $this->api_controller ); + + parent::set_up(); + + // Setup fake API key and secret. + TestCase::set_options( + array( + 'apikey' => 'test-apikey', + 'api_secret' => 'test-secret', + ) + ); + } + + /** + * Gets the test endpoint instance. + * + * @since 3.17.0 + * + * @return Endpoint_Smart_Linking + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Tests that the endpoint is correctly registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::register_routes + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + do_action( 'plugins_loaded' ); + $routes = rest_get_server()->get_routes(); + + // Check that the smart-linking/generate route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( 'generate' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the POST method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'POST', $route_data[0]['methods'] ); + } + + /** + * Tests that the generate_smart_links method returns a valid response. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::generate_smart_links + * @uses \Parsely\Models\Base_Model::__construct + * @uses \Parsely\Models\Smart_Link::__construct + * @uses \Parsely\Models\Smart_Link::generate_uid + * @uses \Parsely\Models\Smart_Link::get_post_id_by_url + * @uses \Parsely\Models\Smart_Link::set_href + * @uses \Parsely\Models\Smart_Link::to_array + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_generate_smart_links_returns_valid_response(): void { + // Create a mocked Suggestions API that returns two smart links. + $mock_suggestions_api = $this->createMock( Suggestions_API_Service::class ); + $mock_suggestions_api->expects( self::once() ) + ->method( 'get_smart_links' ) + ->willReturn( + array( + new Smart_Link( 'link1', 'http://example.com/1', 'Example 1', 0, 0 ), + new Smart_Link( 'link2', 'http://example.com/2', 'Example 2', 0, 1 ), + ) + ); + + self::set_protected_property( $this->get_endpoint(), 'suggestions_api', $mock_suggestions_api ); + + // Create a mock request. + $request = new WP_REST_Request( 'POST', '/smart-linking/generate' ); + $request->set_param( 'text', 'Test content' ); + $request->set_param( 'max_links', 2 ); + $request->set_param( 'url_exclusion_list', array( 'http://excluded.com' ) ); + + // Call the generate_smart_links method. + $response = $this->get_endpoint()->generate_smart_links( $request ); + + // Assert that the response is a WP_REST_Response and contains the correct data. + self::assertInstanceOf( WP_REST_Response::class, $response ); + + /** + * The response data. + * + * @var array> $data The response data. + */ + $data = $response->get_data(); + self::assertArrayHasKey( 'data', $data ); + self::assertCount( 2, $data['data'] ); + } + + /** + * Tests that the generate_smart_links method returns an error if Suggest_Linked_Reference_API fails. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::generate_smart_links + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_generate_smart_links_returns_error_on_failure(): void { + // Mock the Suggestions API `get_smart_links` method to return a WP_Error. + $mock_suggestions_api = $this->createMock( Suggestions_API_Service::class ); + $mock_suggestions_api->expects( self::once() ) + ->method( 'get_smart_links' ) + ->willReturn( new WP_Error( 'api_error', 'API request failed' ) ); + + self::set_protected_property( $this->get_endpoint(), 'suggestions_api', $mock_suggestions_api ); + + // Create a mock request. + $request = new WP_REST_Request( 'POST', '/smart-linking/generate' ); + $request->set_param( 'text', 'Test content' ); + $request->set_param( 'max_links', 2 ); + $request->set_param( 'url_exclusion_list', array( 'http://excluded.com' ) ); + + // Call the generate_smart_links method. + $response = $this->get_endpoint()->generate_smart_links( $request ); + + // Assert that the response is a WP_Error. + self::assertInstanceOf( WP_Error::class, $response ); + self::assertEquals( 'api_error', $response->get_error_code() ); + } + + /** + * Tests that the add_smart_link method returns a valid response when adding a new smart link. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::add_smart_link + * @uses \Parsely\Models\Base_Model::__construct + * @uses \Parsely\Models\Base_Model::serialize + * @uses \Parsely\Models\Smart_Link::__construct + * @uses \Parsely\Models\Smart_Link::deserialize + * @uses \Parsely\Models\Smart_Link::exists + * @uses \Parsely\Models\Smart_Link::generate_uid + * @uses \Parsely\Models\Smart_Link::get_post_id_by_url + * @uses \Parsely\Models\Smart_Link::get_smart_link + * @uses \Parsely\Models\Smart_Link::get_smart_link_object_by_uid + * @uses \Parsely\Models\Smart_Link::load + * @uses \Parsely\Models\Smart_Link::save + * @uses \Parsely\Models\Smart_Link::set_href + * @uses \Parsely\Models\Smart_Link::set_source_post_id + * @uses \Parsely\Models\Smart_Link::set_uid + * @uses \Parsely\Models\Smart_Link::to_array + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_add_smart_link_returns_valid_response(): void { + // Create mocked post. + $post = WP_UnitTestCase_Base::factory()->post->create_and_get(); + self::assertNotWPError( $post ); + $post_id = $post->ID; // @phpstan-ignore-line + + // Create a mock request. + $request = new WP_REST_Request( 'POST', $this->get_endpoint()->get_full_endpoint( $post_id . '/add' ) ); + + $smart_link_data = array( + 'uid' => md5( 'link1' ), + 'href' => 'http://example.com/1', + 'title' => 'Example 1', + 'text' => 'Example 1', + 'offset' => 0, + ); + $request->set_param( 'link', $smart_link_data ); + + // Dispatch the request. + $response = rest_get_server()->dispatch( $request ); + + // Assert that the response is a WP_REST_Response and contains the correct data. + self::assertInstanceOf( WP_REST_Response::class, $response ); + + /** + * The response data. + * + * @var array> $data The response data. + */ + $data = $response->get_data(); + + self::assertNotTrue( $response->is_error() ); + + self::assertArrayHasKey( 'data', $data ); + self::assertIsObject( $data['data'] ); + + $smart_link_attributes = array( + 'smart_link_id', + 'uid', + 'href', + 'text', + 'offset', + 'applied', + 'source', + 'destination', + ); + + foreach ( $smart_link_attributes as $attribute ) { + self::assertObjectHasProperty( $attribute, $data['data'] ); + } + } + + /** + * Tests that the add_multiple_smart_links method returns a valid response when adding multiple smart links. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Smart_Linking::add_multiple_smart_links + * @uses \Parsely\Models\Base_Model::__construct + * @uses \Parsely\Models\Base_Model::serialize + * @uses \Parsely\Models\Smart_Link::__construct + * @uses \Parsely\Models\Smart_Link::deserialize + * @uses \Parsely\Models\Smart_Link::exists + * @uses \Parsely\Models\Smart_Link::generate_uid + * @uses \Parsely\Models\Smart_Link::get_post_id_by_url + * @uses \Parsely\Models\Smart_Link::get_smart_link + * @uses \Parsely\Models\Smart_Link::get_smart_link_object_by_uid + * @uses \Parsely\Models\Smart_Link::load + * @uses \Parsely\Models\Smart_Link::save + * @uses \Parsely\Models\Smart_Link::set_href + * @uses \Parsely\Models\Smart_Link::set_source_post_id + * @uses \Parsely\Models\Smart_Link::set_uid + * @uses \Parsely\Models\Smart_Link::to_array + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::current_user_can_use_pch_feature + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_add_multiple_smart_links_returns_valid_response(): void { + // Create mocked post. + $post = WP_UnitTestCase_Base::factory()->post->create_and_get(); + self::assertNotWPError( $post ); + $post_id = $post->ID; // @phpstan-ignore-line + + // Create a mock request. + $request = new WP_REST_Request( 'POST', $this->get_endpoint()->get_full_endpoint( $post_id . '/add-multiple' ) ); + + $smart_links_data = array( + array( + 'uid' => md5( 'link1' ), + 'href' => 'http://example.com/1', + 'title' => 'Example 1', + 'text' => 'Example 1', + 'offset' => 0, + ), + array( + 'uid' => md5( 'link2' ), + 'href' => 'http://example.com/2', + 'title' => 'Example 2', + 'text' => 'Example 2', + 'offset' => 0, + ), + array( + 'uid' => md5( 'link3' ), + 'href' => 'http://example.com/3', + 'title' => 'Example 3', + 'text' => 'Example 3', + 'offset' => 0, + ), + ); + $request->set_param( 'links', $smart_links_data ); + + // Dispatch the request. + $response = rest_get_server()->dispatch( $request ); + + // Assert that the response is a WP_REST_Response and contains the correct data. + self::assertInstanceOf( WP_REST_Response::class, $response ); + + /** + * The response data. + * + * @var array> $data The response data. + */ + $data = $response->get_data(); + + self::assertNotTrue( $response->is_error() ); + + self::assertArrayHasKey( 'data', $data ); + self::assertArrayHasKey( 'added', $data['data'] ); + self::assertIsArray( $data['data']['added'] ); + self::assertCount( 3, $data['data']['added'] ); + + $smart_link_attributes = array( + 'smart_link_id', + 'uid', + 'href', + 'text', + 'offset', + 'applied', + 'source', + 'destination', + ); + + foreach ( $data['data']['added'] as $smart_link ) { + foreach ( $smart_link_attributes as $attribute ) { + self::assertArrayHasKey( $attribute, $smart_link ); + } + } + } +} diff --git a/tests/Integration/RestAPI/ContentHelper/EndpointTitleSuggestionsTest.php b/tests/Integration/RestAPI/ContentHelper/EndpointTitleSuggestionsTest.php new file mode 100644 index 000000000..34969bd2f --- /dev/null +++ b/tests/Integration/RestAPI/ContentHelper/EndpointTitleSuggestionsTest.php @@ -0,0 +1,180 @@ +api_controller = new Content_Helper_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Title_Suggestions( $this->api_controller ); + + parent::set_up(); + } + + /** + * Gets the test endpoint instance. + * + * @since 3.17.0 + * + * @return Endpoint_Title_Suggestions + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Tests that the endpoint is correctly registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Title_Suggestions::register_routes + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + */ + public function test_route_is_registered(): void { + $routes = rest_get_server()->get_routes(); + + // Check that the title-suggestions/generate route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( 'generate' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the POST method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'POST', $route_data[0]['methods'] ); + } + + /** + * Tests that the generate_titles method returns a valid response. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Title_Suggestions::generate_titles + * @uses \Parsely\Parsely::get_suggestions_api + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Services\Base_API_Service::__construct + * @uses \Parsely\Services\Base_API_Service::register_endpoint + * @uses \Parsely\Services\Base_Service_Endpoint::__construct + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Brief::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Headline::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Linked_Reference::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Suggestions_API_Service::register_endpoints + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_generate_titles_returns_valid_response(): void { + // Mock the Suggestions API `get_title_suggestions` method to return a list of titles. + $mock_suggestions_api = $this->createMock( Suggestions_API_Service::class ); + $mock_suggestions_api->expects( self::once() ) + ->method( 'get_title_suggestions' ) + ->willReturn( array( 'title1', 'title2', 'title3' ) ); + + self::set_protected_property( $this->get_endpoint(), 'suggestions_api', $mock_suggestions_api ); + + // Create a mock request. + $request = new WP_REST_Request( 'POST', '/title-suggestions/generate' ); + $request->set_param( 'text', 'Test content' ); + $request->set_param( 'limit', 3 ); + $request->set_param( 'style', 'neutral' ); + $request->set_param( 'persona', 'journalist' ); + + // Call the generate_titles method. + $response = $this->get_endpoint()->generate_titles( $request ); + + // Assert that the response is a WP_REST_Response and contains the correct data. + self::assertInstanceOf( WP_REST_Response::class, $response ); + + /** + * The response data. + * + * @var array $data The response data. + */ + $data = $response->get_data(); + self::assertArrayHasKey( 'data', $data ); + self::assertEquals( array( 'title1', 'title2', 'title3' ), $data['data'] ); + } + + /** + * Tests that the generate_titles method returns an error if Suggest_Headline_API fails. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Content_Helper\Endpoint_Title_Suggestions::generate_titles + * @uses \Parsely\Parsely::get_suggestions_api + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\Services\Base_API_Service::__construct + * @uses \Parsely\Services\Base_API_Service::register_endpoint + * @uses \Parsely\Services\Base_Service_Endpoint::__construct + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Brief::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Headline::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Linked_Reference::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Suggestions_API_Service::register_endpoints + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_generate_titles_returns_error_on_failure(): void { + // Mock the Suggestions API `get_title_suggestions` method to return an error. + $mock_suggestions_api = $this->createMock( Suggestions_API_Service::class ); + $mock_suggestions_api->expects( self::once() ) + ->method( 'get_title_suggestions' ) + ->willReturn( new WP_Error( 'api_error', 'API request failed' ) ); + + self::set_protected_property( $this->get_endpoint(), 'suggestions_api', $mock_suggestions_api ); + + // Create a mock request. + $request = new WP_REST_Request( 'POST', '/title-suggestions/generate' ); + $request->set_param( 'text', 'Test content' ); + $request->set_param( 'limit', 3 ); + $request->set_param( 'style', 'neutral' ); + $request->set_param( 'persona', 'journalist' ); + + // Call the generate_titles method. + $response = $this->get_endpoint()->generate_titles( $request ); + + // Assert that the response is a WP_Error. + self::assertInstanceOf( WP_Error::class, $response ); + self::assertEquals( 'api_error', $response->get_error_code() ); + } +} diff --git a/tests/Integration/RestAPI/RestAPIControllerTest.php b/tests/Integration/RestAPI/RestAPIControllerTest.php new file mode 100644 index 000000000..833d3600a --- /dev/null +++ b/tests/Integration/RestAPI/RestAPIControllerTest.php @@ -0,0 +1,57 @@ +test_controller = new REST_API_Controller( $parsely ); + } + + /** + * Tests the constructor sets up the correct namespace and version. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\REST_API_Controller::__construct + * @uses \Parsely\REST_API\REST_API_Controller::get_full_namespace + */ + public function test_constructor_sets_up_namespace_and_version(): void { + self::assertEquals( 'wp-parsely/v2', $this->test_controller->get_full_namespace() ); + } +} diff --git a/tests/Integration/RestAPI/Settings/BaseSettingsEndpointTest.php b/tests/Integration/RestAPI/Settings/BaseSettingsEndpointTest.php new file mode 100644 index 000000000..aa5a4d9e4 --- /dev/null +++ b/tests/Integration/RestAPI/Settings/BaseSettingsEndpointTest.php @@ -0,0 +1,221 @@ + $extra_data Any Extra key/value pairs to add. + * @return array The generated JSON array. + */ + abstract protected function generate_json( + ?string $metric = null, + ?string $period = null, + array $extra_data = array() + ): array; + + /** + * Returns the default value for the endpoint. + * + * @since 3.17.0 + * + * @return array The default value for the endpoint. + */ + abstract protected function get_default_value(): array; + + /** + * Verifies that the route is registered. + * + * @since 3.17.0 + */ + protected function run_test_route_is_registered(): void { + $routes = rest_get_server()->get_routes(); + + // Check that the main route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( '/' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the GET and PUT methods. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'GET', $route_data[0]['methods'] ); + self::assertArrayHasKey( 'PUT', $route_data[0]['methods'] ); + + // Check the `/get` route. + $expected_route = $this->get_endpoint()->get_full_endpoint( '/get' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the GET method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'GET', $route_data[0]['methods'] ); + + // Check the `/set` route. + $expected_route = $this->get_endpoint()->get_full_endpoint( '/set' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the PUT method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'PUT', $route_data[0]['methods'] ); + } + + /** + * Verifies that the endpoint returns the correct default value. + * + * @since 3.13.0 + * @since 3.17.0 Moved from the old BaseUserMetaEndpointTest class. + */ + public function run_test_endpoint_returns_value_on_get_request(): void { + $this->set_current_user_to_admin(); + + $value = rest_do_request( + new WP_REST_Request( + 'GET', + $this->get_endpoint()->get_full_endpoint( '/get' ) + ) + )->get_data(); + $value = $this->wp_json_encode( $value ); + + $expected = $this->wp_json_encode( + $this->get_default_value() + ); + + self::assertSame( $expected, $value ); + } + + /** + * Provides data for testing PUT requests. + * + * @since 3.13.0 + * @since 3.17.0 Moved from the old BaseUserMetaEndpointTest class. + * + * @return iterable + */ + public function provide_put_requests_data(): iterable { + $default_value = $this->generate_json( 'views', '7d' ); + $valid_value = $this->generate_json( 'avg_engaged', '1h' ); + + // Valid non-default value. It should be returned unmodified. + yield 'valid period and metric values' => array( + 'test_data' => $valid_value, + 'expected' => $valid_value, + ); + + // Missing or problematic keys. Defaults should be used for the missing or problematic keys. + yield 'valid period value, no metric value' => array( + 'test_data' => $this->generate_json( null, '1h' ), + 'expected' => $this->generate_json( 'views', '1h' ), + ); + yield 'valid metric value, no period value' => array( + 'test_data' => $this->generate_json( 'avg_engaged' ), + 'expected' => $this->generate_json( 'avg_engaged', '7d' ), + ); + yield 'no values' => array( + 'test_data' => $this->generate_json(), + 'expected' => $default_value, + ); + + // Invalid values. They should be adjusted to their defaults. + yield 'invalid period value' => array( + 'test_data' => $this->generate_json( 'avg_engaged', 'invalid' ), + 'expected' => $this->generate_json( 'avg_engaged', '7d' ), + ); + yield 'invalid metric value' => array( + 'test_data' => $this->generate_json( 'invalid', '1h' ), + 'expected' => $this->generate_json( 'views', '1h' ), + ); + yield 'invalid period and metric values' => array( + 'test_data' => $this->generate_json( 'invalid', 'invalid' ), + 'expected' => $default_value, + ); + + // Invalid extra data passed. Any such data should be discarded. + yield 'invalid additional value' => array( + 'test_data' => $this->generate_json( + 'avg_engaged', + '1h', + array( 'invalid' ) + ), + 'expected' => $valid_value, + ); + yield 'invalid additional key/value pair' => array( + 'test_data' => $this->generate_json( + 'avg_engaged', + '1h', + array( 'invalid_key' => 'invalid_value' ) + ), + 'expected' => $valid_value, + ); + } + + /** + * Sends a PUT request to the endpoint. + * + * @since 3.13.0 + * @since 3.17.0 Moved from the old BaseUserMetaEndpointTest class. + * + * @param array $data The data to be sent in the request. + * @return array The response returned by the endpoint. + */ + protected function send_put_request( array $data ): array { + $this->set_current_user_to_admin(); + $result = $this->send_wp_rest_request( + 'PUT', + $this->get_endpoint()->get_full_endpoint( '/set' ), + $this->wp_json_encode( $data ) + ); + + if ( ! is_array( $result ) ) { + return array(); + } + + return $result; + } + + /** + * Verifies that the endpoint is not available if the API Secret is not set. + * + * This test is disabled since the endpoint does not require an API Secret. + * + * @since 3.17.0 + * + * @coversNothing + */ + public function test_is_available_to_current_user_returns_error_api_secret_not_set(): void { + self::assertTrue( true ); + } + + /** + * Verifies that the endpoint is not available if the Site ID is not set. + * + * This test is disabled since the endpoint does not require a Site ID. + * + * @since 3.17.0 + * + * @coversNothing + */ + public function test_is_available_to_current_user_returns_error_site_id_not_set(): void { + self::assertTrue( true ); + } +} diff --git a/tests/Integration/RestAPI/Settings/EndpointDashboardWidgetSettingsTest.php b/tests/Integration/RestAPI/Settings/EndpointDashboardWidgetSettingsTest.php new file mode 100644 index 000000000..7d2f6ca6b --- /dev/null +++ b/tests/Integration/RestAPI/Settings/EndpointDashboardWidgetSettingsTest.php @@ -0,0 +1,204 @@ +api_controller = new Content_Helper_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Dashboard_Widget_Settings( $this->api_controller ); + + parent::set_up(); + } + + /** + * Returns the endpoint to be used in tests. + * + * @since 3.17.0 + * + * @return \Parsely\REST_API\Base_Endpoint + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Returns the default value for the endpoint. + * + * @since 3.17.0 + * + * @return array The default value for the endpoint. + */ + public function get_default_value(): array { + return array( + 'Metric' => 'views', + 'Period' => '7d', + ); + } + + /** + * Generates a JSON array for the passed period, metric, and extra data. + * + * @since 3.13.0 + * @since 3.17.0 Moved from old test class. + * + * @param string|null $metric The Metric value. + * @param string|null $period The Period value. + * @param array $extra_data Any Extra key/value pairs to add. + * @return array The generated JSON array. + */ + protected function generate_json( + ?string $metric = null, + ?string $period = null, + array $extra_data = array() + ): array { + $array = $this->get_default_value(); + unset( $array['Metric'], $array['Period'] ); + + if ( null !== $metric ) { + $array['Metric'] = $metric; + } + + if ( null !== $period ) { + $array['Period'] = $period; + } + + ksort( $array ); + + return array_merge( $array, $extra_data ); + } + + /** + * Verifies that the route is registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::register_routes + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_endpoint_name + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_subvalues_specs + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + parent::run_test_route_is_registered(); + } + + /** + * Verifies that the endpoint returns the correct default settings. + * + * @since 3.13.0 + * @since 3.17.0 Moved from old test class. + * + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::process_request + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_settings + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::register_routes + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_endpoint_name + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_meta_key + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_subvalues_specs + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_endpoint_returns_value_on_get_request(): void { + parent::run_test_endpoint_returns_value_on_get_request(); + } + + /** + * Verifies that the endpoint can correctly handle PUT requests. + * + * @since 3.13.0 + * @since 3.17.0 Moved from old test class. + * + * @param array $test_data The data to send in the PUT request. + * @param array $expected The expected value of the setting after the PUT request. + * + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_subvalues_specs + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::sanitize_subvalue + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::sanitize_value + * @covers \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::set_settings + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_settings + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_valid_values + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::register_routes + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_default + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_endpoint_name + * @uses \Parsely\REST_API\Settings\Endpoint_Dashboard_Widget_Settings::get_meta_key + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @dataProvider provide_put_requests_data + */ + public function test_endpoint_correctly_handles_put_requests( + array $test_data, + array $expected + ): void { + $value = $this->send_put_request( $test_data ); + self::assertSame( $expected, $value ); + } +} diff --git a/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php b/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php new file mode 100644 index 000000000..c87f1e4c0 --- /dev/null +++ b/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php @@ -0,0 +1,312 @@ +api_controller = new Content_Helper_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Editor_Sidebar_Settings( $this->api_controller ); + + parent::set_up(); + } + + /** + * Returns the endpoint to be used in tests. + * + * @since 3.17.0 + * + * @return \Parsely\REST_API\Base_Endpoint + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Returns the default value for the endpoint. + * + * @since 3.17.0 + * + * @return array The default value for the endpoint. + */ + public function get_default_value(): array { + return array( + 'InitialTabName' => 'tools', + 'PerformanceStats' => array( + 'Period' => '7d', + 'VisibleDataPoints' => array( 'views', 'visitors', 'avgEngaged', 'recirculation' ), + 'VisiblePanels' => array( 'overview', 'categories', 'referrers' ), + ), + 'RelatedPosts' => array( + 'FilterBy' => 'unavailable', + 'FilterValue' => '', + 'Metric' => 'views', + 'Open' => false, + 'Period' => '7d', + ), + 'SmartLinking' => array( + 'MaxLinks' => 10, + 'MaxLinkWords' => 4, + 'Open' => false, + ), + 'TitleSuggestions' => array( + 'Open' => false, + 'Persona' => 'journalist', + 'Tone' => 'neutral', + ), + ); + } + + /** + * Verifies that the route is registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::register_routes + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_endpoint_name + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_subvalues_specs + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + parent::run_test_route_is_registered(); + } + + /** + * Verifies that the endpoint returns the correct default settings. + * + * @since 3.13.0 + * @since 3.17.0 Moved from old test class. + * + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::process_request + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_settings + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @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 + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_subvalues_specs + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_endpoint_returns_value_on_get_request(): void { + parent::run_test_endpoint_returns_value_on_get_request(); + } + + /** + * Verifies that the endpoint can correctly handle PUT requests. + * + * @param array $test_data The data to send in the PUT request. + * @param array $expected The expected value of the setting after the PUT request. + * + * @since 3.13.0 + * @since 3.17.0 Moved from old test class. + * + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_subvalues_specs + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::sanitize_subvalue + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::sanitize_value + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::set_settings + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_nested_specs + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_settings + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_valid_values + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::register_routes + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_default + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_endpoint_name + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_meta_key + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @dataProvider provide_put_requests_data* + */ + public function test_endpoint_correctly_handles_put_requests( + array $test_data, + array $expected + ): void { + $value = $this->send_put_request( $test_data ); + self::assertSame( $expected, $value ); + } + + /** + * Tests that the endpoint can correctly handle PUT requests with valid + * nested PerformanceStats values. + * + * @since 3.14.0 + * @since 3.17.0 Moved from old test class. + * + * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::sanitize_subvalue + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Content_Helper\Content_Helper_Controller::get_route_prefix + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::__construct + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_nested_specs + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_settings + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_valid_values + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::init + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::register_routes + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::sanitize_value + * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::set_settings + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_endpoint_name + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_meta_key + * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_subvalues_specs + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_valid_nested_performance_stats_settings_period(): void { + $this->set_current_user_to_admin(); + + $value = $this->send_put_request( + $this->generate_json( + 'views', + '7d', + array( + 'PerformanceStats' => array( + 'Period' => '1h', + 'VisibleDataPoints' => array( 'views', 'avgEngaged', 'recirculation' ), + 'VisiblePanels' => array( 'overview', 'referrers' ), + ), + ) + ) + ); + + $expected = array_merge( + $this->get_default_value(), + array( + 'PerformanceStats' => array( + 'Period' => '1h', + 'VisibleDataPoints' => array( 'views', 'avgEngaged', 'recirculation' ), + 'VisiblePanels' => array( 'overview', 'referrers' ), + ), + ) + ); + + self::assertSame( $expected, $value ); + } + + /** + * Generates a JSON array for the passed period, metric, and extra data. + * + * @since 3.13.0 + * @since 3.17.0 Moved from old test class. + * + * @param string|null $metric The RelatedPostsMetric value. + * @param string|null $period The RelatedPostsPeriod value. + * @param array $extra_data Any Extra key/value pairs to add. + * @return array The generated JSON array. + */ + protected function generate_json( + ?string $metric = null, + ?string $period = null, + array $extra_data = array() + ): array { + $array = $this->get_default_value(); + assert( is_array( $array['RelatedPosts'] ) ); + + unset( $array['RelatedPosts']['Metric'], $array['RelatedPosts']['Period'] ); + + if ( null !== $metric ) { + $array['RelatedPosts']['Metric'] = $metric; + } + + if ( null !== $period ) { + $array['RelatedPosts']['Period'] = $period; + } + + $merged_array = array_merge( $array, $extra_data ); + + $this->ksortRecursive( $merged_array, SORT_NATURAL | SORT_FLAG_CASE ); + + return $merged_array; + } + + /** + * Recursively sorts an array by key using a specified sort flag. + * + * @since 3.14.3 + * @since 3.17.0 Moved from old test class. + * + * @param array &$unsorted_array The array to be sorted, passed by reference. + * @param int $sort_flags Optional sorting flags. Defaults to SORT_REGULAR. + */ + private function ksortRecursive( array &$unsorted_array, int $sort_flags = SORT_REGULAR ): void { + ksort( $unsorted_array, $sort_flags ); + foreach ( $unsorted_array as &$value ) { + if ( is_array( $value ) ) { + $this->ksortRecursive( $value, $sort_flags ); + } + } + } +} diff --git a/tests/Integration/RestAPI/Stats/EndpointPostTest.php b/tests/Integration/RestAPI/Stats/EndpointPostTest.php new file mode 100644 index 000000000..a990af693 --- /dev/null +++ b/tests/Integration/RestAPI/Stats/EndpointPostTest.php @@ -0,0 +1,652 @@ +api_controller = new Stats_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Post( $this->api_controller ); + + parent::set_up(); + } + + /** + * Gets the test endpoint instance. + * + * @since 3.17.0 + * + * @return Endpoint_Post + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Verifies that the route is registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Post::register_routes + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::get_registered_routes + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Post::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::register_rest_route_with_post_id + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + $routes = rest_get_server()->get_routes(); + $registered_routes = $this->get_endpoint()->get_registered_routes(); + + // Assert that the routes are registered when the filter returns true. + foreach ( $registered_routes as $route ) { + $expected_route = $this->get_endpoint()->get_full_endpoint( $route ); + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the GET method, since all + // the routes in this endpoint are GET routes. + self::assertArrayHasKey( 'GET', $route_data[0]['methods'] ); + } + } + + /** + * Verifies that the endpoint is not available if the API Secret is not set. + * + * @covers \Parsely\REST_API\Stats\Endpoint_Post::is_available_to_current_user + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Post::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Post::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::register_rest_route_with_post_id + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::validate_post_id + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_access_error_if_api_secret_is_not_set(): void { + $test_post_id = $this->create_test_post(); + TestCase::set_options( + array( + 'apikey' => 'test', + ) + ); + $route = $this->get_endpoint()->get_full_endpoint( '/' . $test_post_id . '/details' ); + $response = rest_get_server()->dispatch( + new WP_REST_Request( 'GET', $route ) + ); + + $error = $response->as_error(); + self::assertNotNull( $error ); + self::assertSame( 403, $response->get_status() ); + self::assertSame( 'parsely_api_secret_not_set', $error->get_error_code() ); + self::assertSame( + 'A Parse.ly API Secret must be set in site options to use this endpoint', + $error->get_error_message() + ); + } + + /** + * Verifies forbidden error when current user doesn't have proper + * capabilities. + * + * @covers \Parsely\REST_API\Stats\Endpoint_Post::is_available_to_current_user + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Post::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Post::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::register_rest_route_with_post_id + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::validate_post_id + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_access_of_stats_post_endpoint_is_forbidden(): void { + $test_post_id = $this->create_test_post(); + TestCase::set_options( + array( + 'apikey' => 'test-api-key', + 'api_secret' => 'test-secret', + ) + ); + $this->set_current_user_to_contributor(); + + $route = $this->get_endpoint()->get_full_endpoint( '/' . $test_post_id . '/details' ); + $response = rest_get_server()->dispatch( + new WP_REST_Request( 'GET', $route ) + ); + /** + * Variable. + * + * @var WP_Error $error + */ + $error = $response->as_error(); + + self::assertSame( 403, $response->get_status() ); + self::assertSame( 'rest_forbidden', $error->get_error_code() ); + self::assertSame( + 'Sorry, you are not allowed to do that.', + $error->get_error_message() + ); + } + + /** + * Verifies that calls to the stats/{post_id}/details endpoint return the + * expected data, in the expected format. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Post::get_post_details + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_api_secret + * @uses \Parsely\Parsely::get_dash_url + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::get_url_with_itm_source + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Post::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Post::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::extract_post_data + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::set_itm_source_from_request + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::register_rest_route_with_post_id + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::validate_post_id + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @uses \Parsely\Utils\Utils::get_formatted_duration + * @uses \Parsely\Utils\Utils::parsely_is_https_supported + */ + public function test_get_details(): void { + $test_post_id = $this->create_test_post(); + $route = $this->get_endpoint()->get_full_endpoint( '/' . $test_post_id . '/details' ); + + TestCase::set_options( + array( + 'apikey' => 'example.com', + 'api_secret' => 'test-secret', + ) + ); + $this->set_current_user_to_admin(); + + $dispatched = 0; + + add_filter( + 'pre_http_request', + function () use ( &$dispatched ): array { + $dispatched++; + return array( + 'body' => ' + {"data":[{ + "avg_engaged": 1.911, + "metrics": { + "views": 2158, + "visitors": 1537 + }, + "url": "https://example.com" + }]} + ', + ); + } + ); + + $response = rest_get_server()->dispatch( new WP_REST_Request( 'GET', $route ) ); + + /** + * The response data. + * + * @var array $response_data + */ + $response_data = $response->get_data(); + + self::assertSame( 1, $dispatched ); + self::assertSame( 200, $response->get_status() ); + self::assertEquals( + array( + array( + 'avgEngaged' => '1:55', + 'dashUrl' => Parsely::DASHBOARD_BASE_URL . '/example.com/find?url=https%3A%2F%2Fexample.com', + 'id' => 'https://example.com', + 'postId' => 0, + 'url' => 'https://example.com', + 'views' => '2,158', + 'visitors' => '1,537', + 'rawUrl' => 'https://example.com', + ), + ), + $response_data['data'] + ); + } + + /** + * Verifies that calls to the stats/{post_id}/referrers endpoint return the + * expected data, in the expected format. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Post::get_post_referrers + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_api_secret + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Post::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Post::generate_referrer_types_data + * @uses \Parsely\REST_API\Stats\Endpoint_Post::generate_referrers_data + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_i18n_percentage + * @uses \Parsely\REST_API\Stats\Endpoint_Post::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::set_itm_source_from_request + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::register_rest_route_with_post_id + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::validate_post_id + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @uses \Parsely\Utils\Utils::convert_to_positive_integer + */ + public function test_get_referrers(): void { + $test_post_id = $this->create_test_post(); + $route = $this->get_endpoint()->get_full_endpoint( '/' . $test_post_id . '/referrers' ); + + TestCase::set_options( + array( + 'apikey' => 'example.com', + 'api_secret' => 'test-secret', + ) + ); + $this->set_current_user_to_admin(); + + $dispatched = 0; + + add_filter( + 'pre_http_request', + function () use ( &$dispatched ): array { + $dispatched++; + return array( + 'body' => '{"data":[ + { + "metrics": {"referrers_views": 1500}, + "name": "google", + "type": "search" + }, + { + "metrics": {"referrers_views": 100}, + "name": "blog.parse.ly", + "type": "internal" + }, + { + "metrics": {"referrers_views": 50}, + "name": "bing", + "type": "search" + }, + { + "metrics": {"referrers_views": 30}, + "name": "facebook.com", + "type": "social" + }, + { + "metrics": {"referrers_views": 10}, + "name": "okt.to", + "type": "other" + }, + { + "metrics": {"referrers_views": 10}, + "name": "yandex", + "type": "search" + }, + { + "metrics": {"referrers_views": 10}, + "name": "parse.ly", + "type": "internal" + }, + { + "metrics": {"referrers_views": 10}, + "name": "yahoo!", + "type": "search" + }, + { + "metrics": {"referrers_views": 5}, + "name": "site1.com", + "type": "other" + }, + { + "metrics": {"referrers_views": 5}, + "name": "link.site2.com", + "type": "other" + } + ]}', + ); + } + ); + + $expected_top = array( + 'direct' => array( + 'views' => '770', + 'viewsPercentage' => '30.80', + 'datasetViewsPercentage' => '31.43', + ), + 'google' => array( + 'views' => '1,500', + 'viewsPercentage' => '60.00', + 'datasetViewsPercentage' => '61.22', + ), + 'blog.parse.ly' => array( + 'views' => '100', + 'viewsPercentage' => '4.00', + 'datasetViewsPercentage' => '4.08', + ), + 'bing' => array( + 'views' => '50', + 'viewsPercentage' => '2.00', + 'datasetViewsPercentage' => '2.04', + ), + 'facebook.com' => array( + 'views' => '30', + 'viewsPercentage' => '1.20', + 'datasetViewsPercentage' => '1.22', + ), + 'totals' => array( + 'views' => '2,450', + 'viewsPercentage' => '98.00', + 'datasetViewsPercentage' => '100.00', + ), + ); + + $expected_types = array( + 'social' => array( + 'views' => '30', + 'viewsPercentage' => '1.20', + ), + 'search' => array( + 'views' => '1,570', + 'viewsPercentage' => '62.80', + ), + 'other' => array( + 'views' => '20', + 'viewsPercentage' => '0.80', + ), + 'internal' => array( + 'views' => '110', + 'viewsPercentage' => '4.40', + ), + 'direct' => array( + 'views' => '770', + 'viewsPercentage' => '30.80', + ), + 'totals' => array( + 'views' => '2,500', + 'viewsPercentage' => '100.00', + ), + ); + + $request = new WP_REST_Request( 'GET', $route ); + $request->set_param( 'total_views', '2,500' ); + + $response = rest_get_server()->dispatch( $request ); + + /** + * The response data. + * + * @var array $response_data + */ + $response_data = $response->get_data(); + + self::assertSame( 1, $dispatched ); + self::assertSame( 200, $response->get_status() ); + self::assertEquals( + array( + 'top' => $expected_top, + 'types' => $expected_types, + ), + $response_data['data'] + ); + } + + /** + * Verifies that calls to the stats/{post_id}/related endpoint return the + * expected data, in the expected format. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Post::get_related_posts + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_api_secret + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::get_url_with_itm_source + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Post::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Post::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Post::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::set_itm_source_from_request + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_of_url + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::register_rest_route_with_post_id + * @uses \Parsely\REST_API\Use_Post_ID_Parameter_Trait::validate_post_id + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_get_related_posts(): void { + $test_post_id = $this->create_test_post(); + $route = $this->get_endpoint()->get_full_endpoint( '/' . $test_post_id . '/related' ); + + TestCase::set_options( + array( + 'apikey' => 'example.com', + 'api_secret' => 'test-secret', + ) + ); + $this->set_current_user_to_admin(); + + $dispatched = 0; + + add_filter( + 'pre_http_request', + function () use ( &$dispatched ): array { + $dispatched++; + return array( + 'body' => '{"data":[ + { + "image_url":"https:\/\/example.com\/img.png", + "thumb_url_medium":"https:\/\/example.com\/thumb.png", + "title":"something", + "url":"https:\/\/example.com" + }, + { + "image_url":"https:\/\/example.com\/img2.png", + "thumb_url_medium":"https:\/\/example.com\/thumb2.png", + "title":"something2", + "url":"https:\/\/example.com\/2" + } + ]}', + ); + } + ); + + $response = rest_get_server()->dispatch( new WP_REST_Request( 'GET', $route ) ); + /** + * The response data. + * + * @var array $response_data + */ + $response_data = $response->get_data(); + + self::assertSame( 1, $dispatched ); + self::assertSame( 200, $response->get_status() ); + self::assertEquals( + array( + array( + 'image_url' => 'https://example.com/img.png', + 'thumb_url_medium' => 'https://example.com/thumb.png', + 'title' => 'something', + 'url' => 'https://example.com', + ), + array( + 'image_url' => 'https://example.com/img2.png', + 'thumb_url_medium' => 'https://example.com/thumb2.png', + 'title' => 'something2', + 'url' => 'https://example.com/2', + ), + ), + $response_data['data'] + ); + } +} diff --git a/tests/Integration/RestAPI/Stats/EndpointPostsTest.php b/tests/Integration/RestAPI/Stats/EndpointPostsTest.php new file mode 100644 index 000000000..0cde8e31f --- /dev/null +++ b/tests/Integration/RestAPI/Stats/EndpointPostsTest.php @@ -0,0 +1,335 @@ +api_controller = new Stats_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Posts( $this->api_controller ); + + parent::set_up(); + } + + /** + * Gets the test endpoint instance. + * + * @since 3.17.0 + * + * @return Endpoint_Posts + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Verifies that the route is registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Posts::register_routes + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + $routes = rest_get_server()->get_routes(); + + // Check that the route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( '/' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the GET method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'GET', $route_data[0]['methods'] ); + } + + /** + * Verifies that the endpoint is not available if the API Secret is not set. + * + * @covers \Parsely\REST_API\Stats\Endpoint_Posts::is_available_to_current_user + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_access_error_if_api_secret_is_not_set(): void { + TestCase::set_options( + array( + 'apikey' => 'test', + ) + ); + $route = $this->get_endpoint()->get_full_endpoint( '/' ); + $response = rest_get_server()->dispatch( + new WP_REST_Request( 'GET', $route ) + ); + + $error = $response->as_error(); + self::assertNotNull( $error ); + self::assertSame( 403, $response->get_status() ); + self::assertSame( 'parsely_api_secret_not_set', $error->get_error_code() ); + self::assertSame( + 'A Parse.ly API Secret must be set in site options to use this endpoint', + $error->get_error_message() + ); + } + + /** + * Verifies forbidden error when current user doesn't have proper + * capabilities. + * + * @covers \Parsely\REST_API\Stats\Endpoint_Posts::is_available_to_current_user + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_access_of_stats_posts_endpoint_is_forbidden(): void { + TestCase::set_options( + array( + 'apikey' => 'test-api-key', + 'api_secret' => 'test-secret', + ) + ); + $this->set_current_user_to_contributor(); + + $route = $this->get_endpoint()->get_full_endpoint( '/' ); + $response = rest_get_server()->dispatch( + new WP_REST_Request( 'GET', $route ) + ); + /** + * Variable. + * + * @var WP_Error $error + */ + $error = $response->as_error(); + + self::assertSame( 403, $response->get_status() ); + self::assertSame( 'rest_forbidden', $error->get_error_code() ); + self::assertSame( + 'Sorry, you are not allowed to do that.', + $error->get_error_message() + ); + } + + /** + * Verifies that calls to the endpoint return the expected data, in the + * expected format. + * + * @covers \Parsely\REST_API\Stats\Endpoint_Posts::get_posts + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_api_secret + * @uses \Parsely\Parsely::get_dash_url + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::get_url_with_itm_source + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::apply_capability_filters + * @uses \Parsely\REST_API\Base_Endpoint::get_default_access_capability + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\Base_Endpoint::validate_site_id_and_secret + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + * @uses \Parsely\Utils\Utils::get_date_format + * @uses \Parsely\Utils\Utils::parsely_is_https_supported + */ + public function test_get_posts(): void { + TestCase::set_options( + array( + 'apikey' => 'example.com', + 'api_secret' => 'test-secret', + ) + ); + $this->set_current_user_to_admin(); + + $dispatched = 0; + $date_format = Utils::get_date_format(); + + add_filter( + 'pre_http_request', + function () use ( &$dispatched ): array { + $dispatched++; + + return array( + 'body' => '{"data":[ + { + "author": "Aakash Shah", + "metrics": {"views": 142}, + "pub_date": "2020-04-06T13:30:58", + "thumb_url_medium": "https://images.parsely.com/XCmTXuOf8yVbUYTxj2abQ4RSDkM=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/06/Web-Analytics-Tool.png%3Fw%3D150%26h%3D150%26crop%3D1", + "title": "9 Types of Web Analytics Tools \u2014 And How to Know Which Ones You Really Need", + "url": "https://blog.parse.ly/web-analytics-software-tools/?itm_source=parsely-api" + }, + { + "author": "Stephanie Schwartz and Andrew Butler", + "metrics": {"views": 40}, + "pub_date": "2021-04-30T20:30:24", + "thumb_url_medium": "https://images.parsely.com/ap3YSufqxnLpz6zzQshoks3snXI=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/05/pexels-brett-jordan-998501-1024x768-2.jpeg%3Fw%3D150%26h%3D150%26crop%3D1", + "title": "5 Tagging Best Practices For Getting the Most Out of Your Content Strategy", + "url": "https://blog.parse.ly/5-tagging-best-practices-content-strategy/?itm_source=parsely-api" + } + ]}', + ); + } + ); + + $rest_request = new WP_REST_Request( 'GET', '/wp-parsely/v2/stats/posts' ); + $rest_request->set_param( 'itm_source', 'wp-parsely-content-helper' ); + + $response = rest_get_server()->dispatch( $rest_request ); + + /** + * The response data. + * + * @var array $response_data + */ + $response_data = $response->get_data(); + + self::assertSame( 1, $dispatched ); + self::assertSame( 200, $response->get_status() ); + self::assertEquals( + array( + array( + 'author' => 'Aakash Shah', + 'date' => wp_date( $date_format, strtotime( '2020-04-06T13:30:58' ) ), + 'id' => 'https://blog.parse.ly/web-analytics-software-tools/', + 'dashUrl' => PARSELY::DASHBOARD_BASE_URL . '/example.com/find?url=https%3A%2F%2Fblog.parse.ly%2Fweb-analytics-software-tools%2F', + 'thumbnailUrl' => 'https://images.parsely.com/XCmTXuOf8yVbUYTxj2abQ4RSDkM=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/06/Web-Analytics-Tool.png%3Fw%3D150%26h%3D150%26crop%3D1', + 'title' => '9 Types of Web Analytics Tools — And How to Know Which Ones You Really Need', + 'url' => 'https://blog.parse.ly/web-analytics-software-tools/?itm_source=wp-parsely-content-helper', + 'views' => '142', + 'postId' => 0, + 'rawUrl' => 'https://blog.parse.ly/web-analytics-software-tools/', + ), + array( + 'author' => 'Stephanie Schwartz and Andrew Butler', + 'date' => wp_date( $date_format, strtotime( '2021-04-30T20:30:24' ) ), + 'id' => 'https://blog.parse.ly/5-tagging-best-practices-content-strategy/', + 'dashUrl' => PARSELY::DASHBOARD_BASE_URL . '/example.com/find?url=https%3A%2F%2Fblog.parse.ly%2F5-tagging-best-practices-content-strategy%2F', + 'thumbnailUrl' => 'https://images.parsely.com/ap3YSufqxnLpz6zzQshoks3snXI=/85x85/smart/https%3A//blog.parse.ly/wp-content/uploads/2021/05/pexels-brett-jordan-998501-1024x768-2.jpeg%3Fw%3D150%26h%3D150%26crop%3D1', + 'title' => '5 Tagging Best Practices For Getting the Most Out of Your Content Strategy', + 'url' => 'https://blog.parse.ly/5-tagging-best-practices-content-strategy/?itm_source=wp-parsely-content-helper', + 'views' => '40', + 'postId' => 0, + 'rawUrl' => 'https://blog.parse.ly/5-tagging-best-practices-content-strategy/', + ), + ), + $response_data['data'] + ); + + self::assertEquals( + array( + 'limit' => 5, + 'sort' => 'views', + 'page' => 1, + 'itm_source' => 'wp-parsely-content-helper', + ), + $response_data['params'] + ); + } +} diff --git a/tests/Integration/RestAPI/Stats/EndpointRelatedTest.php b/tests/Integration/RestAPI/Stats/EndpointRelatedTest.php new file mode 100644 index 000000000..616818d98 --- /dev/null +++ b/tests/Integration/RestAPI/Stats/EndpointRelatedTest.php @@ -0,0 +1,304 @@ +api_controller = new Stats_Controller( $this->parsely ); + $this->endpoint = new Endpoint_Related( $this->api_controller ); + + parent::set_up(); + } + + /** + * Gets the test endpoint instance. + * + * @since 3.17.0 + * + * @return Endpoint_Related + */ + public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { + return $this->endpoint; + } + + /** + * Verifies that the route is registered. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Related::register_routes + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Related::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Related::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Related::is_available_to_current_user + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_route_is_registered(): void { + $routes = rest_get_server()->get_routes(); + + // Check that the route is registered. + $expected_route = $this->get_endpoint()->get_full_endpoint( '/' ); + self::assertArrayHasKey( $expected_route, $routes ); + + // Check that the route is associated with the GET method. + $route_data = $routes[ $expected_route ]; + self::assertArrayHasKey( 'GET', $route_data[0]['methods'] ); + } + + /** + * Verifies that the endpoint is available to everyone, even if they are not + * logged in. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Related::is_available_to_current_user + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_api_secret + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::get_url_with_itm_source + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Related::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Related::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Related::get_related_posts + * @uses \Parsely\REST_API\Stats\Endpoint_Related::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::set_itm_source_from_request + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_of_url + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_access_of_related_posts_is_available_to_everyone(): void { + TestCase::set_options( + array( + 'apikey' => 'test-api-key', + 'api_secret' => 'test-secret', + ) + ); + wp_set_current_user( 0 ); + + $dispatched = 0; + $this->mock_api_response( $dispatched ); + + $route = $this->get_endpoint()->get_full_endpoint( '/' ); + $request = new WP_REST_Request( 'GET', $route ); + $request->set_param( 'url', 'https://example.com/a-post' ); + $response = rest_get_server()->dispatch( $request ); + + self::assertEquals( 1, $dispatched ); + self::assertSame( 200, $response->get_status() ); + } + + /** + * Mocks the API response of the Parse.ly API. + * + * @since 3.17.0 + * + * @param int &$dispatched The number of times the API was dispatched. + */ + private function mock_api_response( int &$dispatched ): void { + add_filter( + 'pre_http_request', + function () use ( &$dispatched ): array { + $dispatched++; + return array( + 'body' => '{"data":[ + { + "image_url":"https:\/\/example.com\/img.png", + "thumb_url_medium":"https:\/\/example.com\/thumb.png", + "title":"something", + "url":"https:\/\/example.com" + }, + { + "image_url":"https:\/\/example.com\/img2.png", + "thumb_url_medium":"https:\/\/example.com\/thumb2.png", + "title":"something2", + "url":"https:\/\/example.com\/2" + } + ]}', + ); + } + ); + } + + /** + * Verifies that calls to the `stats/related` return the expected data, in the + * expected format, despite the user being unauthenticated. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Endpoint_Related::get_related_posts + * @uses \Parsely\Parsely::api_secret_is_set + * @uses \Parsely\Parsely::get_api_secret + * @uses \Parsely\Parsely::get_managed_credentials + * @uses \Parsely\Parsely::get_options + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::get_url_with_itm_source + * @uses \Parsely\Parsely::set_default_content_helper_settings_values + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Permissions::build_pch_permissions_settings_array + * @uses \Parsely\Permissions::get_user_roles_with_edit_posts_cap + * @uses \Parsely\REST_API\Base_API_Controller::__construct + * @uses \Parsely\REST_API\Base_API_Controller::get_full_namespace + * @uses \Parsely\REST_API\Base_API_Controller::get_parsely + * @uses \Parsely\REST_API\Base_API_Controller::prefix_route + * @uses \Parsely\REST_API\Base_Endpoint::__construct + * @uses \Parsely\REST_API\Base_Endpoint::get_full_endpoint + * @uses \Parsely\REST_API\Base_Endpoint::init + * @uses \Parsely\REST_API\Base_Endpoint::register_rest_route + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + * @uses \Parsely\REST_API\Stats\Endpoint_Related::__construct + * @uses \Parsely\REST_API\Stats\Endpoint_Related::get_endpoint_name + * @uses \Parsely\REST_API\Stats\Endpoint_Related::is_available_to_current_user + * @uses \Parsely\REST_API\Stats\Endpoint_Related::register_routes + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::get_itm_source_param_args + * @uses \Parsely\REST_API\Stats\Post_Data_Trait::set_itm_source_from_request + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_of_url + * @uses \Parsely\REST_API\Stats\Related_Posts_Trait::get_related_posts_param_args + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_route_prefix + * @uses \Parsely\Utils\Utils::convert_endpoint_to_filter_key + */ + public function test_get_related_posts(): void { + $route = $this->get_endpoint()->get_full_endpoint( '/' ); + + TestCase::set_options( + array( + 'apikey' => 'example.com', + 'api_secret' => 'test-secret', + ) + ); + + $dispatched = 0; + + add_filter( + 'pre_http_request', + function () use ( &$dispatched ): array { + $dispatched++; + return array( + 'body' => '{"data":[ + { + "image_url":"https:\/\/example.com\/img.png", + "thumb_url_medium":"https:\/\/example.com\/thumb.png", + "title":"something", + "url":"https:\/\/example.com" + }, + { + "image_url":"https:\/\/example.com\/img2.png", + "thumb_url_medium":"https:\/\/example.com\/thumb2.png", + "title":"something2", + "url":"https:\/\/example.com\/2" + } + ]}', + ); + } + ); + + $request = new WP_REST_Request( 'GET', $route ); + $request->set_param( 'url', 'https://example.com/a-post' ); + $response = rest_get_server()->dispatch( $request ); + + /** + * The response data. + * + * @var array $response_data + */ + $response_data = $response->get_data(); + + self::assertSame( 1, $dispatched ); + self::assertSame( 200, $response->get_status() ); + self::assertEquals( + array( + array( + 'image_url' => 'https://example.com/img.png', + 'thumb_url_medium' => 'https://example.com/thumb.png', + 'title' => 'something', + 'url' => 'https://example.com', + ), + array( + 'image_url' => 'https://example.com/img2.png', + 'thumb_url_medium' => 'https://example.com/thumb2.png', + 'title' => 'something2', + 'url' => 'https://example.com/2', + ), + ), + $response_data['data'] + ); + } + + /** + * Verifies that the endpoint is not available if the API Secret is not set. + * + * This test is disabled since the endpoint does not require an API Secret. + * + * @since 3.17.0 + * + * @coversNothing + */ + public function test_is_available_to_current_user_returns_error_api_secret_not_set(): void { + self::assertTrue( true ); + } +} diff --git a/tests/Integration/RestAPI/Stats/StatsControllerTest.php b/tests/Integration/RestAPI/Stats/StatsControllerTest.php new file mode 100644 index 000000000..2eb6ba287 --- /dev/null +++ b/tests/Integration/RestAPI/Stats/StatsControllerTest.php @@ -0,0 +1,61 @@ +stats_controller = new Stats_Controller( new Parsely() ); + } + + /** + * Verifies that the constructor sets up the correct namespace and version. + * + * @since 3.17.0 + * + * @covers \Parsely\REST_API\Stats\Stats_Controller::__construct + * @uses \Parsely\REST_API\Stats\Stats_Controller::get_full_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_namespace + * @uses \Parsely\REST_API\REST_API_Controller::get_version + */ + public function test_constructor_sets_up_namespace_and_version(): void { + self::assertEquals( + 'wp-parsely/v2', + $this->stats_controller->get_full_namespace() + ); + } +} diff --git a/tests/Integration/ScriptsTest.php b/tests/Integration/ScriptsTest.php index 7f598df63..7eabab3f6 100644 --- a/tests/Integration/ScriptsTest.php +++ b/tests/Integration/ScriptsTest.php @@ -347,7 +347,7 @@ public function test_track_logged_in_users(): void { 'track_authenticated_users' => true, ) ); - $new_user_id = $this->create_test_user( 'bill_brasky' ); + $new_user_id = self::create_test_user( 'bill_brasky' ); wp_set_current_user( $new_user_id ); $this->go_to_new_post(); self::$scripts->register_scripts(); @@ -390,10 +390,10 @@ public function test_do_not_track_logged_in_users_multisite(): void { } // Set up users and blogs. - $first_blog_admin = $this->create_test_user( 'optimus_prime' ); - $second_blog_admin = $this->create_test_user( 'megatron' ); - $first_blog = $this->create_test_blog( 'autobots', $first_blog_admin ); - $second_blog = $this->create_test_blog( 'decepticons', $second_blog_admin ); + $first_blog_admin = self::create_test_user( 'optimus_prime' ); + $second_blog_admin = self::create_test_user( 'megatron' ); + $first_blog = self::create_test_blog( 'autobots', $first_blog_admin ); + $second_blog = self::create_test_blog( 'decepticons', $second_blog_admin ); // These custom options will be used for both blogs. $custom_options = array( diff --git a/tests/Integration/Services/BaseAPIServiceTestCase.php b/tests/Integration/Services/BaseAPIServiceTestCase.php new file mode 100644 index 000000000..30d71d802 --- /dev/null +++ b/tests/Integration/Services/BaseAPIServiceTestCase.php @@ -0,0 +1,57 @@ +> + */ + abstract public function data_registered_endpoints(): iterable; + + /** + * Runs once before all tests. + * + * @since 3.17.0 + */ + public static function set_up_before_class(): void { + static::initialize(); + } +} diff --git a/tests/Integration/Services/BaseServiceEndpointTestCase.php b/tests/Integration/Services/BaseServiceEndpointTestCase.php new file mode 100644 index 000000000..7d55190c6 --- /dev/null +++ b/tests/Integration/Services/BaseServiceEndpointTestCase.php @@ -0,0 +1,136 @@ + + */ + abstract public function data_api_url(): iterable; + + /** + * Returns the endpoint for the API request. + * + * @since 3.17.0 + * + * @return Base_Service_Endpoint + */ + abstract public function get_service_endpoint(): Base_Service_Endpoint; + + /** + * Runs once before all tests. + * + * @since 3.17.0 + */ + public static function set_up_before_class(): void { + static::initialize(); + } + + /** + * Verifies that the truncate_array_content() method truncates long text in + * any member of the array. + * + * @since 3.17.0 + * + * @covers \Parsely\Services\Base_Service_Endpoint::truncate_array_content + */ + public function test_truncate_body_content(): void { + $endpoint = $this->get_service_endpoint(); + + $body = array( + 'output_params' => array( + 'some_param' => true, + 'other_param' => 'Hello', + 'recursive' => array( + 'key' => 'value', + ), + ), + 'text' => $this->generate_content_with_length( 30000 ), + 'something' => 'else', + ); + + $truncate_array_content = self::get_method( 'truncate_array_content', $endpoint ); + $truncated_array = $truncate_array_content->invoke( $endpoint, $body ); + + self::assertIsArray( $truncated_array ); + self::assertArrayHasKey( 'output_params', $truncated_array ); + self::assertArrayHasKey( 'text', $truncated_array ); + self::assertLessThanOrEqual( 25000, strlen( $truncated_array['text'] ) ); + + // Assert that the truncated text is the beginning of the original text. + self::assertStringStartsWith( $truncated_array['text'], $body['text'] ); + + // Assert that the other keys are the same in both arrays. + self::assertEquals( $body['output_params'], $truncated_array['output_params'] ); + self::assertEquals( $body['something'], $truncated_array['something'] ); + } + + /** + * Generates content with a specific length. + * + * @since 3.17.0 + * + * @param int $length Length of the generated content. + * @return string The generated content. + */ + private function generate_content_with_length( int $length ): string { + $words = array( 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit' ); + $string = ''; + $current_length = 0; + + while ( $current_length < $length ) { + $word = $words[ array_rand( $words ) ]; + if ( $current_length > 0 ) { + if ( $current_length + strlen( $word ) + 1 > $length ) { + break; + } + $string .= ' '; + ++$current_length; + } + $string .= $word; + $current_length += strlen( $word ); + } + + return $string; + } +} diff --git a/tests/Integration/Services/ContentAPI/ContentApiServiceTestCase.php b/tests/Integration/Services/ContentAPI/ContentApiServiceTestCase.php new file mode 100644 index 000000000..4b03397ed --- /dev/null +++ b/tests/Integration/Services/ContentAPI/ContentApiServiceTestCase.php @@ -0,0 +1,133 @@ + + */ + private static $endpoints; + + /** + * Initializes all required values for the test. + * + * @since 3.17.0 + */ + public static function initialize(): void { + self::$api_service = new Content_API_Service( new Parsely() ); + + // Get the endpoints from the protected $endpoints property using reflection. + $endpoints_prop = self::get_property( 'endpoints', self::$api_service ); + + /** @var array $endpoints */ + $endpoints = $endpoints_prop->getValue( self::$api_service ); + + // Store it. + self::$endpoints = $endpoints; + } + + /** + * Provides data for test_endpoint_is_registered(). + * + * Should return an array of arrays, each containing the endpoint name and + * class. + * + * @since 3.17.0 + * + * @return array> + */ + public function data_registered_endpoints(): iterable { + return array( + 'analytics/posts' => array( + 'endpoint' => '/analytics/posts', + 'class' => Endpoint_Analytics_Posts::class, + ), + 'analytics/post/details' => array( + 'endpoint' => '/analytics/post/detail', + 'class' => Endpoint_Analytics_Post_Details::class, + ), + 'related' => array( + 'endpoint' => '/related', + 'class' => Endpoint_Related::class, + ), + 'referrers/post/details' => array( + 'endpoint' => '/referrers/post/detail', + 'class' => Endpoint_Referrers_Post_Detail::class, + ), + 'validate/secret' => array( + 'endpoint' => '/validate/secret', + 'class' => Endpoint_Validate::class, + ), + ); + } + + /** + * Verifies that the number of registered endpoints is as expected. + * + * @since 3.17.0 + * + * @covers \Parsely\Services\Suggestions_API\Suggestions_API_Service::register_endpoint + */ + public function test_number_of_registered_endpoints_is_as_expected(): void { + self::assertSameSize( $this->data_registered_endpoints(), self::$endpoints ); + } + + /** + * Tests that the endpoint is registered and is an instance of the expected class. + * + * @since 3.17.0 + * + * @dataProvider data_registered_endpoints + * @covers \Parsely\Services\Base_API_Service::get_endpoint + * @uses \Parsely\Services\Cached_Service_Endpoint::get_uncached_endpoint + * + * @param string $endpoint The endpoint name to check. + * @param class-string $class_name The endpoint class to check. + */ + public function test_endpoint_is_registered( string $endpoint, string $class_name ): void { + // Check that the endpoint exists and is an instance of the expected class. + self::assertArrayHasKey( $endpoint, self::$endpoints, "Endpoint $endpoint is not registered." ); + $endpoint = self::$api_service->get_endpoint( $endpoint ); + self::assertInstanceOf( Base_Service_Endpoint::class, $endpoint ); + + // If the endpoint is cached, check the inner endpoint. + if ( $endpoint instanceof Cached_Service_Endpoint ) { + self::assertInstanceOf( $class_name, $endpoint->get_uncached_endpoint() ); + } else { + self::assertInstanceOf( $class_name, $endpoint ); + } + } +} diff --git a/tests/Integration/Services/ContentAPI/Endpoints/ContentAPIBaseEndpointTestCase.php b/tests/Integration/Services/ContentAPI/Endpoints/ContentAPIBaseEndpointTestCase.php new file mode 100644 index 000000000..6233563de --- /dev/null +++ b/tests/Integration/Services/ContentAPI/Endpoints/ContentAPIBaseEndpointTestCase.php @@ -0,0 +1,129 @@ + $query Test query arguments. + * @param string $url Expected generated URL. + */ + public function test_api_url( array $query, string $url ): void { + // Get the endpoint object. + $endpoint = $this->get_service_endpoint(); + self::assertInstanceOf( Base_Service_Endpoint::class, $endpoint ); + + self::set_options( + array( + 'apikey' => 'my-key', + 'api_secret' => 'my-secret', + ) + ); + + self::assertSame( $url, $endpoint->get_endpoint_url( $query ) ); + } + + /** + * Verifies the basic generation of the API headers. + * + * @since 3.17.0 + * + * @covers \Parsely\Tests\Integration\Services\ContentAPI\Endpoints\Content_API_Base_Endpoint::get_request_options + */ + public function test_api_authentication(): void { + // Assume self::$api_service is always an instance of Suggestions_API_Service. + // If there's any doubt, this should be handled in the test setup or constructor, + // not within individual tests. + self::assertInstanceOf( Content_API_Service::class, self::$api_service ); + + // Get the endpoint object. + $endpoint = $this->get_service_endpoint(); + self::assertInstanceOf( Base_Service_Endpoint::class, $endpoint ); + + // Set options - this assumes set_options() does not produce side effects that affect other tests. + // Consider resetting any global or static state in a tearDown() method if necessary. + self::set_options( + array( + 'apikey' => 'my-key', + 'api_secret' => 'my-secret', + ) + ); + + // Call the protected method get_query_args() using reflection. + $get_query_args = self::get_method( 'get_query_args', $endpoint ); + $query_args = $get_query_args->invoke( $endpoint ); + + // Ensure that $query_args is an array. + self::assertIsArray( $query_args ); + + // Verify the API key and secret are present in the query args and their values + // match the ones set in the options. + self::assertArrayHasKey( 'apikey', $query_args ); + self::assertEquals( 'my-key', $query_args['apikey'] ); + + self::assertArrayHasKey( 'secret', $query_args ); + self::assertEquals( 'my-secret', $query_args['secret'] ); + } +} diff --git a/tests/Integration/Services/ContentAPI/Endpoints/EndpointAnalyticsPostsTest.php b/tests/Integration/Services/ContentAPI/Endpoints/EndpointAnalyticsPostsTest.php new file mode 100644 index 000000000..4d522fe48 --- /dev/null +++ b/tests/Integration/Services/ContentAPI/Endpoints/EndpointAnalyticsPostsTest.php @@ -0,0 +1,48 @@ +get_content_api()->get_endpoint( '/analytics/posts' ); + } + + /** + * Provides data for test_api_url(). + * + * @since 3.17.0 + * + * @return \ArrayIterator + */ + public function data_api_url(): iterable { + yield 'Basic (Expected data)' => array( + array( + 'limit' => 5, + ), + Content_API_Service::get_base_url() . '/analytics/posts?limit=5&apikey=my-key&secret=my-secret', + ); + } +} diff --git a/tests/Integration/Services/ContentAPI/Endpoints/EndpointRelatedTest.php b/tests/Integration/Services/ContentAPI/Endpoints/EndpointRelatedTest.php new file mode 100644 index 000000000..2b39a5717 --- /dev/null +++ b/tests/Integration/Services/ContentAPI/Endpoints/EndpointRelatedTest.php @@ -0,0 +1,54 @@ +get_content_api()->get_endpoint( '/related' ); + } + + /** + * Provides data for test_api_url(). + * + * @return \ArrayIterator + */ + public function data_api_url(): iterable { + yield 'Basic (Expected data)' => array( + array( + 'limit' => 5, + ), + Content_API_Service::get_base_url() . '/related?limit=5&apikey=my-key&secret=my-secret', + ); + yield 'published_within value of 0' => array( + array( + 'apikey' => 'my-key', + 'sort' => 'score', + 'limit' => 5, + ), + Content_API_Service::get_base_url() . '/related?apikey=my-key&sort=score&limit=5&secret=my-secret', + ); + } +} diff --git a/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestBriefTest.php b/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestBriefTest.php new file mode 100644 index 000000000..d6e8fb568 --- /dev/null +++ b/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestBriefTest.php @@ -0,0 +1,132 @@ +get_suggestions_api()->get_endpoint( '/suggest-brief' ); + } + + /** + * Provides data for test_api_url(). + * + * @since 3.17.0 + * + * @covers \Parsely\Services\Base_Service_Endpoint::get_endpoint_url + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Brief::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Suggestions_API_Service::get_base_url + * + * @return \ArrayIterator + */ + public function data_api_url(): iterable { + yield 'Basic (Expected data)' => array( + array( + 'apikey' => 'my-key', + ), + Suggestions_API_Service::get_base_url() . '/suggest-brief?apikey=my-key', + ); + } + + /** + * Mocks a successful HTTP response to the Content Suggestion suggest-brief + * API endpoint. + * + * @since 3.17.0 + * + * @param string $response The response to mock. + * @param array $args The arguments passed to the HTTP request. + * @param string $url The URL of the HTTP request. + * @return array|false The mocked response. + * + * @phpstan-ignore-next-line + */ + public function mock_successful_suggest_brief_response( + string $response, + array $args, + string $url + ) { + if ( ! str_contains( $url, 'suggest-brief' ) ) { + return false; + } + + $response = array( + 'result' => array( + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + ), + ); + + return array( + 'headers' => array(), + 'cookies' => array(), + 'filename' => null, + 'response' => array( + 'code' => 200, + 'message' => 'OK', + ), + 'status_code' => 200, + 'success' => true, + 'body' => $this->wp_json_encode( $response ), + ); + } + + /** + * Tests getting meta description from the API with some generic content. + * + * @since 3.17.0 + * + * @covers \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Brief::get_suggestion + */ + public function test_get_suggestion(): void { + $title = 'Lorem Ipsum is a random title'; + $content = '

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

'; + $persona = 'journalist'; + $style = 'neutral'; + + // Mock API result. + add_filter( 'pre_http_request', array( $this, 'mock_successful_suggest_brief_response' ), 10, 3 ); + + // Get the brief suggestion from the Suggestions API. + $brief = $this->get_suggestions_api()->get_brief_suggestions( + $title, + $content, + array( + 'persona' => $persona, + 'style' => $style, + 'max_items' => 1, + ) + ); + + self::assertIsArray( $brief ); + self::assertCount( 1, $brief ); + self::assertIsString( $brief[0] ); + self::assertEquals( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', $brief[0] ); + + // Remove mock. + remove_filter( 'pre_http_request', array( $this, 'mock_successful_suggest_brief_response' ) ); + } +} diff --git a/tests/Integration/RemoteAPI/ContentSuggestions/SuggestHeadlineAPITest.php b/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestHeadlineTest.php similarity index 57% rename from tests/Integration/RemoteAPI/ContentSuggestions/SuggestHeadlineAPITest.php rename to tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestHeadlineTest.php index d6d879f46..ce2236cde 100644 --- a/tests/Integration/RemoteAPI/ContentSuggestions/SuggestHeadlineAPITest.php +++ b/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestHeadlineTest.php @@ -1,48 +1,41 @@ get_suggestions_api()->get_endpoint( '/suggest-headline' ); } /** * Provides data for test_api_url(). * - * @since 3.12.0 + * @since 3.17.0 * * @return \ArrayIterator */ @@ -51,8 +44,7 @@ public function data_api_url(): iterable { array( 'apikey' => 'my-key', ), - Parsely::PUBLIC_SUGGESTIONS_API_BASE_URL . - '/suggest-headline?apikey=my-key', + Suggestions_API_Service::get_base_url() . '/suggest-headline?apikey=my-key', ); } @@ -60,7 +52,7 @@ public function data_api_url(): iterable { * Mocks a successful HTTP response to the Content Suggestion suggest-headline * API endpoint. * - * @since 3.12.0 + * @since 3.17.0 * * @param string $response The response to mock. * @param array $args The arguments passed to the HTTP request. @@ -103,14 +95,11 @@ public function mock_successful_suggest_headline_response( /** * Tests getting titles from the API with some generic content. * - * @since 3.12.0 + * @since 3.17.0 * - * @covers \Parsely\RemoteAPI\ContentSuggestions\Suggest_Headline_API::get_titles - * @uses \Parsely\RemoteAPI\ContentSuggestions\Suggest_Headline_API::__construct - * @uses \Parsely\RemoteAPI\ContentSuggestions\Suggest_Headline_API::get_titles - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::__construct - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_api_url - * @uses \Parsely\RemoteAPI\Remote_API_Base::__construct + * @covers \Parsely\Services\Suggestions_API\Suggestions_API_Service::get_title_suggestions + * @covers \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Headline::get_headlines + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Headline::call */ public function test_get_titles(): void { $content = '

@@ -123,7 +112,12 @@ public function test_get_titles(): void { add_filter( 'pre_http_request', array( $this, 'mock_successful_suggest_headline_response' ), 10, 3 ); // Test getting three titles. - $titles = self::$suggest_headline_api->get_titles( $content, 3 ); + $titles = $this->get_suggestions_api()->get_title_suggestions( + $content, + array( + 'max_items' => 3, + ) + ); self::assertIsArray( $titles ); self::assertEquals( 3, count( $titles ) ); diff --git a/tests/Integration/RemoteAPI/ContentSuggestions/SuggestLinkedReferenceAPITest.php b/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestLinkedReferenceTest.php similarity index 57% rename from tests/Integration/RemoteAPI/ContentSuggestions/SuggestLinkedReferenceAPITest.php rename to tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestLinkedReferenceTest.php index 21d2d3c8d..de0f663fb 100644 --- a/tests/Integration/RemoteAPI/ContentSuggestions/SuggestLinkedReferenceAPITest.php +++ b/tests/Integration/Services/SuggestionsAPI/Endpoints/EndpointSuggestLinkedReferenceTest.php @@ -1,50 +1,45 @@ get_suggestions_api()->get_endpoint( '/suggest-linked-reference' ); } /** * Provides data for test_api_url(). * - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::validate_required_constraints - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_api_url - - * @since 3.14.0 + * @since 3.17.0 + * * @return \ArrayIterator */ public function data_api_url(): iterable { @@ -52,8 +47,7 @@ public function data_api_url(): iterable { array( 'apikey' => 'my-key', ), - Parsely::PUBLIC_SUGGESTIONS_API_BASE_URL . - '/suggest-linked-reference?apikey=my-key', + Suggestions_API_Service::get_base_url() . '/suggest-linked-reference?apikey=my-key', ); } @@ -61,7 +55,7 @@ public function data_api_url(): iterable { * Mocks a successful HTTP response to the Content Suggestion suggest-links * API endpoint. * - * @since 3.14.0 + * @since 3.17.0 * * @param string $response The response to mock. * @param array $args The arguments passed to the HTTP request. @@ -119,20 +113,35 @@ public function mock_successful_suggest_links_response( /** * Tests getting smart links suggestions from the API. * - * @since 3.14.0 + * @since 3.17.0 * - * @covers \Parsely\RemoteAPI\ContentSuggestions\Suggest_Linked_Reference_API::get_links + * @covers \Parsely\Services\Suggestions_API\Suggestions_API_Service::get_smart_links + * @uses \Parsely\Models\Base_Model::__construct + * @uses Smart_Link::__construct + * @uses Smart_Link::generate_uid + * @uses Smart_Link::get_post_id_by_url + * @uses Smart_Link::set_href * @uses \Parsely\Parsely::api_secret_is_set * @uses \Parsely\Parsely::get_managed_credentials * @uses \Parsely\Parsely::get_options * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts * @uses \Parsely\Parsely::set_default_track_as_values * @uses \Parsely\Parsely::site_id_is_set - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::get_api_url - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_request_options - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::post_request - * @uses \Parsely\RemoteAPI\Base_Endpoint_Remote::validate_required_constraints - * @uses \Parsely\RemoteAPI\ContentSuggestions\Content_Suggestions_Base_API::get_api_url + * @uses \Parsely\Services\Base_API_Service::get_api_url + * @uses \Parsely\Services\Base_API_Service::get_endpoint + * @uses \Parsely\Services\Base_API_Service::get_parsely + * @uses Base_Service_Endpoint::get_endpoint_url + * @uses Base_Service_Endpoint::get_parsely + * @uses Base_Service_Endpoint::get_query_args + * @uses Base_Service_Endpoint::request + * @uses Base_Service_Endpoint::truncate_array_content + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Linked_Reference::get_endpoint + * @uses \Parsely\Services\Suggestions_API\Endpoints\Endpoint_Suggest_Linked_Reference::get_links + * @uses \Parsely\Services\Suggestions_API\Endpoints\Suggestions_API_Base_Endpoint::get_query_args + * @uses \Parsely\Services\Suggestions_API\Endpoints\Suggestions_API_Base_Endpoint::get_request_options + * @uses \Parsely\Services\Suggestions_API\Endpoints\Suggestions_API_Base_Endpoint::process_response + * @uses Suggestions_API_Service::get_base_url */ public function test_get_links(): void { $content = '

@@ -145,7 +154,7 @@ public function test_get_links(): void { add_filter( 'pre_http_request', array( $this, 'mock_successful_suggest_links_response' ), 10, 3 ); // Test getting three titles. - $suggested_links = self::$suggest_linked_reference_api->get_links( $content ); + $suggested_links = $this->get_suggestions_api()->get_smart_links( $content ); self::assertIsArray( $suggested_links ); self::assertEquals( 3, count( $suggested_links ) ); diff --git a/tests/Integration/Services/SuggestionsAPI/Endpoints/SuggestionsAPIBaseEndpointTestCase.php b/tests/Integration/Services/SuggestionsAPI/Endpoints/SuggestionsAPIBaseEndpointTestCase.php new file mode 100644 index 000000000..54086555d --- /dev/null +++ b/tests/Integration/Services/SuggestionsAPI/Endpoints/SuggestionsAPIBaseEndpointTestCase.php @@ -0,0 +1,131 @@ + $query Test query arguments. + * @param string $url Expected generated URL. + */ + public function test_api_url( array $query, string $url ): void { + // Get the endpoint object. + $endpoint = $this->get_service_endpoint(); + self::assertInstanceOf( Base_Service_Endpoint::class, $endpoint ); + + self::set_options( array( 'apikey' => 'my-key' ) ); + self::assertSame( $url, $endpoint->get_endpoint_url( $query ) ); + } + + /** + * Verifies the basic generation of the API headers. + * + * @since 3.17.0 + * + * @covers \Parsely\Services\Suggestions_API\Suggestions_API_Service::get_request_options + * @uses \Parsely\Parsely::api_secret_is_set() + * @uses \Parsely\Parsely::get_api_secret() + * @uses \Parsely\Parsely::get_managed_credentials() + * @uses \Parsely\Parsely::get_options() + */ + public function test_api_headers(): void { + // Assume self::$api_service is always an instance of Suggestions_API_Service. + // If there's any doubt, this should be handled in the test setup or constructor, + // not within individual tests. + self::assertInstanceOf( Suggestions_API_Service::class, self::$api_service ); + + // Get the endpoint object. + $endpoint = $this->get_service_endpoint(); + self::assertInstanceOf( Base_Service_Endpoint::class, $endpoint ); + + // Set options - this assumes set_options() does not produce side effects that affect other tests. + // Consider resetting any global or static state in a tearDown() method if necessary. + self::set_options( + array( + 'apikey' => 'my-key', + 'api_secret' => 'my-secret', + ) + ); + + // Call the protected method get_request_options() using reflection. + $get_request_options = self::get_method( 'get_request_options', $endpoint ); + $request_options = $get_request_options->invoke( $endpoint, 'GET' ); + + // Ensure that $request_options is an array and 'headers' key exists. + self::assertIsArray( $request_options ); + self::assertArrayHasKey( 'headers', $request_options ); + + $headers = $request_options['headers']; + self::assertIsArray( $headers ); // Ensures $headers is indeed an array. + + // Verify the Content-Type header is present and its value is application/json. + self::assertArrayHasKey( 'Content-Type', $headers ); + self::assertEquals( 'application/json; charset=utf-8', $headers['Content-Type'] ); + + // Verify the API key is present in the headers and its value matches the one set in the options. + self::assertArrayHasKey( 'X-APIKEY-SECRET', $headers ); + self::assertEquals( 'my-secret', $headers['X-APIKEY-SECRET'] ); + } +} diff --git a/tests/Integration/Services/SuggestionsAPI/SuggestionsApiServiceTestCase.php b/tests/Integration/Services/SuggestionsAPI/SuggestionsApiServiceTestCase.php new file mode 100644 index 000000000..392791e85 --- /dev/null +++ b/tests/Integration/Services/SuggestionsAPI/SuggestionsApiServiceTestCase.php @@ -0,0 +1,115 @@ + + */ + private static $endpoints; + + /** + * Initializes all required values for the test. + * + * @since 3.17.0 + */ + public static function initialize(): void { + self::$api_service = new Suggestions_API_Service( new Parsely() ); + + // Get the endpoints from the protected $endpoints property using reflection. + $endpoints_prop = self::get_property( 'endpoints', self::$api_service ); + + /** @var array $endpoints */ + $endpoints = $endpoints_prop->getValue( self::$api_service ); + + // Store it. + self::$endpoints = $endpoints; + } + + /** + * Provides data for test_endpoint_is_registered(). + * + * Should return an array of arrays, each containing the endpoint name and + * class. + * + * @since 3.17.0 + * + * @return array> + */ + public function data_registered_endpoints(): iterable { + return array( + 'suggest-linked-reference' => array( + 'endpoint' => '/suggest-linked-reference', + 'class' => Endpoint_Suggest_Linked_Reference::class, + ), + 'suggest-brief' => array( + 'endpoint' => '/suggest-brief', + 'class' => Endpoint_Suggest_Brief::class, + ), + 'suggest-headline' => array( + 'endpoint' => '/suggest-headline', + 'class' => Endpoint_Suggest_Headline::class, + ), + ); + } + + /** + * Verifies that the number of registered endpoints is as expected. + * + * @since 3.17.0 + * + * @covers \Parsely\Services\Suggestions_API\Suggestions_API_Service::register_endpoint + */ + public function test_number_of_registered_endpoints_is_as_expected(): void { + self::assertSameSize( $this->data_registered_endpoints(), self::$endpoints ); + } + + /** + * Tests that the endpoint is registered and is an instance of the expected + * class. + * + * @since 3.17.0 + * + * @dataProvider data_registered_endpoints + * @covers \Parsely\Services\Base_API_Service::get_endpoint + * + * @param string $endpoint The endpoint name to check. + * @param class-string $class_name The endpoint class to check. + */ + public function test_endpoint_is_registered( string $endpoint, string $class_name ): void { + // Check that the endpoint exists and is an instance of the expected class. + self::assertArrayHasKey( $endpoint, self::$endpoints, "Endpoint $endpoint is not registered." ); + $endpoint = self::$api_service->get_endpoint( $endpoint ); + self::assertInstanceOf( $class_name, $endpoint ); + } +} diff --git a/tests/Integration/TestCase.php b/tests/Integration/TestCase.php index c2bc79058..1f0ede347 100644 --- a/tests/Integration/TestCase.php +++ b/tests/Integration/TestCase.php @@ -100,7 +100,7 @@ public function create_test_category( string $name ): int { * @param string $user_role The user's role. Default is subscriber. * @return int The newly created user's ID. */ - public function create_test_user( string $user_login, string $user_role = 'subscriber' ): int { + public static function create_test_user( string $user_login, string $user_role = 'subscriber' ): int { /** @var int */ return self::factory()->user->create( array( @@ -427,15 +427,15 @@ public function go_to_new_post( string $post_status = 'publish' ): int { * @param string $user_login The user's login. * @param string $user_role The user's role. */ - public function set_current_user_to( string $user_login, string $user_role ): void { + public static function set_current_user_to( string $user_login, string $user_role ): void { $user = get_user_by( 'login', $user_login ); if ( false === $user ) { - $user_id = $this->create_test_user( $user_login, $user_role ); + $user_id = self::create_test_user( $user_login, $user_role ); $user = get_user_by( 'id', $user_id ); } if ( false === $user ) { - $this::fail( 'Invalid user.' ); + self::fail( 'Invalid user.' ); } wp_set_current_user( $user->ID ); @@ -445,14 +445,14 @@ public function set_current_user_to( string $user_login, string $user_role ): vo * Changes the current user to the built-in admin account. */ public function set_current_user_to_admin(): void { - $this->set_current_user_to( 'admin', 'administrator' ); + self::set_current_user_to( 'admin', 'administrator' ); } /** * Changes the current user to a contributor account. */ public function set_current_user_to_contributor(): void { - $this->set_current_user_to( 'test_contributor', 'contributor' ); + self::set_current_user_to( 'test_contributor', 'contributor' ); } /** diff --git a/tests/Traits/TestsReflection.php b/tests/Traits/TestsReflection.php index 5223b4b0e..4c1484bbe 100644 --- a/tests/Traits/TestsReflection.php +++ b/tests/Traits/TestsReflection.php @@ -12,14 +12,15 @@ use Parsely\Parsely; use ReflectionException; use ReflectionMethod; +use ReflectionProperty; trait TestsReflection { /** * Gets a method from a class. This should be used when trying to access a * private method for testing. * - * @param string $method_name Name of the method to get. - * @param class-string $class_name Name of the class the method is in. + * @param string $method_name Name of the method to get. + * @param class-string|object $class_name Name of the class the method is in. * @throws ReflectionException The method does not exist in the class. * @return ReflectionMethod */ @@ -30,6 +31,24 @@ public static function get_method( string $method_name, $class_name = Parsely::c return $method; } + /** + * Gets a property from a class. This should be used when trying to access a + * private property for testing. + * + * @since 3.17.0 + * + * @param string $property_name Name of the property to get. + * @param class-string|object $class_name Name of the class the property is in. + * @throws ReflectionException The property does not exist in the class. + * @return ReflectionProperty + */ + public static function get_property( string $property_name, $class_name = Parsely::class ) { + $property = ( new \ReflectionClass( $class_name ) )->getProperty( $property_name ); + $property->setAccessible( true ); + + return $property; + } + /** * Overrides the value of a private property on a given object. This is * useful when mocking the internals of a class. @@ -37,19 +56,39 @@ public static function get_method( string $method_name, $class_name = Parsely::c * Note that the property will no longer be private after setAccessible is * called. * - * @param class-string $class_name The fully qualified class name, including namespace. - * @param object $object_instance The object instance on which to set the value. - * @param string $property_name The name of the private property to override. - * @param mixed $value The value to set. + * @since 3.17.0 Changed the method signature. + * + * @param object $obj The object instance on which to set the value. + * @param string $property_name The name of the private property to override. + * @param mixed $value The value to set. + * + * @throws ReflectionException The property does not exist in the class. */ - public static function set_private_property( - string $class_name, - $object_instance, - string $property_name, - $value - ): void { - $property = ( new \ReflectionClass( $class_name ) )->getProperty( $property_name ); + public static function set_private_property( $obj, string $property_name, $value ): void { + $property = ( new \ReflectionClass( $obj ) )->getProperty( $property_name ); + $property->setAccessible( true ); + $property->setValue( $obj, $value ); + } + + /** + * Overrides the value of a protected property on a given object. This is + * useful when mocking the internals of a class. + * + * Note that the property will no longer be protected after setAccessible is + * called. + * + * @since 3.17.0 + * + * @param object $obj The object instance on which to set the value. + * @param string $property_name The name of the protected property to override. + * @param mixed $value The value to set. + * + * @throws ReflectionException The property does not exist in the class. + */ + public static function set_protected_property( $obj, string $property_name, $value ): void { + $reflection = new \ReflectionClass( $obj ); + $property = $reflection->getProperty( $property_name ); $property->setAccessible( true ); - $property->setValue( $object_instance, $value ); + $property->setValue( $obj, $value ); } } diff --git a/wp-parsely.php b/wp-parsely.php index 8815a2927..f1db9e67c 100644 --- a/wp-parsely.php +++ b/wp-parsely.php @@ -30,30 +30,12 @@ use Parsely\Content_Helper\Editor_Sidebar; use Parsely\Content_Helper\Excerpt_Generator; use Parsely\Content_Helper\Post_List_Stats; -use Parsely\Endpoints\Analytics_Post_Detail_API_Proxy; -use Parsely\Endpoints\Analytics_Posts_API_Proxy; -use Parsely\Endpoints\Content_Helper\Smart_Linking_Endpoint; -use Parsely\Endpoints\ContentSuggestions\Suggest_Brief_API_Proxy; -use Parsely\Endpoints\ContentSuggestions\Suggest_Headline_API_Proxy; -use Parsely\Endpoints\ContentSuggestions\Suggest_Linked_Reference_API_Proxy; use Parsely\Endpoints\GraphQL_Metadata; -use Parsely\Endpoints\Referrers_Post_Detail_API_Proxy; -use Parsely\Endpoints\Related_API_Proxy; use Parsely\Endpoints\Rest_Metadata; -use Parsely\Endpoints\User_Meta\Dashboard_Widget_Settings_Endpoint; -use Parsely\Endpoints\User_Meta\Editor_Sidebar_Settings_Endpoint; use Parsely\Integrations\Amp; use Parsely\Integrations\Google_Web_Stories; use Parsely\Integrations\Integrations; -use Parsely\RemoteAPI\Analytics_Post_Detail_API; -use Parsely\RemoteAPI\Analytics_Posts_API; -use Parsely\RemoteAPI\ContentSuggestions\Suggest_Brief_API; -use Parsely\RemoteAPI\ContentSuggestions\Suggest_Headline_API; -use Parsely\RemoteAPI\ContentSuggestions\Suggest_Linked_Reference_API; -use Parsely\RemoteAPI\Referrers_Post_Detail_API; -use Parsely\RemoteAPI\Related_API; -use Parsely\RemoteAPI\Remote_API_Cache; -use Parsely\RemoteAPI\WordPress_Cache; +use Parsely\REST_API\REST_API_Controller; use Parsely\UI\Admin_Bar; use Parsely\UI\Admin_Warning; use Parsely\UI\Metadata_Renderer; @@ -75,6 +57,10 @@ require_once __DIR__ . '/vendor/autoload.php'; } +// Load Telemetry classes. +require_once __DIR__ . '/src/Telemetry/telemetry-init.php'; + + add_action( 'plugins_loaded', __NAMESPACE__ . '\\parsely_initialize_plugin' ); /** * Registers the basic classes to initialize the plugin. @@ -124,6 +110,10 @@ function parsely_wp_admin_early_register(): void { $network_admin_sites_list = new Network_Admin_Sites_List( $GLOBALS['parsely'] ); $network_admin_sites_list->run(); + + // Initialize the REST API Controller. + $rest_api_controller = $GLOBALS['parsely']->get_rest_api_controller(); + $rest_api_controller->init(); } add_action( 'rest_api_init', __NAMESPACE__ . '\\parsely_rest_api_init' ); @@ -134,58 +124,8 @@ function parsely_wp_admin_early_register(): void { * @since 3.2.0 */ function parsely_rest_api_init(): void { - $wp_cache = new WordPress_Cache(); - $rest = new Rest_Metadata( $GLOBALS['parsely'] ); + $rest = new Rest_Metadata( $GLOBALS['parsely'] ); $rest->run(); - - // Content Helper settings endpoints. - ( new Dashboard_Widget_Settings_Endpoint( $GLOBALS['parsely'] ) )->run(); - ( new Editor_Sidebar_Settings_Endpoint( $GLOBALS['parsely'] ) )->run(); - - // Internal Content Helper endpoints. - ( new Smart_Linking_Endpoint( $GLOBALS['parsely'] ) )->run(); - - parsely_run_rest_api_endpoint( - Related_API::class, - Related_API_Proxy::class, - $wp_cache - ); - - parsely_run_rest_api_endpoint( - Analytics_Posts_API::class, - Analytics_Posts_API_Proxy::class, - $wp_cache - ); - - parsely_run_rest_api_endpoint( - Analytics_Post_Detail_API::class, - Analytics_Post_Detail_API_Proxy::class, - $wp_cache - ); - - parsely_run_rest_api_endpoint( - Referrers_Post_Detail_API::class, - Referrers_Post_Detail_API_Proxy::class, - $wp_cache - ); - - parsely_run_rest_api_endpoint( - Suggest_Headline_API::class, - Suggest_Headline_API_Proxy::class, - $wp_cache - ); - - parsely_run_rest_api_endpoint( - Suggest_Brief_API::class, - Suggest_Brief_API_Proxy::class, - $wp_cache - ); - - parsely_run_rest_api_endpoint( - Suggest_Linked_Reference_API::class, - Suggest_Linked_Reference_API_Proxy::class, - $wp_cache - ); } add_action( 'init', __NAMESPACE__ . '\\init_recommendations_block' ); @@ -273,34 +213,3 @@ function parsely_integrations( $parsely = null ): Integrations { return $parsely_integrations; } - -/** - * Instantiates and runs the specified API endpoint. - * - * @since 3.6.0 - * - * @param string $api_class_name The proxy class to instantiate. - * @param string $proxy_api_class_name The API proxy class to instantiate and run. - * @param WordPress_Cache $wp_cache The WordPress cache instance to be used. - */ -function parsely_run_rest_api_endpoint( - string $api_class_name, - string $proxy_api_class_name, - WordPress_Cache &$wp_cache -): void { - /** - * Internal Variable. - * - * @var RemoteAPI\Base_Endpoint_Remote $remote_api - */ - $remote_api = new $api_class_name( $GLOBALS['parsely'] ); - $remote_api_cache = new Remote_API_Cache( $remote_api, $wp_cache ); - - /** - * Internal Variable. - * - * @var Endpoints\Base_API_Proxy $remote_api_proxy - */ - $remote_api_proxy = new $proxy_api_class_name( $GLOBALS['parsely'], $remote_api_cache ); - $remote_api_proxy->run(); -} From be4217168d1e421f9ca331e1aa1040557417f71f Mon Sep 17 00:00:00 2001 From: Alex Cicovic <23142906+acicovic@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:11:33 +0300 Subject: [PATCH 02/15] PCH Excerpt Suggestions: Add persona and tone settings --- build/content-helper/editor-sidebar-rtl.css | 4 +- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.css | 4 +- .../content-helper/excerpt-generator-rtl.css | 2 +- .../excerpt-generator.asset.php | 2 +- build/content-helper/excerpt-generator.css | 2 +- build/content-helper/excerpt-generator.js | 4 +- src/content-helper/common/css/common.scss | 10 ++ .../types/excerpt-suggestions-settings.d.ts | 10 ++ .../common/settings/types/index.ts | 6 +- .../title-suggestions/title-suggestions.scss | 30 ----- .../components/excerpt-panel-settings.tsx | 82 ++++++++++++ .../components/excerpt-panel.tsx | 117 ++++++++++++------ .../excerpt-generator/excerpt-generator.scss | 41 +++++- .../excerpt-generator/excerpt-generator.tsx | 57 ++++++++- .../excerpt-generator/provider.ts | 8 +- ...-endpoint-excerpt-suggestions-settings.php | 67 ++++++++++ .../settings/class-settings-controller.php | 1 + 18 files changed, 367 insertions(+), 82 deletions(-) create mode 100644 src/content-helper/common/settings/types/excerpt-suggestions-settings.d.ts create mode 100644 src/content-helper/excerpt-generator/components/excerpt-panel-settings.tsx create mode 100644 src/rest-api/settings/class-endpoint-excerpt-suggestions-settings.php diff --git a/build/content-helper/editor-sidebar-rtl.css b/build/content-helper/editor-sidebar-rtl.css index 85427ab8d..3acf25df7 100644 --- a/build/content-helper/editor-sidebar-rtl.css +++ b/build/content-helper/editor-sidebar-rtl.css @@ -1,5 +1,5 @@ #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-block-overlay{align-items:center;background-color:hsla(0,0%,100%,.85);box-sizing:border-box;display:flex;font-size:1.125rem;height:100%;justify-content:center;right:0;position:absolute;top:0;width:100%}.wp-parsely-block-overlay .wp-parsely-block-overlay-label{align-items:center;display:flex;flex-direction:column;flex-grow:1;gap:var(--grid-unit-10);justify-content:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--grid-unit-10)}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel{font-size:1.125rem;padding:0;pointer-events:all;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:10}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel:focus{box-shadow:none;outline:none}.wp-parsely-block-overlay svg{height:1.5625rem;width:1.5625rem}.wp-parsely-block-overlay.full-content-overlay{font-size:1.25rem;z-index:999}.wp-parsely-block-overlay.full-content-overlay span{margin-top:.9375rem}.wp-parsely-block-overlay.full-content-overlay svg{height:3.125rem;width:3.125rem}.wp-parsely-panel .components-panel__icon{height:1.5rem;margin:0 0 0 var(--grid-unit-15);order:-1;width:1.5rem}.wp-parsely-smart-linking .components-panel__row{flex-direction:column;margin-bottom:0}.wp-parsely-smart-linking .components-base-control,.wp-parsely-smart-linking .components-base-control .components-panel__row,.wp-parsely-smart-linking .components-base-control:last-child{margin-bottom:0}.wp-parsely-smart-linking .smart-linking-text{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings{width:100%}.wp-parsely-smart-linking .parsely-panel-settings-body{display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select{align-self:stretch;display:flex;flex-direction:column;gap:1.5rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control-option-base{padding:.625rem 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control{height:40px;overflow:hidden}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s,color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button:not([data-active-item]){transition:color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-settings{align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-smart-linking .smart-linking-generate,.wp-parsely-smart-linking .smart-linking-manage{align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .smart-linking-generate button,.wp-parsely-smart-linking .smart-linking-manage button{align-items:center;align-self:stretch;display:flex;justify-content:center;width:100%}.wp-parsely-smart-linking .wp-parsely-smart-linking-suggested-links{margin:0}.wp-parsely-smart-linking .wp-parsely-smart-linking-hint{margin-top:calc(var(--grid-unit-10)*-1)}.wp-parsely-smart-linking-review-modal{align-items:flex-start;display:flex;flex-direction:column;width:47.875rem}.wp-parsely-smart-linking-review-modal .smart-linking-modal-body{align-self:stretch;display:flex;flex-direction:row;gap:var(--grid-unit-30)}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details{height:auto;margin-bottom:var(--grid-unit-20);text-align:right}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details .components-menu-item__item{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .linking-post-details{align-items:center;display:flex;justify-content:space-between;width:100%}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image{margin-left:.625rem;max-width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image .icon-container{align-items:center;display:flex;height:3.125rem;justify-content:center;width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title a{text-decoration:none}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info{display:flex;flex-direction:column;flex-grow:1}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info .linking-post-meta{color:var(--Gutenberg-Gray-700,#757575);font-size:.9em}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-type{color:var(--Gutenberg-Gray-700,#757575);margin-right:.625rem;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);min-width:13.75rem;padding:.1875rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs{margin-bottom:var(--grid-unit-20)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:var(--grid-unit-40)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item{color:var(--sidebar-black);font-size:.6875rem;font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item:focus-visible:before{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tab-content{max-height:23.125rem;overflow-y:auto}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip{align-items:center;display:flex;font-size:var(--font-size--small);margin-bottom:.3125rem;margin-top:-.5625rem;padding:.3125rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip .review-sidebar-tip svg{flex-shrink:0;height:1.5rem;margin-right:auto;width:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header{align-items:center;align-self:stretch;color:var(--sidebar-black);display:flex;font-size:.6875rem;font-style:normal;font-weight:600;gap:.375rem;line-height:var(--grid-unit-20);margin-bottom:var(--grid-unit-15);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header>span{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button{align-items:center;display:flex;justify-content:space-between;width:13.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button:focus{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-label{align-items:center;color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));display:flex;padding-right:var(--grid-unit-10);white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected{background-color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected .smart-linking-menu-label{color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .components-menu-item__item{padding-left:0;width:100%}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-item{display:inline;flex-grow:1;overflow:hidden;text-align:right;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion{align-items:flex-start;align-self:stretch;display:flex;flex:1;flex-direction:column;gap:1rem;max-width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs{font-size:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-separator{margin:0 var(--grid-unit-5)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-block{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block .breadcrumbs-current-block-name{margin-right:var(--grid-unit-10)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestion-post-title{font-size:var(--font-size--large);font-weight:500;line-height:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .components-divider{border-color:#ccc;height:1px;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots{color:#ccc;font-size:1rem;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-top{margin-bottom:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-bottom{margin-top:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls{align-items:center;align-self:stretch;display:flex;flex-shrink:0;justify-content:space-between;margin:0 var(--grid-unit-20);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .reviews-controls-middle{align-items:center;display:flex;flex:1 0 0;gap:var(--grid-unit-20);justify-content:center}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-next,.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-previous{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-reject{background:var(--Gutenberg-White,#fff);border-radius:2px;box-shadow:inset 0 0 0 1px var(--Gutenberg-Alert-Red,#cc1818);color:var(--Gutenberg-Alert-Red,#cc1818)}.wp-parsely-smart-linking-close-dialog{align-items:flex-start;display:flex;flex-direction:column;width:24rem}.wp-parsely-smart-linking-close-dialog .smart-linking-close-dialog-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;padding-top:var(--grid-unit-30)}.wp-parsely-preview-editor .editor-styles-wrapper{background:var(--Gutenberg-White,#fff);font-size:var(--font-size--medium);padding-bottom:0}.wp-parsely-preview-editor p[role=document]{margin:0}.wp-parsely-preview-editor .smart-linking-highlight{background:hsla(var(--parsely-green-components),.5);border-radius:2px;color:var(--sidebar-black)!important;mix-blend-mode:multiply;text-decoration-line:underline} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-performance-panel{border-top:1px solid #ddd;margin-top:-1px;padding:16px}.wp-parsely-content-helper .wp-parsely-performance-panel .content-helper-error-message{margin:0!important}.wp-parsely-content-helper .wp-parsely-performance-panel .components-button.wp-parsely-view-post{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .panel-body{width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.5rem;padding:.375rem 0 1rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header{align-items:center;display:flex;gap:.375rem;height:1rem;margin-bottom:0;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2{margin-bottom:.9375rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2 h2{margin-bottom:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-3 h3{font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:1rem;margin-bottom:0;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-subtitle{align-items:center;align-self:stretch;color:var(--Gutenberg-Gray-700,#757575);display:flex;flex:1 0 0;font-size:var(--font-size--smaller);font-style:normal;font-weight:600;gap:.375rem;height:1rem;line-height:1rem;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .components-heading{display:block;font-weight:500;line-height:normal;margin:0}.wp-parsely-content-helper .wp-parsely-performance-panel .components-dropdown-menu{line-height:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points{align-content:flex-start;align-items:flex-start;align-self:stretch;display:flex;flex-wrap:wrap;gap:1rem var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point{align-items:center;background:var(--sidebar-white);border-radius:.25rem;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-5);justify-content:center;min-width:100px;padding:var(--grid-unit-20) var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point svg{align-items:flex-start;border-radius:.125rem;display:flex}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-title{align-self:stretch;color:var(--sidebar-black);font-size:.75rem;font-style:normal;font-weight:400;line-height:1rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value{align-self:stretch;color:var(--sidebar-black);font-size:1.25rem;font-style:normal;font-weight:590;line-height:1.75rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value.is-small{font-size:var(--font-size--medium)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar{align-items:flex-start;align-self:stretch;display:flex;height:1rem;margin:1rem 0;position:relative}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill{--radius:2px;align-self:stretch;position:relative;transition:filter .1s ease,transform .1s ease}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:hover{filter:opacity(1)!important;transform:scaleX(1) scaleY(1)!important}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:first-child{border-radius:0 var(--radius) var(--radius) 0}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:last-child{border-radius:var(--radius) 0 0 var(--radius)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar:hover .bar-fill{filter:opacity(.5);transform:scaleX(1) scaleY(.7)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label{align-items:center;align-self:stretch;display:flex;gap:.5rem;justify-content:center}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color{align-items:center;border-radius:.09375rem;display:flex;flex-direction:column;gap:.625rem;height:.625rem;justify-content:center;width:.1875rem}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-text{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1 0 0;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-value{color:var(--sidebar-black);font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;text-align:left}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:1rem 0}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10);justify-content:space-between}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar{display:flex;flex:1;flex-direction:column;gap:.625rem;justify-content:center;max-width:6.25rem}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar{--radius:1.5px;background:var(--gray-400);border-radius:var(--radius);display:flex;height:.1875rem;margin:0;overflow:hidden}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar:after{background:var(--blueberry,#3858e9);border-radius:var(--radius);content:"";height:100%;width:var(--bar-fill)}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-value{color:var(--sidebar-black);flex-shrink:0;font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;min-width:3.125rem;text-align:left} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-related-posts{align-items:flex-start;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-description{font-size:.8125rem;font-style:normal;font-weight:400;gap:.625rem;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body,.wp-parsely-related-posts .related-posts-description{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body{gap:1rem}.wp-parsely-related-posts .related-posts-body>div{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings{align-self:stretch;display:flex;flex-direction:column;gap:1rem;width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings{display:flex;flex-direction:column;gap:var(--grid-unit-20);width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control{height:2.5rem;overflow:hidden}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex{height:2.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex input{margin:0 var(--grid-unit-15)}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-descr{font-size:.8125rem;font-style:normal;font-weight:400;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-empty,.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-loading-message{color:var(--gray-900);font-size:.75rem;font-style:normal;font-weight:700;line-height:var(--grid-unit-20);overflow:hidden;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-title{align-items:center;align-self:stretch;display:flex;flex-direction:column;font-size:.875rem;font-style:normal;font-weight:600;gap:.5rem;justify-content:center;line-height:1.25rem;overflow:hidden;padding:var(--grid-unit-20);text-decoration-line:underline;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions{align-items:center;align-self:stretch;border-top:1px solid var(--gray-400);display:flex;flex-wrap:wrap;padding:0 var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:first-child,.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:last-child{display:flex;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric{align-items:center;display:flex}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric .parsely-post-metric-data{align-items:center;display:flex;gap:var(--grid-unit-5)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-linked{align-items:center;display:flex;margin-right:auto;fill:#008a20}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon path{fill:#1e1e1e}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon:hover path{fill:#0073aa} -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper{display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding-bottom:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header .parsely-write-titles-text strong{text-transform:lowercase}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding-top:.375rem}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-dropdown-label{align-self:stretch;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .parsely-write-titles-accepted-title-container .parsely-write-titles-accepted-title{font-size:1rem;font-weight:600;line-height:1.25rem;margin:0 0 .9375rem;text-align:center}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .parsely-write-titles-accepted-title-container .parsely-write-titles-accepted-title-actions{display:flex;gap:.625rem;justify-content:center;margin:.625rem 0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion.pinned-title{background:var(--Gutenberg-Gray-100,#f0f0f0)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title{align-items:center;align-self:stretch;color:#1e1e1e;display:flex;flex-direction:column;font-size:.75rem;font-style:normal;font-weight:600;gap:var(--grid-unit-10);justify-content:center;line-height:1.25rem;padding:var(--grid-unit-15) var(--grid-unit-15) 0 var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title .suggested-title-original{align-self:flex-start;margin:0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions{align-items:center;align-self:stretch;border-top:1px solid var(--Gutenberg-Gray-400,#ccc);display:flex;flex-wrap:wrap;height:2.5rem;padding:0 var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-left,.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-right{display:flex;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin-bottom:var(--grid-unit-20);position:relative}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay{align-items:center;background-color:hsla(0,0%,100%,.9);bottom:0;display:flex;flex-direction:column;gap:var(--grid-unit-10);justify-content:center;right:0;position:absolute;left:0;top:0;z-index:1}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay .components-spinner{transform:scale(1.125)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-pinned-suggestions{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-content-helper-error.components-notice{margin-bottom:var(--grid-unit-10)}.wp-parsely-popover .components-popover__content{width:15.5rem}.wp-parsely-suggested-title-modal{align-items:flex-start;display:flex;flex-direction:column;width:20rem}.wp-parsely-suggested-title-modal h2{color:var(--sidebar-black);font-size:1rem;font-style:normal;font-weight:600;line-height:1.5rem}.wp-parsely-suggested-title-modal .suggested-title-modal-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;margin-top:1.5rem} -.parsely-tone-selector-dropdown{align-items:center;align-self:stretch;background:var(--Gutenberg-White,#fff);border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-tone-selector-dropdown button{height:2.0625rem}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-tone-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle svg:first-of-type path{transform:scale(1.4);transform-origin:center}.parsely-tone-selector-dropdown .parsely-tone-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:right}.parsely-tone-selector-dropdown .parsely-tone-selector-label:first-letter{text-transform:uppercase}.parsely-persona-selector-custom{width:100%}.parsely-persona-selector-custom .components-base-control__field input{display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-persona-selector-custom .components-base-control__field input,.parsely-persona-selector-dropdown{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px}.parsely-persona-selector-dropdown{background:var(--Gutenberg-White,#fff);height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-persona-selector-dropdown button{height:2.0625rem}.parsely-persona-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-persona-selector-dropdown .parsely-persona-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:right}.parsely-persona-selector-dropdown .parsely-persona-selector-label:first-letter{text-transform:uppercase}.parsely-tone-selector-custom{width:100%}.parsely-tone-selector-custom .components-base-control__field input{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.parsely-inputrange-control{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-inputrange-control .parsely-inputrange-control__label{margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-20);height:2.5rem}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control{display:flex;flex:1 0 0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-inner-spin-button,.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]{-moz-appearance:textfield}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-base-control__field{flex-grow:1}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-input-control__suffix{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control{flex:1 0 0;height:36px}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control .components-range-control__root{height:2.5rem}.parsely-panel-settings{width:100%}.parsely-panel-settings .parsely-panel-settings-header{display:flex;margin:.625rem 0;width:100%}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label{flex-grow:2;margin:0 .3125rem 0 0;text-align:right}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field{align-items:center;display:flex;justify-content:space-between}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field .components-base-control__label{margin-bottom:0}.parsely-panel-settings .parsely-panel-settings-body{align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-content-helper-error{align-self:flex-start;margin:0}.wp-parsely-content-helper-error p{margin:0}.wp-parsely-content-helper-error .content-helper-error-message{margin:0!important}.wp-parsely-collapsible-panel{align-items:flex-start;align-self:stretch;border-bottom:none;border-radius:2px;border-top:none;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:0 0 .5rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title{align-items:center;align-self:stretch;display:flex;margin:0 -1rem .375rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title .components-panel__icon,.wp-parsely-collapsible-panel .components-panel__body-title svg{margin-right:0;margin-left:var(--grid-unit-10);order:-1}.wp-parsely-collapsible-panel .components-panel__body-title:hover{background-color:transparent}.wp-parsely-collapsible-panel.is-opened{padding:0}.wp-parsely-collapsible-panel.is-opened>div:first-of-type{margin-top:calc(var(--grid-unit-20)*-1)}.wp-parsely-collapsible-panel.is-opened .components-panel__body-title{margin:0 calc(var(--grid-unit-20)*-1) .375rem;padding-bottom:0}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button{color:var(--Gutenberg-Gray-900,#1e1e1e);font-size:.6875rem;font-style:normal;font-weight:600;line-height:1rem;padding:var(--grid-unit-20) var(--grid-unit-20);text-transform:uppercase}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button .components-panel__arrow{margin-left:0}.wp-parsely-collapsible-panel .components-panel__body.is-opened{padding:0}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:focus,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:hover{background-color:#fff}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover{background-color:var(--parsely-green-65)}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed .wp-parsely-sidebar-icon path,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover .wp-parsely-sidebar-icon path{fill:var(--parsely-green-10)}.content-helper-error-message,.wp-parsely-content-helper-error .content-helper-error-message{margin-top:.9375rem!important}p.content-helper-error-message-hint{color:var(--gray-700)}.wp-parsely-content-helper-error.components-notice .components-notice__content{margin:0}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important}.wp-parsely-content-helper .wp-parsely-sidebar-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:1.5rem}.wp-parsely-content-helper .wp-parsely-sidebar-header .components-button{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel .panel-settings-button>button,.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel button.panel-settings-button{height:unset;min-width:unset;padding:0}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-panel>.content-helper-error-message{margin:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:3rem}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item:after{background:var(--gray-400);height:calc(var(--wp-admin-border-width-focus)*1);outline:2px solid transparent;outline-offset:-1px}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.is-active:after{background:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-content-helper .parsely-spinner-wrapper{display:flex;justify-content:center;margin:2.5rem 0}.wp-parsely-content-helper .parsely-spinner-wrapper svg{height:22px;width:22px} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper{display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding-bottom:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header .parsely-write-titles-text strong{text-transform:lowercase}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding-top:.375rem}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion.pinned-title{background:var(--Gutenberg-Gray-100,#f0f0f0)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title{align-items:center;align-self:stretch;color:#1e1e1e;display:flex;flex-direction:column;font-size:.75rem;font-style:normal;font-weight:600;gap:var(--grid-unit-10);justify-content:center;line-height:1.25rem;padding:var(--grid-unit-15) var(--grid-unit-15) 0 var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title .suggested-title-original{align-self:flex-start;margin:0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions{align-items:center;align-self:stretch;border-top:1px solid var(--Gutenberg-Gray-400,#ccc);display:flex;flex-wrap:wrap;height:2.5rem;padding:0 var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-left,.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-right{display:flex;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin-bottom:var(--grid-unit-20);position:relative}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay{align-items:center;background-color:hsla(0,0%,100%,.9);bottom:0;display:flex;flex-direction:column;gap:var(--grid-unit-10);justify-content:center;right:0;position:absolute;left:0;top:0;z-index:1}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay .components-spinner{transform:scale(1.125)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-pinned-suggestions{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-content-helper-error.components-notice{margin-bottom:var(--grid-unit-10)}.wp-parsely-popover .components-popover__content{width:15.5rem}.wp-parsely-suggested-title-modal{align-items:flex-start;display:flex;flex-direction:column;width:20rem}.wp-parsely-suggested-title-modal h2{color:var(--sidebar-black);font-size:1rem;font-style:normal;font-weight:600;line-height:1.5rem}.wp-parsely-suggested-title-modal .suggested-title-modal-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;margin-top:1.5rem} +.parsely-tone-selector-dropdown{align-items:center;align-self:stretch;background:var(--Gutenberg-White,#fff);border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-tone-selector-dropdown button{height:2.0625rem}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-tone-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle svg:first-of-type path{transform:scale(1.4);transform-origin:center}.parsely-tone-selector-dropdown .parsely-tone-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:right}.parsely-tone-selector-dropdown .parsely-tone-selector-label:first-letter{text-transform:uppercase}.parsely-persona-selector-custom{width:100%}.parsely-persona-selector-custom .components-base-control__field input{display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-persona-selector-custom .components-base-control__field input,.parsely-persona-selector-dropdown{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px}.parsely-persona-selector-dropdown{background:var(--Gutenberg-White,#fff);height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-persona-selector-dropdown button{height:2.0625rem}.parsely-persona-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-persona-selector-dropdown .parsely-persona-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:right}.parsely-persona-selector-dropdown .parsely-persona-selector-label:first-letter{text-transform:uppercase}.parsely-tone-selector-custom{width:100%}.parsely-tone-selector-custom .components-base-control__field input{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.parsely-inputrange-control{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-inputrange-control .parsely-inputrange-control__label{margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-20);height:2.5rem}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control{display:flex;flex:1 0 0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-inner-spin-button,.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]{-moz-appearance:textfield}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-base-control__field{flex-grow:1}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-input-control__suffix{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control{flex:1 0 0;height:36px}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control .components-range-control__root{height:2.5rem}.parsely-panel-settings{width:100%}.parsely-panel-settings .parsely-panel-settings-header{display:flex;margin:.625rem 0;width:100%}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label{flex-grow:2;margin:0 .3125rem 0 0;text-align:right}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field{align-items:center;display:flex;justify-content:space-between}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field .components-base-control__label{margin-bottom:0}.parsely-panel-settings .parsely-panel-settings-body{align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-dropdown-label{align-self:stretch;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-content-helper-error{align-self:flex-start;margin:0}.wp-parsely-content-helper-error p{margin:0}.wp-parsely-content-helper-error .content-helper-error-message{margin:0!important}.wp-parsely-collapsible-panel{align-items:flex-start;align-self:stretch;border-bottom:none;border-radius:2px;border-top:none;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:0 0 .5rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title{align-items:center;align-self:stretch;display:flex;margin:0 -1rem .375rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title .components-panel__icon,.wp-parsely-collapsible-panel .components-panel__body-title svg{margin-right:0;margin-left:var(--grid-unit-10);order:-1}.wp-parsely-collapsible-panel .components-panel__body-title:hover{background-color:transparent}.wp-parsely-collapsible-panel.is-opened{padding:0}.wp-parsely-collapsible-panel.is-opened>div:first-of-type{margin-top:calc(var(--grid-unit-20)*-1)}.wp-parsely-collapsible-panel.is-opened .components-panel__body-title{margin:0 calc(var(--grid-unit-20)*-1) .375rem;padding-bottom:0}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button{color:var(--Gutenberg-Gray-900,#1e1e1e);font-size:.6875rem;font-style:normal;font-weight:600;line-height:1rem;padding:var(--grid-unit-20) var(--grid-unit-20);text-transform:uppercase}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button .components-panel__arrow{margin-left:0}.wp-parsely-collapsible-panel .components-panel__body.is-opened{padding:0}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:focus,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:hover{background-color:#fff}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover{background-color:var(--parsely-green-65)}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed .wp-parsely-sidebar-icon path,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover .wp-parsely-sidebar-icon path{fill:var(--parsely-green-10)}.content-helper-error-message,.wp-parsely-content-helper-error .content-helper-error-message{margin-top:.9375rem!important}p.content-helper-error-message-hint{color:var(--gray-700)}.wp-parsely-content-helper-error.components-notice .components-notice__content{margin:0}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important}.wp-parsely-content-helper .wp-parsely-sidebar-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:1.5rem}.wp-parsely-content-helper .wp-parsely-sidebar-header .components-button{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel .panel-settings-button>button,.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel button.panel-settings-button{height:unset;min-width:unset;padding:0}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-panel>.content-helper-error-message{margin:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:3rem}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item:after{background:var(--gray-400);height:calc(var(--wp-admin-border-width-focus)*1);outline:2px solid transparent;outline-offset:-1px}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.is-active:after{background:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-content-helper .parsely-spinner-wrapper{display:flex;justify-content:center;margin:2.5rem 0}.wp-parsely-content-helper .parsely-spinner-wrapper svg{height:22px;width:22px} diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 6858edd20..c5ae176e1 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-plugins', 'wp-primitives', 'wp-url'), 'version' => '6e668f9bfad0f3f02bf6'); + 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-plugins', 'wp-primitives', 'wp-url'), 'version' => 'c56cfef0f833d0c36135'); diff --git a/build/content-helper/editor-sidebar.css b/build/content-helper/editor-sidebar.css index a06403d1e..d7de57746 100644 --- a/build/content-helper/editor-sidebar.css +++ b/build/content-helper/editor-sidebar.css @@ -1,5 +1,5 @@ #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-block-overlay{align-items:center;background-color:hsla(0,0%,100%,.85);box-sizing:border-box;display:flex;font-size:1.125rem;height:100%;justify-content:center;left:0;position:absolute;top:0;width:100%}.wp-parsely-block-overlay .wp-parsely-block-overlay-label{align-items:center;display:flex;flex-direction:column;flex-grow:1;gap:var(--grid-unit-10);justify-content:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--grid-unit-10)}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel{font-size:1.125rem;padding:0;pointer-events:all;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:10}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel:focus{box-shadow:none;outline:none}.wp-parsely-block-overlay svg{height:1.5625rem;width:1.5625rem}.wp-parsely-block-overlay.full-content-overlay{font-size:1.25rem;z-index:999}.wp-parsely-block-overlay.full-content-overlay span{margin-top:.9375rem}.wp-parsely-block-overlay.full-content-overlay svg{height:3.125rem;width:3.125rem}.wp-parsely-panel .components-panel__icon{height:1.5rem;margin:0 var(--grid-unit-15) 0 0;order:-1;width:1.5rem}.wp-parsely-smart-linking .components-panel__row{flex-direction:column;margin-bottom:0}.wp-parsely-smart-linking .components-base-control,.wp-parsely-smart-linking .components-base-control .components-panel__row,.wp-parsely-smart-linking .components-base-control:last-child{margin-bottom:0}.wp-parsely-smart-linking .smart-linking-text{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings{width:100%}.wp-parsely-smart-linking .parsely-panel-settings-body{display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select{align-self:stretch;display:flex;flex-direction:column;gap:1.5rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control-option-base{padding:.625rem 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control{height:40px;overflow:hidden}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s,color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button:not([data-active-item]){transition:color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-settings{align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-smart-linking .smart-linking-generate,.wp-parsely-smart-linking .smart-linking-manage{align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .smart-linking-generate button,.wp-parsely-smart-linking .smart-linking-manage button{align-items:center;align-self:stretch;display:flex;justify-content:center;width:100%}.wp-parsely-smart-linking .wp-parsely-smart-linking-suggested-links{margin:0}.wp-parsely-smart-linking .wp-parsely-smart-linking-hint{margin-top:calc(var(--grid-unit-10)*-1)}.wp-parsely-smart-linking-review-modal{align-items:flex-start;display:flex;flex-direction:column;width:47.875rem}.wp-parsely-smart-linking-review-modal .smart-linking-modal-body{align-self:stretch;display:flex;flex-direction:row;gap:var(--grid-unit-30)}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details{height:auto;margin-bottom:var(--grid-unit-20);text-align:left}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details .components-menu-item__item{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .linking-post-details{align-items:center;display:flex;justify-content:space-between;width:100%}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image{margin-right:.625rem;max-width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image .icon-container{align-items:center;display:flex;height:3.125rem;justify-content:center;width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title a{text-decoration:none}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info{display:flex;flex-direction:column;flex-grow:1}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info .linking-post-meta{color:var(--Gutenberg-Gray-700,#757575);font-size:.9em}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-type{color:var(--Gutenberg-Gray-700,#757575);margin-left:.625rem;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);min-width:13.75rem;padding:.1875rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs{margin-bottom:var(--grid-unit-20)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:var(--grid-unit-40)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item{color:var(--sidebar-black);font-size:.6875rem;font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item:focus-visible:before{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tab-content{max-height:23.125rem;overflow-y:auto}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip{align-items:center;display:flex;font-size:var(--font-size--small);margin-bottom:.3125rem;margin-top:-.5625rem;padding:.3125rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip .review-sidebar-tip svg{flex-shrink:0;height:1.5rem;margin-left:auto;width:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header{align-items:center;align-self:stretch;color:var(--sidebar-black);display:flex;font-size:.6875rem;font-style:normal;font-weight:600;gap:.375rem;line-height:var(--grid-unit-20);margin-bottom:var(--grid-unit-15);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header>span{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button{align-items:center;display:flex;justify-content:space-between;width:13.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button:focus{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-label{align-items:center;color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));display:flex;padding-left:var(--grid-unit-10);white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected{background-color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected .smart-linking-menu-label{color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .components-menu-item__item{padding-right:0;width:100%}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-item{display:inline;flex-grow:1;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion{align-items:flex-start;align-self:stretch;display:flex;flex:1;flex-direction:column;gap:1rem;max-width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs{font-size:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-separator{margin:0 var(--grid-unit-5)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-block{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block .breadcrumbs-current-block-name{margin-left:var(--grid-unit-10)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestion-post-title{font-size:var(--font-size--large);font-weight:500;line-height:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .components-divider{border-color:#ccc;height:1px;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots{color:#ccc;font-size:1rem;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-top{margin-bottom:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-bottom{margin-top:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls{align-items:center;align-self:stretch;display:flex;flex-shrink:0;justify-content:space-between;margin:0 var(--grid-unit-20);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .reviews-controls-middle{align-items:center;display:flex;flex:1 0 0;gap:var(--grid-unit-20);justify-content:center}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-next,.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-previous{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-reject{background:var(--Gutenberg-White,#fff);border-radius:2px;box-shadow:inset 0 0 0 1px var(--Gutenberg-Alert-Red,#cc1818);color:var(--Gutenberg-Alert-Red,#cc1818)}.wp-parsely-smart-linking-close-dialog{align-items:flex-start;display:flex;flex-direction:column;width:24rem}.wp-parsely-smart-linking-close-dialog .smart-linking-close-dialog-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;padding-top:var(--grid-unit-30)}.wp-parsely-preview-editor .editor-styles-wrapper{background:var(--Gutenberg-White,#fff);font-size:var(--font-size--medium);padding-bottom:0}.wp-parsely-preview-editor p[role=document]{margin:0}.wp-parsely-preview-editor .smart-linking-highlight{background:hsla(var(--parsely-green-components),.5);border-radius:2px;color:var(--sidebar-black)!important;mix-blend-mode:multiply;text-decoration-line:underline} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-performance-panel{border-top:1px solid #ddd;margin-top:-1px;padding:16px}.wp-parsely-content-helper .wp-parsely-performance-panel .content-helper-error-message{margin:0!important}.wp-parsely-content-helper .wp-parsely-performance-panel .components-button.wp-parsely-view-post{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .panel-body{width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.5rem;padding:.375rem 0 1rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header{align-items:center;display:flex;gap:.375rem;height:1rem;margin-bottom:0;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2{margin-bottom:.9375rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2 h2{margin-bottom:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-3 h3{font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:1rem;margin-bottom:0;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-subtitle{align-items:center;align-self:stretch;color:var(--Gutenberg-Gray-700,#757575);display:flex;flex:1 0 0;font-size:var(--font-size--smaller);font-style:normal;font-weight:600;gap:.375rem;height:1rem;line-height:1rem;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .components-heading{display:block;font-weight:500;line-height:normal;margin:0}.wp-parsely-content-helper .wp-parsely-performance-panel .components-dropdown-menu{line-height:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points{align-content:flex-start;align-items:flex-start;align-self:stretch;display:flex;flex-wrap:wrap;gap:1rem var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point{align-items:center;background:var(--sidebar-white);border-radius:.25rem;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-5);justify-content:center;min-width:100px;padding:var(--grid-unit-20) var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point svg{align-items:flex-start;border-radius:.125rem;display:flex}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-title{align-self:stretch;color:var(--sidebar-black);font-size:.75rem;font-style:normal;font-weight:400;line-height:1rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value{align-self:stretch;color:var(--sidebar-black);font-size:1.25rem;font-style:normal;font-weight:590;line-height:1.75rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value.is-small{font-size:var(--font-size--medium)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar{align-items:flex-start;align-self:stretch;display:flex;height:1rem;margin:1rem 0;position:relative}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill{--radius:2px;align-self:stretch;position:relative;transition:filter .1s ease,transform .1s ease}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:hover{filter:opacity(1)!important;transform:scaleX(1) scaleY(1)!important}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:first-child{border-radius:var(--radius) 0 0 var(--radius)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:last-child{border-radius:0 var(--radius) var(--radius) 0}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar:hover .bar-fill{filter:opacity(.5);transform:scaleX(1) scaleY(.7)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label{align-items:center;align-self:stretch;display:flex;gap:.5rem;justify-content:center}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color{align-items:center;border-radius:.09375rem;display:flex;flex-direction:column;gap:.625rem;height:.625rem;justify-content:center;width:.1875rem}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-text{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1 0 0;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-value{color:var(--sidebar-black);font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;text-align:right}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:1rem 0}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10);justify-content:space-between}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar{display:flex;flex:1;flex-direction:column;gap:.625rem;justify-content:center;max-width:6.25rem}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar{--radius:1.5px;background:var(--gray-400);border-radius:var(--radius);display:flex;height:.1875rem;margin:0;overflow:hidden}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar:after{background:var(--blueberry,#3858e9);border-radius:var(--radius);content:"";height:100%;width:var(--bar-fill)}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-value{color:var(--sidebar-black);flex-shrink:0;font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;min-width:3.125rem;text-align:right} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-related-posts{align-items:flex-start;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-description{font-size:.8125rem;font-style:normal;font-weight:400;gap:.625rem;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body,.wp-parsely-related-posts .related-posts-description{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body{gap:1rem}.wp-parsely-related-posts .related-posts-body>div{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings{align-self:stretch;display:flex;flex-direction:column;gap:1rem;width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings{display:flex;flex-direction:column;gap:var(--grid-unit-20);width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control{height:2.5rem;overflow:hidden}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex{height:2.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex input{margin:0 var(--grid-unit-15)}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-descr{font-size:.8125rem;font-style:normal;font-weight:400;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-empty,.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-loading-message{color:var(--gray-900);font-size:.75rem;font-style:normal;font-weight:700;line-height:var(--grid-unit-20);overflow:hidden;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-title{align-items:center;align-self:stretch;display:flex;flex-direction:column;font-size:.875rem;font-style:normal;font-weight:600;gap:.5rem;justify-content:center;line-height:1.25rem;overflow:hidden;padding:var(--grid-unit-20);text-decoration-line:underline;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions{align-items:center;align-self:stretch;border-top:1px solid var(--gray-400);display:flex;flex-wrap:wrap;padding:0 var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:first-child,.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:last-child{display:flex;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric{align-items:center;display:flex}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric .parsely-post-metric-data{align-items:center;display:flex;gap:var(--grid-unit-5)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-linked{align-items:center;display:flex;margin-left:auto;fill:#008a20}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon path{fill:#1e1e1e}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon:hover path{fill:#0073aa} -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper{display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding-bottom:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header .parsely-write-titles-text strong{text-transform:lowercase}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding-top:.375rem}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-dropdown-label{align-self:stretch;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .parsely-write-titles-accepted-title-container .parsely-write-titles-accepted-title{font-size:1rem;font-weight:600;line-height:1.25rem;margin:0 0 .9375rem;text-align:center}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .parsely-write-titles-accepted-title-container .parsely-write-titles-accepted-title-actions{display:flex;gap:.625rem;justify-content:center;margin:.625rem 0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion.pinned-title{background:var(--Gutenberg-Gray-100,#f0f0f0)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title{align-items:center;align-self:stretch;color:#1e1e1e;display:flex;flex-direction:column;font-size:.75rem;font-style:normal;font-weight:600;gap:var(--grid-unit-10);justify-content:center;line-height:1.25rem;padding:var(--grid-unit-15) var(--grid-unit-15) 0 var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title .suggested-title-original{align-self:flex-start;margin:0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions{align-items:center;align-self:stretch;border-top:1px solid var(--Gutenberg-Gray-400,#ccc);display:flex;flex-wrap:wrap;height:2.5rem;padding:0 var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-left,.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-right{display:flex;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin-bottom:var(--grid-unit-20);position:relative}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay{align-items:center;background-color:hsla(0,0%,100%,.9);bottom:0;display:flex;flex-direction:column;gap:var(--grid-unit-10);justify-content:center;left:0;position:absolute;right:0;top:0;z-index:1}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay .components-spinner{transform:scale(1.125)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-pinned-suggestions{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-content-helper-error.components-notice{margin-bottom:var(--grid-unit-10)}.wp-parsely-popover .components-popover__content{width:15.5rem}.wp-parsely-suggested-title-modal{align-items:flex-start;display:flex;flex-direction:column;width:20rem}.wp-parsely-suggested-title-modal h2{color:var(--sidebar-black);font-size:1rem;font-style:normal;font-weight:600;line-height:1.5rem}.wp-parsely-suggested-title-modal .suggested-title-modal-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;margin-top:1.5rem} -.parsely-tone-selector-dropdown{align-items:center;align-self:stretch;background:var(--Gutenberg-White,#fff);border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-tone-selector-dropdown button{height:2.0625rem}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-tone-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle svg:first-of-type path{transform:scale(1.4);transform-origin:center}.parsely-tone-selector-dropdown .parsely-tone-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:left}.parsely-tone-selector-dropdown .parsely-tone-selector-label:first-letter{text-transform:uppercase}.parsely-persona-selector-custom{width:100%}.parsely-persona-selector-custom .components-base-control__field input{display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-persona-selector-custom .components-base-control__field input,.parsely-persona-selector-dropdown{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px}.parsely-persona-selector-dropdown{background:var(--Gutenberg-White,#fff);height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-persona-selector-dropdown button{height:2.0625rem}.parsely-persona-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-persona-selector-dropdown .parsely-persona-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:left}.parsely-persona-selector-dropdown .parsely-persona-selector-label:first-letter{text-transform:uppercase}.parsely-tone-selector-custom{width:100%}.parsely-tone-selector-custom .components-base-control__field input{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.parsely-inputrange-control{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-inputrange-control .parsely-inputrange-control__label{margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-20);height:2.5rem}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control{display:flex;flex:1 0 0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-inner-spin-button,.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]{-moz-appearance:textfield}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-base-control__field{flex-grow:1}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-input-control__suffix{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control{flex:1 0 0;height:36px}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control .components-range-control__root{height:2.5rem}.parsely-panel-settings{width:100%}.parsely-panel-settings .parsely-panel-settings-header{display:flex;margin:.625rem 0;width:100%}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label{flex-grow:2;margin:0 0 0 .3125rem;text-align:left}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field{align-items:center;display:flex;justify-content:space-between}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field .components-base-control__label{margin-bottom:0}.parsely-panel-settings .parsely-panel-settings-body{align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-content-helper-error{align-self:flex-start;margin:0}.wp-parsely-content-helper-error p{margin:0}.wp-parsely-content-helper-error .content-helper-error-message{margin:0!important}.wp-parsely-collapsible-panel{align-items:flex-start;align-self:stretch;border-bottom:none;border-radius:2px;border-top:none;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:0 0 .5rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title{align-items:center;align-self:stretch;display:flex;margin:0 -1rem .375rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title .components-panel__icon,.wp-parsely-collapsible-panel .components-panel__body-title svg{margin-left:0;margin-right:var(--grid-unit-10);order:-1}.wp-parsely-collapsible-panel .components-panel__body-title:hover{background-color:transparent}.wp-parsely-collapsible-panel.is-opened{padding:0}.wp-parsely-collapsible-panel.is-opened>div:first-of-type{margin-top:calc(var(--grid-unit-20)*-1)}.wp-parsely-collapsible-panel.is-opened .components-panel__body-title{margin:0 calc(var(--grid-unit-20)*-1) .375rem;padding-bottom:0}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button{color:var(--Gutenberg-Gray-900,#1e1e1e);font-size:.6875rem;font-style:normal;font-weight:600;line-height:1rem;padding:var(--grid-unit-20) var(--grid-unit-20);text-transform:uppercase}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button .components-panel__arrow{margin-right:0}.wp-parsely-collapsible-panel .components-panel__body.is-opened{padding:0}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:focus,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:hover{background-color:#fff}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover{background-color:var(--parsely-green-65)}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed .wp-parsely-sidebar-icon path,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover .wp-parsely-sidebar-icon path{fill:var(--parsely-green-10)}.content-helper-error-message,.wp-parsely-content-helper-error .content-helper-error-message{margin-top:.9375rem!important}p.content-helper-error-message-hint{color:var(--gray-700)}.wp-parsely-content-helper-error.components-notice .components-notice__content{margin:0}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important}.wp-parsely-content-helper .wp-parsely-sidebar-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:1.5rem}.wp-parsely-content-helper .wp-parsely-sidebar-header .components-button{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel .panel-settings-button>button,.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel button.panel-settings-button{height:unset;min-width:unset;padding:0}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-panel>.content-helper-error-message{margin:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:3rem}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item:after{background:var(--gray-400);height:calc(var(--wp-admin-border-width-focus)*1);outline:2px solid transparent;outline-offset:-1px}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.is-active:after{background:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-content-helper .parsely-spinner-wrapper{display:flex;justify-content:center;margin:2.5rem 0}.wp-parsely-content-helper .parsely-spinner-wrapper svg{height:22px;width:22px} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper{display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding-bottom:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-header .parsely-write-titles-text strong{text-transform:lowercase}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding-top:.375rem}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion.pinned-title{background:var(--Gutenberg-Gray-100,#f0f0f0)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title{align-items:center;align-self:stretch;color:#1e1e1e;display:flex;flex-direction:column;font-size:.75rem;font-style:normal;font-weight:600;gap:var(--grid-unit-10);justify-content:center;line-height:1.25rem;padding:var(--grid-unit-15) var(--grid-unit-15) 0 var(--grid-unit-15)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title .suggested-title-original{align-self:flex-start;margin:0}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions{align-items:center;align-self:stretch;border-top:1px solid var(--Gutenberg-Gray-400,#ccc);display:flex;flex-wrap:wrap;height:2.5rem;padding:0 var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-left,.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-title-suggestion .suggested-title-actions .suggested-title-actions-container .suggested-title-actions-right{display:flex;gap:var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin-bottom:var(--grid-unit-20);position:relative}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay{align-items:center;background-color:hsla(0,0%,100%,.9);bottom:0;display:flex;flex-direction:column;gap:var(--grid-unit-10);justify-content:center;left:0;position:absolute;right:0;top:0;z-index:1}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .title-suggestions-container .wp-parsely-loading-overlay .components-spinner{transform:scale(1.125)}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-pinned-suggestions{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column}.wp-parsely-content-helper .wp-parsely-title-suggestions-wrapper .wp-parsely-content-helper-error.components-notice{margin-bottom:var(--grid-unit-10)}.wp-parsely-popover .components-popover__content{width:15.5rem}.wp-parsely-suggested-title-modal{align-items:flex-start;display:flex;flex-direction:column;width:20rem}.wp-parsely-suggested-title-modal h2{color:var(--sidebar-black);font-size:1rem;font-style:normal;font-weight:600;line-height:1.5rem}.wp-parsely-suggested-title-modal .suggested-title-modal-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;margin-top:1.5rem} +.parsely-tone-selector-dropdown{align-items:center;align-self:stretch;background:var(--Gutenberg-White,#fff);border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-tone-selector-dropdown button{height:2.0625rem}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-tone-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle svg:first-of-type path{transform:scale(1.4);transform-origin:center}.parsely-tone-selector-dropdown .parsely-tone-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:left}.parsely-tone-selector-dropdown .parsely-tone-selector-label:first-letter{text-transform:uppercase}.parsely-persona-selector-custom{width:100%}.parsely-persona-selector-custom .components-base-control__field input{display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-persona-selector-custom .components-base-control__field input,.parsely-persona-selector-dropdown{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px}.parsely-persona-selector-dropdown{background:var(--Gutenberg-White,#fff);height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-persona-selector-dropdown button{height:2.0625rem}.parsely-persona-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-persona-selector-dropdown .parsely-persona-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:left}.parsely-persona-selector-dropdown .parsely-persona-selector-label:first-letter{text-transform:uppercase}.parsely-tone-selector-custom{width:100%}.parsely-tone-selector-custom .components-base-control__field input{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.parsely-inputrange-control{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-inputrange-control .parsely-inputrange-control__label{margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-20);height:2.5rem}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control{display:flex;flex:1 0 0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-inner-spin-button,.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]{-moz-appearance:textfield}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-base-control__field{flex-grow:1}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-input-control__suffix{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control{flex:1 0 0;height:36px}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control .components-range-control__root{height:2.5rem}.parsely-panel-settings{width:100%}.parsely-panel-settings .parsely-panel-settings-header{display:flex;margin:.625rem 0;width:100%}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label{flex-grow:2;margin:0 0 0 .3125rem;text-align:left}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field{align-items:center;display:flex;justify-content:space-between}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field .components-base-control__label{margin-bottom:0}.parsely-panel-settings .parsely-panel-settings-body{align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-dropdown-label{align-self:stretch;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-content-helper-error{align-self:flex-start;margin:0}.wp-parsely-content-helper-error p{margin:0}.wp-parsely-content-helper-error .content-helper-error-message{margin:0!important}.wp-parsely-collapsible-panel{align-items:flex-start;align-self:stretch;border-bottom:none;border-radius:2px;border-top:none;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:0 0 .5rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title{align-items:center;align-self:stretch;display:flex;margin:0 -1rem .375rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title .components-panel__icon,.wp-parsely-collapsible-panel .components-panel__body-title svg{margin-left:0;margin-right:var(--grid-unit-10);order:-1}.wp-parsely-collapsible-panel .components-panel__body-title:hover{background-color:transparent}.wp-parsely-collapsible-panel.is-opened{padding:0}.wp-parsely-collapsible-panel.is-opened>div:first-of-type{margin-top:calc(var(--grid-unit-20)*-1)}.wp-parsely-collapsible-panel.is-opened .components-panel__body-title{margin:0 calc(var(--grid-unit-20)*-1) .375rem;padding-bottom:0}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button{color:var(--Gutenberg-Gray-900,#1e1e1e);font-size:.6875rem;font-style:normal;font-weight:600;line-height:1rem;padding:var(--grid-unit-20) var(--grid-unit-20);text-transform:uppercase}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button .components-panel__arrow{margin-right:0}.wp-parsely-collapsible-panel .components-panel__body.is-opened{padding:0}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:focus,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"]:hover{background-color:#fff}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover{background-color:var(--parsely-green-65)}.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed .wp-parsely-sidebar-icon path,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"].is-pressed:hover .wp-parsely-sidebar-icon path{fill:var(--parsely-green-10)}.content-helper-error-message,.wp-parsely-content-helper-error .content-helper-error-message{margin-top:.9375rem!important}p.content-helper-error-message-hint{color:var(--gray-700)}.wp-parsely-content-helper-error.components-notice .components-notice__content{margin:0}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-content-helper-error.components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important}.wp-parsely-content-helper .wp-parsely-sidebar-header{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:1.5rem}.wp-parsely-content-helper .wp-parsely-sidebar-header .components-button{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel .panel-settings-button>button,.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .components-panel button.panel-settings-button{height:unset;min-width:unset;padding:0}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-panel>.content-helper-error-message{margin:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:3rem}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item:after{background:var(--gray-400);height:calc(var(--wp-admin-border-width-focus)*1);outline:2px solid transparent;outline-offset:-1px}.wp-parsely-content-helper .wp-parsely-sidebar-main-panel .wp-parsely-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.is-active:after{background:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-content-helper .parsely-spinner-wrapper{display:flex;justify-content:center;margin:2.5rem 0}.wp-parsely-content-helper .parsely-spinner-wrapper svg{height:22px;width:22px} diff --git a/build/content-helper/excerpt-generator-rtl.css b/build/content-helper/excerpt-generator-rtl.css index f84e4b74c..61a2750ab 100644 --- a/build/content-helper/excerpt-generator-rtl.css +++ b/build/content-helper/excerpt-generator-rtl.css @@ -1 +1 @@ -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{right:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.wp-parsely-excerpt-generator{margin-top:1.25rem}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-right:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-right:.375rem}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{right:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.wp-parsely-excerpt-generator{margin-top:1.25rem}.wp-parsely-excerpt-generator .excerpt-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-right:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-right:.375rem}.wp-parsely-excerpt-generator .excerpt-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;margin:var(--grid-unit-10) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} diff --git a/build/content-helper/excerpt-generator.asset.php b/build/content-helper/excerpt-generator.asset.php index b9e272436..6d2889225 100644 --- a/build/content-helper/excerpt-generator.asset.php +++ b/build/content-helper/excerpt-generator.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'f4a464bba52051300fa7'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '71e77ba27d5916d7d836'); diff --git a/build/content-helper/excerpt-generator.css b/build/content-helper/excerpt-generator.css index 039140a6b..5bafbe846 100644 --- a/build/content-helper/excerpt-generator.css +++ b/build/content-helper/excerpt-generator.css @@ -1 +1 @@ -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{left:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.wp-parsely-excerpt-generator{margin-top:1.25rem}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-left:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-left:.375rem}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{left:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.wp-parsely-excerpt-generator{margin-top:1.25rem}.wp-parsely-excerpt-generator .excerpt-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-left:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-left:.375rem}.wp-parsely-excerpt-generator .excerpt-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;margin:var(--grid-unit-10) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} diff --git a/build/content-helper/excerpt-generator.js b/build/content-helper/excerpt-generator.js index 724730f86..14589d917 100644 --- a/build/content-helper/excerpt-generator.js +++ b/build/content-helper/excerpt-generator.js @@ -1,4 +1,4 @@ -!function(){"use strict";var e={20:function(e,t,r){var n=r(609),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,s=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,a={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,n)&&!l.hasOwnProperty(n)&&(a[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===a[n]&&(a[n]=t[n]);return{$$typeof:o,type:e,key:c,ref:u,props:a,_owner:s.current}}t.Fragment=a,t.jsx=c,t.jsxs=c},848:function(e,t,r){e.exports=r(20)},609:function(e){e.exports=window.React}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e,t,n,o,a,i,s,l,c,u,p,d=window.wp.data,y=window.wp.hooks,h=window.wp.plugins,f=((0,d.dispatch)("core/block-editor"),(0,d.dispatch)("core/editor"),(0,d.dispatch)("core/edit-post")),w=r(848),v=window.wp.components,g=window.wp.editor;void 0!==window.wp&&(p=null!==(t=null===(e=window.wp.editor)||void 0===e?void 0:e.PluginDocumentSettingPanel)&&void 0!==t?t:null!==(o=null===(n=window.wp.editPost)||void 0===n?void 0:n.PluginDocumentSettingPanel)&&void 0!==o?o:null===(a=window.wp.editSite)||void 0===a?void 0:a.PluginDocumentSettingPanel,null!==(s=null===(i=window.wp.editor)||void 0===i?void 0:i.PluginSidebar)&&void 0!==s||null!==(c=null===(l=window.wp.editPost)||void 0===l?void 0:l.PluginSidebar)&&void 0!==c||null===(u=window.wp.editSite)||void 0===u||u.PluginSidebar);var _,b,P=window.wp.element,m=window.wp.i18n,x=window.wp.wordcount,E=window.wp.primitives,A=(0,w.jsx)(E.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,w.jsx)(E.Path,{d:"M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"})}),S=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 r=this,n=arguments,a=function(t,r){var n;return void 0===r&&(r={}),function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(l){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=1e4&&(clearInterval(a),r("Telemetry library not loaded"))}),100);else r("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,r){var n;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(r=this.prepareProperties(r),null===(n=this._tkq)||void 0===n||n.push(["recordEvent",t,r])):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,r={};return Object.keys(e).forEach((function(n){t.isProprietyValid(n)&&(r[n]=e[n])})),r},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),k=(S.trackEvent,function(e){void 0===e&&(e=null);var t="";(null==e?void 0:e.children)&&(t=e.children);var r="content-helper-error-message";return(null==e?void 0:e.className)&&(r+=" "+e.className),(0,w.jsx)("div",{className:r,"data-testid":null==e?void 0:e.testId,dangerouslySetInnerHTML:{__html:t}})}),T=(_=function(e,t){return _=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},_(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function __(){this.constructor=e}_(e,t),e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)});!function(e){e.AccessToFeatureDisabled="ch_access_to_feature_disabled",e.CannotFormulateApiQuery="ch_cannot_formulate_api_query",e.FetchError="fetch_error",e.HttpRequestFailed="http_request_failed",e.ParselyAborted="ch_parsely_aborted",e[e.ParselyApiForbidden=403]="ParselyApiForbidden",e.ParselyApiResponseContainsError="ch_response_contains_error",e.ParselyApiReturnedNoData="ch_parsely_api_returned_no_data",e.ParselyApiReturnedTooManyResults="ch_parsely_api_returned_too_many_results",e.PluginCredentialsNotSetMessageDetected="parsely_credentials_not_set_message_detected",e.PluginSettingsApiSecretNotSet="parsely_api_secret_not_set",e.PluginSettingsSiteIdNotSet="parsely_site_id_not_set",e.PostIsNotPublished="ch_post_not_published",e.UnknownError="ch_unknown_error",e.ParselySuggestionsApiAuthUnavailable="AUTH_UNAVAILABLE",e.ParselySuggestionsApiNoAuthentication="NO_AUTHENTICATION",e.ParselySuggestionsApiNoAuthorization="NO_AUTHORIZATION",e.ParselySuggestionsApiNoData="NO_DATA",e.ParselySuggestionsApiOpenAiError="OPENAI_ERROR",e.ParselySuggestionsApiOpenAiSchema="OPENAI_SCHEMA",e.ParselySuggestionsApiOpenAiUnavailable="OPENAI_UNAVAILABLE",e.ParselySuggestionsApiSchemaError="SCHEMA_ERROR"}(b||(b={}));var N=function(e){function t(r,n,o){void 0===o&&(o=(0,m.__)("Error:","wp-parsely"));var a=this;r.startsWith(o)&&(o=""),(a=e.call(this,o.length>0?"".concat(o," ").concat(r):r)||this).hint=null,a.name=a.constructor.name,a.code=n;var i=[b.AccessToFeatureDisabled,b.ParselyApiForbidden,b.ParselyApiResponseContainsError,b.ParselyApiReturnedNoData,b.ParselyApiReturnedTooManyResults,b.PluginCredentialsNotSetMessageDetected,b.PluginSettingsApiSecretNotSet,b.PluginSettingsSiteIdNotSet,b.PostIsNotPublished,b.UnknownError,b.ParselySuggestionsApiAuthUnavailable,b.ParselySuggestionsApiNoAuthentication,b.ParselySuggestionsApiNoAuthorization,b.ParselySuggestionsApiNoData,b.ParselySuggestionsApiSchemaError];return a.retryFetch=!i.includes(a.code),Object.setPrototypeOf(a,t.prototype),a.code===b.AccessToFeatureDisabled?a.message=(0,m.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):a.code===b.ParselySuggestionsApiNoAuthorization?a.message=(0,m.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):a.code===b.ParselySuggestionsApiOpenAiError||a.code===b.ParselySuggestionsApiOpenAiUnavailable?a.message=(0,m.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):a.code===b.HttpRequestFailed&&a.message.includes("cURL error 28")?a.message=(0,m.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):a.code===b.ParselySuggestionsApiSchemaError?a.message=(0,m.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):a.code===b.ParselySuggestionsApiNoData?a.message=(0,m.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):a.code===b.ParselySuggestionsApiOpenAiSchema?a.message=(0,m.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):a.code===b.ParselySuggestionsApiAuthUnavailable&&(a.message=(0,m.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),a}return T(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[b.PluginCredentialsNotSetMessageDetected,b.PluginSettingsSiteIdNotSet,b.PluginSettingsApiSecretNotSet].includes(this.code)?function(e){var t;return void 0===e&&(e=null),(0,w.jsx)(k,{className:null==e?void 0:e.className,testId:"empty-credentials-message",children:null!==(t=window.wpParselyEmptyCredentialsMessage)&&void 0!==t?t:(0,m.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})}(e):(this.code===b.FetchError&&(this.hint=this.Hint((0,m.__)("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!==b.ParselyApiForbidden&&this.code!==b.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,m.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===b.HttpRequestFailed&&(this.hint=this.Hint((0,m.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,w.jsx)(k,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,m.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,d.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),j=function(e){var t=e.size,r=void 0===t?24:t,n=e.className,o=void 0===n?"wp-parsely-icon":n;return(0,w.jsxs)(v.SVG,{className:o,height:r,viewBox:"0 0 60 65",width:r,xmlns:"http://www.w3.org/2000/svg",children:[(0,w.jsx)(v.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,w.jsx)(v.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,w.jsx)(v.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,w.jsx)(v.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"})]})},I=window.wp.url,O=window.wp.apiFetch,C=r.n(O),R=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,r=Array.from(this.abortControllers.keys()).pop();r&&(t=this.abortControllers.get(r))&&(t.abort(),this.abortControllers.delete(r))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),r=new AbortController;return this.abortControllers.set(t,r),{abortController:r,abortId:t}},e.prototype.fetch=function(e,t){return r=this,n=void 0,a=function(){var r,n,o,a,i,s;return function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(l){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]0?(0,m.sprintf)( +!function(){"use strict";var e={20:function(e,t,r){var n=r(609),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),s=Object.prototype.hasOwnProperty,i=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,a={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)s.call(t,n)&&!l.hasOwnProperty(n)&&(a[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===a[n]&&(a[n]=t[n]);return{$$typeof:o,type:e,key:c,ref:u,props:a,_owner:i.current}}t.Fragment=a,t.jsx=c,t.jsxs=c},848:function(e,t,r){e.exports=r(20)},609:function(e){e.exports=window.React}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e=r(848),t=window.wp.data,n=window.wp.hooks,o=window.wp.plugins,a=((0,t.dispatch)("core/block-editor"),(0,t.dispatch)("core/editor"),(0,t.dispatch)("core/edit-post")),s=function(){return s=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=1e4&&(clearInterval(a),r("Telemetry library not loaded"))}),100);else r("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,r){var n;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(r=this.prepareProperties(r),null===(n=this._tkq)||void 0===n||n.push(["recordEvent",t,r])):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,r={};return Object.keys(e).forEach((function(n){t.isProprietyValid(n)&&(r[n]=e[n])})),r},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),L=(D.trackEvent,function(t){void 0===t&&(t=null);var r="";(null==t?void 0:t.children)&&(r=t.children);var n="content-helper-error-message";return(null==t?void 0:t.className)&&(n+=" "+t.className),(0,e.jsx)("div",{className:n,"data-testid":null==t?void 0:t.testId,dangerouslySetInnerHTML:{__html:r}})}),F=(O=function(e,t){return O=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},O(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function __(){this.constructor=e}O(e,t),e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)});!function(e){e.AccessToFeatureDisabled="ch_access_to_feature_disabled",e.CannotFormulateApiQuery="ch_cannot_formulate_api_query",e.FetchError="fetch_error",e.HttpRequestFailed="http_request_failed",e.ParselyAborted="ch_parsely_aborted",e[e.ParselyApiForbidden=403]="ParselyApiForbidden",e.ParselyApiResponseContainsError="ch_response_contains_error",e.ParselyApiReturnedNoData="ch_parsely_api_returned_no_data",e.ParselyApiReturnedTooManyResults="ch_parsely_api_returned_too_many_results",e.PluginCredentialsNotSetMessageDetected="parsely_credentials_not_set_message_detected",e.PluginSettingsApiSecretNotSet="parsely_api_secret_not_set",e.PluginSettingsSiteIdNotSet="parsely_site_id_not_set",e.PostIsNotPublished="ch_post_not_published",e.UnknownError="ch_unknown_error",e.ParselySuggestionsApiAuthUnavailable="AUTH_UNAVAILABLE",e.ParselySuggestionsApiNoAuthentication="NO_AUTHENTICATION",e.ParselySuggestionsApiNoAuthorization="NO_AUTHORIZATION",e.ParselySuggestionsApiNoData="NO_DATA",e.ParselySuggestionsApiOpenAiError="OPENAI_ERROR",e.ParselySuggestionsApiOpenAiSchema="OPENAI_SCHEMA",e.ParselySuggestionsApiOpenAiUnavailable="OPENAI_UNAVAILABLE",e.ParselySuggestionsApiSchemaError="SCHEMA_ERROR"}(R||(R={}));var M=function(r){function n(e,t,o){void 0===o&&(o=(0,C.__)("Error:","wp-parsely"));var a=this;e.startsWith(o)&&(o=""),(a=r.call(this,o.length>0?"".concat(o," ").concat(e):e)||this).hint=null,a.name=a.constructor.name,a.code=t;var s=[R.AccessToFeatureDisabled,R.ParselyApiForbidden,R.ParselyApiResponseContainsError,R.ParselyApiReturnedNoData,R.ParselyApiReturnedTooManyResults,R.PluginCredentialsNotSetMessageDetected,R.PluginSettingsApiSecretNotSet,R.PluginSettingsSiteIdNotSet,R.PostIsNotPublished,R.UnknownError,R.ParselySuggestionsApiAuthUnavailable,R.ParselySuggestionsApiNoAuthentication,R.ParselySuggestionsApiNoAuthorization,R.ParselySuggestionsApiNoData,R.ParselySuggestionsApiSchemaError];return a.retryFetch=!s.includes(a.code),Object.setPrototypeOf(a,n.prototype),a.code===R.AccessToFeatureDisabled?a.message=(0,C.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):a.code===R.ParselySuggestionsApiNoAuthorization?a.message=(0,C.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):a.code===R.ParselySuggestionsApiOpenAiError||a.code===R.ParselySuggestionsApiOpenAiUnavailable?a.message=(0,C.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):a.code===R.HttpRequestFailed&&a.message.includes("cURL error 28")?a.message=(0,C.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):a.code===R.ParselySuggestionsApiSchemaError?a.message=(0,C.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):a.code===R.ParselySuggestionsApiNoData?a.message=(0,C.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):a.code===R.ParselySuggestionsApiOpenAiSchema?a.message=(0,C.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):a.code===R.ParselySuggestionsApiAuthUnavailable&&(a.message=(0,C.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),a}return F(n,r),n.prototype.Message=function(t){return void 0===t&&(t=null),[R.PluginCredentialsNotSetMessageDetected,R.PluginSettingsSiteIdNotSet,R.PluginSettingsApiSecretNotSet].includes(this.code)?function(t){var r;return void 0===t&&(t=null),(0,e.jsx)(L,{className:null==t?void 0:t.className,testId:"empty-credentials-message",children:null!==(r=window.wpParselyEmptyCredentialsMessage)&&void 0!==r?r:(0,C.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})}(t):(this.code===R.FetchError&&(this.hint=this.Hint((0,C.__)("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!==R.ParselyApiForbidden&&this.code!==R.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,C.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===R.HttpRequestFailed&&(this.hint=this.Hint((0,C.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,e.jsx)(L,{className:null==t?void 0:t.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},n.prototype.Hint=function(e){return'

'.concat((0,C.__)("Hint:","wp-parsely")," ").concat(e,"

")},n.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,t.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},n}(Error),G=function(t){var r=t.size,n=void 0===r?24:r,o=t.className,a=void 0===o?"wp-parsely-icon":o;return(0,e.jsxs)(j.SVG,{className:a,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,e.jsx)(j.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,e.jsx)(j.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,e.jsx)(j.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,e.jsx)(j.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"})]})},U=window.wp.url,H=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,r=Array.from(this.abortControllers.keys()).pop();r&&(t=this.abortControllers.get(r))&&(t.abort(),this.abortControllers.delete(r))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),r=new AbortController;return this.abortControllers.set(t,r),{abortController:r,abortId:t}},e.prototype.fetch=function(e,t){return r=this,n=void 0,a=function(){var r,n,o,a,s,i;return function(e,t){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=i(0),s.throw=i(1),s.return=i(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function i(i){return function(l){return function(i){if(r)throw new TypeError("Generator is already executing.");for(;s&&(s=0,i[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&i[0]?n.return:i[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,i[1])).done)return o;switch(n=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,n=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]32&&(e=e.slice(0,32)),i(e),s(e)}})})},Q=function(t){var r=t.persona,n=t.value,o=void 0===n?(0,C.__)("Select a persona…","wp-parsely"):n,a=t.label,s=void 0===a?(0,C.__)("Persona","wp-parsely"):a,i=t.onChange,l=t.onDropdownChange,c=t.disabled,u=void 0!==c&&c,p=t.allowCustom,d=void 0!==p&&p;return(0,e.jsxs)(j.Disabled,{isDisabled:u,children:[s&&(0,e.jsx)("div",{className:"wp-parsely-dropdown-label",children:s}),(0,e.jsx)(j.DropdownMenu,{label:(0,C.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(u?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("div",{className:"parsely-persona-selector-label",children:K(r)?J.custom.label:o}),(0,e.jsx)(X,{})]})},children:function(t){var n=t.onClose;return(0,e.jsx)(j.MenuGroup,{label:(0,C.__)("Persona","wp-parsely"),children:(0,e.jsx)(e.Fragment,{children:Z.map((function(t){if(!d&&"custom"===t)return null;var o=J[t],a=t===r||K(r)&&"custom"===t;return(0,e.jsxs)(j.MenuItem,{isSelected:a,className:a?"is-selected":"",role:"menuitemradio",onClick:function(){null==l||l(t),i(t),n(),"custom"===t&&setTimeout((function(){var e=document.querySelector(".parsely-persona-selector-custom input");e&&e.focus()}),0)},children:[o.icon&&(0,e.jsx)(W,{icon:o.icon}),o.label]},t)}))})})}}),d&&K(r)&&(0,e.jsx)(Y,{onChange:function(e){i(""!==e?e:"custom")},value:"custom"===r?"":r})]})},ee={neutral:{label:(0,C.__)("Neutral","wp-parsely")},formal:{label:(0,C.__)("Formal","wp-parsely")},humorous:{label:(0,C.__)("Humorous","wp-parsely")},confident:{label:(0,C.__)("Confident","wp-parsely")},provocative:{label:(0,C.__)("Provocative","wp-parsely")},serious:{label:(0,C.__)("Serious","wp-parsely")},inspirational:{label:(0,C.__)("Inspirational","wp-parsely")},skeptical:{label:(0,C.__)("Skeptical","wp-parsely")},conversational:{label:(0,C.__)("Conversational","wp-parsely")},analytical:{label:(0,C.__)("Analytical","wp-parsely")},custom:{label:(0,C.__)("Custom Tone","wp-parsely"),icon:V}},te=Object.keys(ee),re=function(e){return"custom"===e||""===e?ee.custom.label:ne(e)?e:ee[e].label},ne=function(e){return!te.includes(e)||"custom"===e},oe=function(t){var r=t.value,n=t.onChange,o=(0,d.useState)(""),a=o[0],s=o[1],i=(0,z.useDebounce)(n,500);return(0,e.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,e.jsx)(j.TextControl,{value:a||r,placeholder:(0,C.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void s("");e.length>32&&(e=e.slice(0,32)),i(e),s(e)}})})},ae=function(t){var r=t.tone,n=t.value,o=void 0===n?(0,C.__)("Select a tone","wp-parsely"):n,a=t.label,s=void 0===a?(0,C.__)("Tone","wp-parsely"):a,i=t.onChange,l=t.onDropdownChange,c=t.disabled,u=void 0!==c&&c,p=t.allowCustom,d=void 0!==p&&p;return(0,e.jsxs)(j.Disabled,{isDisabled:u,children:[(0,e.jsx)("div",{className:"wp-parsely-dropdown-label",children:s}),(0,e.jsx)(j.DropdownMenu,{label:(0,C.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(u?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("div",{className:"parsely-tone-selector-label",children:ne(r)?ee.custom.label:o}),(0,e.jsx)(X,{})]})},children:function(t){var n=t.onClose;return(0,e.jsx)(j.MenuGroup,{label:(0,C.__)("Select a tone","wp-parsely"),children:(0,e.jsx)(e.Fragment,{children:te.map((function(t){if(!d&&"custom"===t)return null;var o=ee[t],a=t===r||ne(r)&&"custom"===t;return(0,e.jsxs)(j.MenuItem,{isSelected:a,className:a?"is-selected":"",role:"menuitemradio",onClick:function(){null==l||l(t),i(t),n(),"custom"===t&&setTimeout((function(){var e=document.querySelector(".parsely-tone-selector-custom input");e&&e.focus()}),0)},children:[o.icon&&(0,e.jsx)(W,{icon:o.icon}),o.label]},t)}))})})}}),d&&ne(r)&&(0,e.jsx)(oe,{onChange:function(e){i(""!==e?e:"custom")},value:"custom"===r?"":r})]})},se=function(t){var r=t.isLoading,n=t.onPersonaChange,o=t.onToneChange,a=t.persona,s=t.tone;return(0,e.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,e.jsx)(ae,{tone:s,value:re(s),onChange:function(e){o(e)},onDropdownChange:function(e){D.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:r,allowCustom:!0}),(0,e.jsx)(Q,{persona:a,value:$(a),onChange:function(e){n(e)},onDropdownChange:function(e){D.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:r,allowCustom:!0})]})},ie=function(){return ie=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?(0,C.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. -(0,m._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[h.currentExcerpt,k]),(0,P.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[h.newExcerptGeneratedCount]),(0,w.jsxs)("div",{className:"editor-post-excerpt",children:[(0,w.jsxs)("div",{style:{position:"relative"},children:[t&&(0,w.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,w.jsx)(H,{})}),(0,w.jsx)(v.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,m.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){h.isUnderReview||_({excerpt:e}),f(F(F({},h),{currentExcerpt:e})),l(!0)},onKeyUp:function(){var e;if(s)l(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),r=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";f(F(F({},h),{currentExcerpt:r}))}},value:t?"":h.isUnderReview?h.currentExcerpt:k,help:u||null})]}),(0,w.jsxs)(v.Button,{href:(0,m.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,m.__)("Learn more about manual excerpts","wp-parsely"),(0,w.jsx)(v.Icon,{icon:A,size:18,className:"parsely-external-link-icon"})]}),(0,w.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[(0,w.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,w.jsx)(j,{size:16}),(0,w.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,m.__)("Generate With Parse.ly","wp-parsely"),(0,w.jsx)("span",{className:"beta-label",children:(0,m.__)("Beta","wp-parsely")})]})]}),o&&(0,w.jsx)(v.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return a(void 0)},status:"info",children:o.Message()}),(0,w.jsx)("div",{className:"wp-parsely-excerpt-generator-controls",children:h.isUnderReview?(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(v.Button,{variant:"secondary",onClick:function(){return L(void 0,void 0,void 0,(function(){return M(this,(function(e){switch(e.label){case 0:return[4,_({excerpt:h.currentExcerpt})];case 1:return e.sent(),f(F(F({},h),{isUnderReview:!1})),S.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,m.__)("Accept","wp-parsely")}),(0,w.jsx)(v.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return L(void 0,void 0,void 0,(function(){return M(this,(function(e){return _({excerpt:h.oldExcerpt}),f(F(F({},h),{currentExcerpt:h.oldExcerpt,isUnderReview:!1})),S.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,m.__)("Discard","wp-parsely")})]}):(0,w.jsxs)(v.Button,{onClick:function(){return L(void 0,void 0,void 0,(function(){var e,t;return M(this,(function(n){switch(n.label){case 0:r(!0),a(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),S.trackEvent("excerpt_generator_pressed"),[4,D.getInstance().generateExcerpt(I,T)];case 2:return e=n.sent(),f({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:h.newExcerptGeneratedCount+1,oldExcerpt:k}),[3,5];case 3:return(t=n.sent())instanceof N?a(t):(a(new N((0,m.__)("An unknown error occurred.","wp-parsely"),b.UnknownError)),console.error(t)),[3,5];case 4:return r(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:t,disabled:t||!T,children:[t&&(0,m.__)("Generating Excerpt…","wp-parsely"),!t&&h.newExcerptGeneratedCount>0&&(0,m.__)("Regenerate Excerpt","wp-parsely"),!t&&0===h.newExcerptGeneratedCount&&(0,m.__)("Generate Excerpt","wp-parsely")]})}),(0,w.jsxs)(v.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,m.__)("Learn more about Parse.ly AI","wp-parsely"),(0,w.jsx)(v.Icon,{icon:A,size:18,className:"parsely-external-link-icon"})]})]})]})},H=function(){return(0,w.jsx)(v.Animate,{type:"loading",children:function(e){var t=e.className;return(0,w.jsx)("span",{className:t,children:(0,m.__)("Generating…","wp-parsely")})}})},q=function(){return(0,w.jsx)(g.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,w.jsx)(p,{name:"parsely-post-excerpt",title:(0,m.__)("Excerpt","wp-parsely"),children:(0,w.jsx)(G,{})})})};(0,y.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-generator",(function(e,t){var r,n,o;return"wp-parsely-block-editor-sidebar"!==t||((null===(r=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===r?void 0:r.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,y.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,h.registerPlugin)("wp-parsely-excerpt-generator",{render:q}),(null===(n=(0,d.dispatch)("core/editor"))||void 0===n?void 0:n.removeEditorPanel)?null===(o=(0,d.dispatch)("core/editor"))||void 0===o||o.removeEditorPanel("post-excerpt"):null==f||f.removeEditorPanel("post-excerpt")),e}),1e3)}()}(); \ No newline at end of file +(0,C._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[c.currentExcerpt,U]),(0,d.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[c.newExcerptGeneratedCount]);var z=(0,e.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,e.jsx)(G,{size:16}),(0,e.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,C.__)("Generate With Parse.ly","wp-parsely"),(0,e.jsx)("span",{className:"beta-label",children:(0,C.__)("Beta","wp-parsely")})]})]});return(0,e.jsxs)("div",{className:"editor-post-excerpt",children:[(0,e.jsxs)("div",{style:{position:"relative"},children:[h&&(0,e.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,e.jsx)(pe,{})}),(0,e.jsx)(j.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,C.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){c.isUnderReview||O({excerpt:e}),u(ie(ie({},c),{currentExcerpt:e})),g(!0)},onKeyUp:function(){var e;if(v)g(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),r=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";u(ie(ie({},c),{currentExcerpt:r}))}},value:h?"":c.isUnderReview?c.currentExcerpt:U,help:A||null})]}),(0,e.jsxs)(j.Button,{href:(0,C.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,C.__)("Learn more about manual excerpts","wp-parsely"),(0,e.jsx)(j.Icon,{icon:k,size:18,className:"parsely-external-link-icon"})]}),(0,e.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[s&&(0,e.jsx)(j.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return i(void 0)},status:"info",children:s.Message()}),c.isUnderReview?(0,e.jsxs)(e.Fragment,{children:[z,(0,e.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,e.jsx)(j.Button,{variant:"secondary",onClick:function(){return le(void 0,void 0,void 0,(function(){return ce(this,(function(e){switch(e.label){case 0:return[4,O({excerpt:c.currentExcerpt})];case 1:return e.sent(),u(ie(ie({},c),{isUnderReview:!1})),D.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,C.__)("Accept","wp-parsely")}),(0,e.jsx)(j.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return le(void 0,void 0,void 0,(function(){return ce(this,(function(e){return O({excerpt:c.oldExcerpt}),u(ie(ie({},c),{currentExcerpt:c.oldExcerpt,isUnderReview:!1})),D.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,C.__)("Discard","wp-parsely")})]})]}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(se,{isLoading:h,onPersonaChange:function(e){L("Persona",e),m(e)},onSettingChange:L,onToneChange:function(e){L("Tone",e),S(e)},persona:n.Persona,tone:n.Tone}),z,(0,e.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,e.jsxs)(j.Button,{onClick:function(){return le(void 0,void 0,void 0,(function(){var e,t;return ce(this,(function(r){switch(r.label){case 0:f(!0),i(void 0),r.label=1;case 1:return r.trys.push([1,3,4,5]),D.trackEvent("excerpt_generator_pressed"),[4,q.getInstance().generateExcerpt(B,H,b,P)];case 2:return e=r.sent(),u({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:c.newExcerptGeneratedCount+1,oldExcerpt:U}),[3,5];case 3:return(t=r.sent())instanceof M?i(t):(i(new M((0,C.__)("An unknown error occurred.","wp-parsely"),R.UnknownError)),console.error(t)),[3,5];case 4:return f(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:h,disabled:h||!H,children:[h&&(0,C.__)("Generating Excerpt…","wp-parsely"),!h&&c.newExcerptGeneratedCount>0&&(0,C.__)("Regenerate Excerpt","wp-parsely"),!h&&0===c.newExcerptGeneratedCount&&(0,C.__)("Generate Excerpt","wp-parsely")]})})]}),(0,e.jsxs)(j.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,C.__)("Learn more about Parse.ly AI","wp-parsely"),(0,e.jsx)(j.Icon,{icon:k,size:18,className:"parsely-external-link-icon"})]})]})]})},pe=function(){return(0,e.jsx)(j.Animate,{type:"loading",children:function(t){var r=t.className;return(0,e.jsx)("span",{className:r,children:(0,C.__)("Generating…","wp-parsely")})}})},de=function(){return(0,e.jsx)(T.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,e.jsx)(A,{name:"parsely-post-excerpt",title:(0,C.__)("Excerpt","wp-parsely"),children:(0,e.jsx)(ue,{})})})},he=function(e){var t;try{t=JSON.parse(e)}catch(e){return{Open:!1,Persona:"journalist",Tone:"neutral"}}return"boolean"!=typeof(null==t?void 0:t.Open)&&(t.Open=!1),"string"!=typeof(null==t?void 0:t.Persona)&&(t.Persona="journalist"),"string"!=typeof(null==t?void 0:t.Tone)&&(t.Tone="neutral"),t};(0,n.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-generator",(function(r,s){var i,l,c;return"wp-parsely-block-editor-sidebar"!==s||((null===(i=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===i?void 0:i.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,n.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,o.registerPlugin)("wp-parsely-excerpt-generator",{render:function(){return(0,e.jsx)(f,{endpoint:"excerpt-suggestions",defaultSettings:he(window.wpParselyContentHelperSettings),children:(0,e.jsx)(de,{})})}}),(null===(l=(0,t.dispatch)("core/editor"))||void 0===l?void 0:l.removeEditorPanel)?null===(c=(0,t.dispatch)("core/editor"))||void 0===c||c.removeEditorPanel("post-excerpt"):null==a||a.removeEditorPanel("post-excerpt")),r}),1e3)}()}(); \ No newline at end of file diff --git a/src/content-helper/common/css/common.scss b/src/content-helper/common/css/common.scss index 25c1182d0..e21ea9b2e 100644 --- a/src/content-helper/common/css/common.scss +++ b/src/content-helper/common/css/common.scss @@ -45,6 +45,16 @@ } } +.wp-parsely-dropdown-label { + align-self: stretch; + color: var(--sidebar-black); + font-size: var(--font-size--smaller); + font-style: normal; + font-weight: 600; + line-height: var(--grid-unit-20); + text-transform: uppercase; +} + .wp-parsely-content-helper-error { margin: 0; align-self: flex-start; diff --git a/src/content-helper/common/settings/types/excerpt-suggestions-settings.d.ts b/src/content-helper/common/settings/types/excerpt-suggestions-settings.d.ts new file mode 100644 index 000000000..5be6c32cb --- /dev/null +++ b/src/content-helper/common/settings/types/excerpt-suggestions-settings.d.ts @@ -0,0 +1,10 @@ +/** + * Defines the settings structure for the PostExcerptGenerator component. + * + * @since 3.17.0 + */ +export interface ExcerptSuggestionsSettings { + Open: boolean; + Persona: string; + Tone: string; +} diff --git a/src/content-helper/common/settings/types/index.ts b/src/content-helper/common/settings/types/index.ts index 6b22cb809..ec8e95134 100644 --- a/src/content-helper/common/settings/types/index.ts +++ b/src/content-helper/common/settings/types/index.ts @@ -1,6 +1,7 @@ /** * Import the settings types. */ +import type { ExcerptSuggestionsSettings } from './excerpt-suggestions-settings'; import type { PerformanceStatsSettings, RelatedPostsSettings, @@ -14,6 +15,7 @@ import type { TopPostsSettings } from './top-posts-settings'; * Export the settings types. */ export type { + ExcerptSuggestionsSettings, PerformanceStatsSettings, // Part of SidebarSettings type. RelatedPostsSettings, // Part of SidebarSettings type. SidebarSettings, @@ -23,5 +25,5 @@ export type { }; // Generic type for settings. -export type Settings = SidebarSettings | TopPostsSettings; - +export type Settings = SidebarSettings | TopPostsSettings | + ExcerptSuggestionsSettings; diff --git a/src/content-helper/editor-sidebar/title-suggestions/title-suggestions.scss b/src/content-helper/editor-sidebar/title-suggestions/title-suggestions.scss index 17a5e7c94..62fe36553 100644 --- a/src/content-helper/editor-sidebar/title-suggestions/title-suggestions.scss +++ b/src/content-helper/editor-sidebar/title-suggestions/title-suggestions.scss @@ -55,36 +55,6 @@ } } - .wp-parsely-dropdown-label { - align-self: stretch; - color: var(--sidebar-black); - font-size: var(--font-size--smaller); - font-style: normal; - font-weight: 600; - line-height: var(--grid-unit-20); - text-transform: uppercase; - } - - // Accepted Title view. - // TODO: Remove, unused? - .parsely-write-titles-accepted-title-container { - .parsely-write-titles-accepted-title { - font-weight: 600; - font-size: to_rem(16px); - line-height: to_rem(20px); - margin: 0 0 to_rem(15px) 0; - text-align: center; - } - - // Accepted Title actions. - .parsely-write-titles-accepted-title-actions { - margin: to_rem(10px) 0; - justify-content: center; - display: flex; - gap: to_rem(10px); - } - } - .wp-parsely-title-suggestion { display: flex; flex-direction: column; diff --git a/src/content-helper/excerpt-generator/components/excerpt-panel-settings.tsx b/src/content-helper/excerpt-generator/components/excerpt-panel-settings.tsx new file mode 100644 index 000000000..aee2eeb05 --- /dev/null +++ b/src/content-helper/excerpt-generator/components/excerpt-panel-settings.tsx @@ -0,0 +1,82 @@ +/** + * Internal dependencies + */ +import { Telemetry } from '../../../js/telemetry/telemetry'; +import { + getPersonaLabel, + PersonaProp, + PersonaSelector, +} from '../../common/components/persona-selector'; +import { + getToneLabel, + ToneProp, + ToneSelector, +} from '../../common/components/tone-selector'; +import { + ExcerptSuggestionsSettings as Settings, +} from '../../common/settings'; + +/** + * Props for the Excerpt Suggestions Settings component. + * + * @since 3.17.0 + */ +type ExcerptSuggestionsSettingsProps = { + isLoading?: boolean, + onPersonaChange: ( persona: PersonaProp | string ) => void, + onSettingChange: ( + key: keyof Settings, + value: string|boolean + ) => void, + onToneChange: ( tone: ToneProp | string ) => void, + persona: PersonaProp, + tone: ToneProp, +}; + +/** + * Component that renders the settings for Excerpt Suggestions. + * + * @since 3.17.0 + * + * @param {ExcerptSuggestionsSettingsProps} props The component's props. + */ +export const ExcerptSuggestionsSettings = ( { + isLoading, + onPersonaChange, + onToneChange, + persona, + tone, +}: Readonly ): React.JSX.Element => { + return ( +
+ { + onToneChange( selectedTone ); + } } + onDropdownChange={ ( selectedTone ) => { + Telemetry.trackEvent( 'excerpt_generator_ai_tone_changed', + { selectedTone } + ); + } } + disabled={ isLoading } + allowCustom + /> + { + onPersonaChange( selectedPersona ); + } } + onDropdownChange={ ( selectedPersona ) => { + Telemetry.trackEvent( 'excerpt_generator_ai_persona_changed', + { persona: selectedPersona } + ); + } } + disabled={ isLoading } + allowCustom + /> +
+ ); +}; diff --git a/src/content-helper/excerpt-generator/components/excerpt-panel.tsx b/src/content-helper/excerpt-generator/components/excerpt-panel.tsx index efa459b35..3c90314ba 100644 --- a/src/content-helper/excerpt-generator/components/excerpt-panel.tsx +++ b/src/content-helper/excerpt-generator/components/excerpt-panel.tsx @@ -9,21 +9,31 @@ import { TextareaControl, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; -import { PostTypeSupportCheck, store as editorStore } from '@wordpress/editor'; -import { PluginDocumentSettingPanel } from '../../../@types/gutenberg/wrapper'; +import { store as editorStore, PostTypeSupportCheck } from '@wordpress/editor'; import { useEffect, useState } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; +import { external } from '@wordpress/icons'; import { count } from '@wordpress/wordcount'; +import { PluginDocumentSettingPanel } from '../../../@types/gutenberg/wrapper'; +import { PersonaProp } from '../../common/components/persona-selector'; +import { ToneProp } from '../../common/components/tone-selector'; /** * Internal dependencies */ -import { external } from '@wordpress/icons'; import { GutenbergFunction } from '../../../@types/gutenberg/types'; import { Telemetry } from '../../../js/telemetry/telemetry'; -import { ContentHelperError, ContentHelperErrorCode } from '../../common/content-helper-error'; +import { + ContentHelperError, + ContentHelperErrorCode, +} from '../../common/content-helper-error'; import { LeafIcon } from '../../common/icons/leaf-icon'; +import { + ExcerptSuggestionsSettings as Settings, + useSettings, +} from '../../common/settings'; import { ExcerptGeneratorProvider } from '../provider'; +import { ExcerptSuggestionsSettings } from './excerpt-panel-settings'; /** * Defines the structure of an object that holds excerpt data. @@ -43,19 +53,30 @@ interface ExcerptData { * @since 3.13.0 */ const PostExcerptGenerator = () => { - const [ isLoading, setLoading ] = useState( false ); + const { settings, setSettings } = useSettings(); + const [ error, setError ] = useState(); - const [ onChangeFired, setOnChangeFired ] = useState( false ); - const [ wordCountString, setWordCountString ] = useState( '' ); const [ excerptData, setExcerptData ] = useState( { currentExcerpt: '', isUnderReview: false, newExcerptGeneratedCount: 0, oldExcerpt: '', } ); + const [ isLoading, setLoading ] = useState( false ); + const [ onChangeFired, setOnChangeFired ] = useState( false ); + const [ persona, setPersona ] = useState( settings.Persona ); + const [ tone, setTone ] = useState( settings.Tone ); + const [ wordCountString, setWordCountString ] = useState( '' ); const { editPost } = useDispatch( editorStore ); + const onSettingChange = ( key: keyof Settings, value: string | boolean ) => { + setSettings( { + ...settings, + [ key ]: value, + } ); + }; + // Get the current excerpt, post content, and post title. const { excerpt, postContent, postTitle } = useSelect( ( select ) => { const { getEditedPostAttribute, getEditedPostContent } = select( editorStore ) as GutenbergFunction; @@ -123,10 +144,10 @@ const PostExcerptGenerator = () => { try { Telemetry.trackEvent( 'excerpt_generator_pressed' ); - const requestedExcerpt = await ExcerptGeneratorProvider.getInstance().generateExcerpt( - postTitle, - postContent - ); + const requestedExcerpt = await ExcerptGeneratorProvider + .getInstance() + .generateExcerpt( postTitle, postContent, persona, tone ); + setExcerptData( { currentExcerpt: requestedExcerpt, isUnderReview: true, @@ -184,6 +205,15 @@ const PostExcerptGenerator = () => { return excerpt; }; + const generateWithParselyHeader = +
+ +
+ { __( 'Generate With Parse.ly', 'wp-parsely' ) } + { __( 'Beta', 'wp-parsely' ) } +
+
; + return (
@@ -234,13 +264,6 @@ const PostExcerptGenerator = () => { />
-
- -
- { __( 'Generate With Parse.ly', 'wp-parsely' ) } - { __( 'Beta', 'wp-parsely' ) } -
-
{ error && ( { { error.Message() } ) } -
- { excerptData.isUnderReview ? ( - <> + { excerptData.isUnderReview ? ( + <> + { generateWithParselyHeader } +
- - ) : ( -
+ + ) : ( + <> + { + onSettingChange( 'Persona', selectedPersona ); + setPersona( selectedPersona ); + } } + onSettingChange={ onSettingChange } + onToneChange={ ( selectedTone ) => { + onSettingChange( 'Tone', selectedTone ); + setTone( selectedTone ); + } } + persona={ settings.Persona } + tone={ settings.Tone } + /> + { generateWithParselyHeader } +
+ - ) } -
+ } + +
+ + ) }
@@ -376,7 +380,14 @@ export const ExcerptPanel = () => { name="parsely-post-excerpt" title={ __( 'Excerpt', 'wp-parsely' ) } > - + + + ); diff --git a/src/content-helper/excerpt-generator/excerpt-generator.scss b/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.scss similarity index 96% rename from src/content-helper/excerpt-generator/excerpt-generator.scss rename to src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.scss index 5baec8f24..3233f857c 100644 --- a/src/content-helper/excerpt-generator/excerpt-generator.scss +++ b/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.scss @@ -1,5 +1,5 @@ -@import "../common/css/variables"; -@import "../common/css/functions"; +@import "../../common/css/variables"; +@import "../../common/css/functions"; .editor-post-excerpt__loading_animation { position: absolute; diff --git a/src/content-helper/excerpt-generator/excerpt-generator.tsx b/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.tsx similarity index 55% rename from src/content-helper/excerpt-generator/excerpt-generator.tsx rename to src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.tsx index 2dbd549fa..f4a13c7e0 100644 --- a/src/content-helper/excerpt-generator/excerpt-generator.tsx +++ b/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.tsx @@ -8,58 +8,15 @@ import { registerPlugin } from '@wordpress/plugins'; /** * Internal dependencies */ -import { dispatchCoreEditPost } from '../../@types/gutenberg/types'; -import { - ExcerptSuggestionsSettings, - SettingsProvider, -} from '../common/settings'; -import { ExcerptPanel } from './components/excerpt-panel'; +import { dispatchCoreEditPost } from '../../../@types/gutenberg/types'; +import { SettingsProvider } from '../../common/settings'; +import { ExcerptPanel } from './component-panel'; +import { getSettingsFromJson } from '../editor-sidebar'; +import './excerpt-generator.scss'; // TODO: Get the plugin ID from the editor sidebar file. const PARSELY_SIDEBAR_PLUGIN_ID = 'wp-parsely-block-editor-sidebar'; -/** - * Gets the settings from the passed JSON. - * - * If missing settings or invalid values are detected, they get set to their - * defaults. - * - * @since 3.17.0 - * - * @param {string} settingsJson The JSON containing the settings. - * - * @return {ExcerptSuggestionsSettings} The resulting settings object. - */ -const getSettingsFromJson = ( - settingsJson: string -): ExcerptSuggestionsSettings => { - let parsedSettings: ExcerptSuggestionsSettings; - - try { - parsedSettings = JSON.parse( settingsJson ); - } catch ( e ) { - // Return defaults when parsing failed or the string is empty. - return { - Open: false, - Persona: 'journalist', - Tone: 'neutral', - }; - } - - // Fix invalid values if any are found. - if ( typeof parsedSettings?.Open !== 'boolean' ) { - parsedSettings.Open = false; - } - if ( typeof parsedSettings?.Persona !== 'string' ) { - parsedSettings.Persona = 'journalist'; - } - if ( typeof parsedSettings?.Tone !== 'string' ) { - parsedSettings.Tone = 'neutral'; - } - - return parsedSettings; -}; - /** * The ExcerptGenerator function registers the custom excerpt panel and removes * the default excerpt panel. @@ -90,7 +47,7 @@ const ExcerptGenerator = ( settings: never, name: string ) => { registerPlugin( 'wp-parsely-excerpt-generator', { render: () => ( { return settings; }; -// Add the ExcerptGenerator function to the plugins.registerPlugin filter. -// Priority is set to 1000 to ensure that the function runs as late as possible. -addFilter( 'plugins.registerPlugin', 'wp-parsely-excerpt-generator', ExcerptGenerator, 1000 ); +export function initExcerptGenerator() { + // Add the ExcerptGenerator function to the plugins.registerPlugin filter. + // Priority is set to 1000 to ensure that the function runs as late as possible. + addFilter( 'plugins.registerPlugin', 'wp-parsely-excerpt-generator', ExcerptGenerator, 1000 ); +} diff --git a/src/content-helper/excerpt-generator/provider.ts b/src/content-helper/editor-sidebar/excerpt-generator/provider.ts similarity index 96% rename from src/content-helper/excerpt-generator/provider.ts rename to src/content-helper/editor-sidebar/excerpt-generator/provider.ts index 187e0bf7e..f10dc5dcf 100644 --- a/src/content-helper/excerpt-generator/provider.ts +++ b/src/content-helper/editor-sidebar/excerpt-generator/provider.ts @@ -6,7 +6,7 @@ import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies */ -import { BaseProvider } from '../common/base-provider'; +import { BaseProvider } from '../../common/base-provider'; /** * Provides the generate excerpt functionality to be used in other components. 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 850a76519..b405c83f3 100644 --- a/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php +++ b/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php @@ -51,11 +51,23 @@ protected function get_meta_key(): string { */ protected function get_subvalues_specs(): array { return array( - 'InitialTabName' => array( + 'ExcerptSuggestions' => array( + 'values' => array( + 'Open' => array( true, false ), + 'Persona' => array(), + 'Tone' => array(), + ), + 'default' => array( + 'Open' => false, + 'Persona' => 'journalist', + 'Tone' => 'neutral', + ), + ), + 'InitialTabName' => array( 'values' => array( 'tools', 'performance' ), 'default' => 'tools', ), - 'PerformanceStats' => array( + 'PerformanceStats' => array( 'values' => array( 'Period' => array( '10m', '1h', '2h', '4h', '24h', '7d', '30d' ), 'VisibleDataPoints' => array( 'views', 'visitors', 'avgEngaged', 'recirculation' ), @@ -67,7 +79,7 @@ protected function get_subvalues_specs(): array { 'VisiblePanels' => array( 'overview', 'categories', 'referrers' ), ), ), - 'RelatedPosts' => array( + 'RelatedPosts' => array( 'values' => array( 'FilterBy' => array( 'unavailable', 'tag', 'section', 'author' ), 'FilterValue' => array(), @@ -83,7 +95,7 @@ protected function get_subvalues_specs(): array { 'Period' => '7d', ), ), - 'SmartLinking' => array( + 'SmartLinking' => array( 'values' => array( 'MaxLinks' => array(), 'MaxLinkWords' => array(), @@ -95,7 +107,7 @@ protected function get_subvalues_specs(): array { 'Open' => false, ), ), - 'TitleSuggestions' => array( + 'TitleSuggestions' => array( 'values' => array( 'Open' => array( true, false ), 'Persona' => array(), diff --git a/src/rest-api/settings/class-settings-controller.php b/src/rest-api/settings/class-settings-controller.php index df55e1d19..930856a66 100644 --- a/src/rest-api/settings/class-settings-controller.php +++ b/src/rest-api/settings/class-settings-controller.php @@ -40,7 +40,6 @@ public function init(): void { $endpoints = array( new Endpoint_Dashboard_Widget_Settings( $this ), new Endpoint_Editor_Sidebar_Settings( $this ), - new Endpoint_Excerpt_Suggestions_Settings( $this ), ); $this->register_endpoints( $endpoints ); diff --git a/tests/Integration/ContentHelper/ContentHelperExcerptSuggestionsTest.php b/tests/Integration/ContentHelper/ContentHelperExcerptSuggestionsTest.php deleted file mode 100644 index e410ee818..000000000 --- a/tests/Integration/ContentHelper/ContentHelperExcerptSuggestionsTest.php +++ /dev/null @@ -1,84 +0,0 @@ - $additional_args Any required additional arguments. - */ - protected function assert_enqueued_status( - $global_filter_value, - $feature_filter_value, - bool $expected, - string $user_login, - string $user_role, - array $additional_args = array() - ): void { - parent::assert_enqueued_status_default( - new Excerpt_Generator( new Parsely() ), - $global_filter_value, - $feature_filter_value, - $expected, - $user_login, - $user_role - ); - } - - /** - * Verifies that by default, the run() method does not enqueue the assets - * when the current user isn't an administrator. - * - * @since 3.17.0 - * - * @covers \Parsely\Content_Helper\Content_Helper_Feature::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::run - * @covers \Parsely\Permissions::current_user_can_use_pch_feature - * @covers \Parsely\Permissions::get_user_roles_with_edit_posts_cap - * @uses \Parsely\Content_Helper\Content_Helper_Feature::get_global_filter_name - * @uses \Parsely\Content_Helper\Excerpt_Generator::__construct - * @uses \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @uses \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @uses \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @uses \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @uses \Parsely\Parsely::__construct - * @uses \Parsely\Parsely::allow_parsely_remote_requests - * @uses \Parsely\Parsely::are_credentials_managed - * @uses \Parsely\Parsely::get_managed_credentials - * @uses \Parsely\Parsely::get_options - * @uses \Parsely\Parsely::set_default_full_metadata_in_non_posts - * @uses \Parsely\Parsely::set_default_track_as_values - * @uses \Parsely\Parsely::set_managed_options - */ - public function test_assets_do_not_get_enqueued_by_default_for_non_admin_users(): void { - $this->assert_enqueued_status( - null, - null, - false, - 'test_editor', - 'editor' - ); - } -} diff --git a/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php b/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php index c87f1e4c0..7bde554d2 100644 --- a/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php +++ b/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php @@ -60,26 +60,32 @@ public function get_endpoint(): \Parsely\REST_API\Base_Endpoint { * @return array The default value for the endpoint. */ public function get_default_value(): array { + // Note: Array keys should be sorted alphabetically. return array( - 'InitialTabName' => 'tools', - 'PerformanceStats' => array( + 'ExcerptSuggestions' => array( + 'Open' => false, + 'Persona' => 'journalist', + 'Tone' => 'neutral', + ), + 'InitialTabName' => 'tools', + 'PerformanceStats' => array( 'Period' => '7d', 'VisibleDataPoints' => array( 'views', 'visitors', 'avgEngaged', 'recirculation' ), 'VisiblePanels' => array( 'overview', 'categories', 'referrers' ), ), - 'RelatedPosts' => array( + 'RelatedPosts' => array( 'FilterBy' => 'unavailable', 'FilterValue' => '', 'Metric' => 'views', 'Open' => false, 'Period' => '7d', ), - 'SmartLinking' => array( + 'SmartLinking' => array( 'MaxLinks' => 10, 'MaxLinkWords' => 4, 'Open' => false, ), - 'TitleSuggestions' => array( + 'TitleSuggestions' => array( 'Open' => false, 'Persona' => 'journalist', 'Tone' => 'neutral', diff --git a/webpack.config.js b/webpack.config.js index 1ef8ba9db..bf2bdd9fd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -21,10 +21,6 @@ module.exports = { path.resolve( __dirname, 'src', 'content-helper', 'post-list-stats', 'post-list-stats' ), path.resolve( __dirname, 'src', 'content-helper', 'post-list-stats', 'post-list-stats.scss' ), ], - 'content-helper/excerpt-generator': [ - path.resolve( __dirname, 'src', 'content-helper', 'excerpt-generator', 'excerpt-generator' ), - path.resolve( __dirname, 'src', 'content-helper', 'excerpt-generator', 'excerpt-generator.scss' ), - ], loader: [ path.resolve( __dirname, 'src', 'js', 'lib', 'loader' ), path.resolve( __dirname, 'src', 'js', 'lib', 'uuid-profile-call' ), diff --git a/wp-parsely.php b/wp-parsely.php index f1db9e67c..4cb3da398 100644 --- a/wp-parsely.php +++ b/wp-parsely.php @@ -168,18 +168,6 @@ function parsely_content_helper_editor_sidebar_features(): void { } } -// The priority of 9 is used to ensure that the Excerpt Generator is loaded before the PCH Editor Sidebar (10). -add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\\init_content_helper_excerpt_generator', 9 ); -/** - * Initializes and inserts the PCH Excerpt Generator. - * - * @since 3.13.0 - */ -function init_content_helper_excerpt_generator(): void { - ( new Excerpt_Generator( $GLOBALS['parsely'] ) )->run(); -} - - add_action( 'widgets_init', __NAMESPACE__ . '\\parsely_recommended_widget_register' ); /** * Registers the Parse.ly Recommended widget. From 03c5a4d0777a5c79ff5d9be08088da62caad5d6a Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Tue, 24 Sep 2024 13:04:13 +0100 Subject: [PATCH 05/15] Rename front-end component to Excerpt Suggestions --- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.js | 2 +- src/UI/class-settings-page.php | 4 +- .../editor-sidebar/class-editor-sidebar.php | 2 +- .../editor-sidebar/editor-sidebar.tsx | 8 +- .../class-excerpt-suggestions.php} | 4 +- .../component-panel-settings.tsx | 0 .../component-panel.tsx | 12 +- .../excerpt-suggestions.scss} | 0 .../excerpt-suggestions.tsx} | 14 +- .../provider.ts | 12 +- .../ContentHelperFeatureTest.php | 168 +++++++++--------- wp-parsely.php | 2 +- 13 files changed, 115 insertions(+), 115 deletions(-) rename src/content-helper/editor-sidebar/{excerpt-generator/class-excerpt-generator.php => excerpt-suggestions/class-excerpt-suggestions.php} (93%) rename src/content-helper/editor-sidebar/{excerpt-generator => excerpt-suggestions}/component-panel-settings.tsx (100%) rename src/content-helper/editor-sidebar/{excerpt-generator => excerpt-suggestions}/component-panel.tsx (96%) rename src/content-helper/editor-sidebar/{excerpt-generator/excerpt-generator.scss => excerpt-suggestions/excerpt-suggestions.scss} (100%) rename src/content-helper/editor-sidebar/{excerpt-generator/excerpt-generator.tsx => excerpt-suggestions/excerpt-suggestions.tsx} (81%) rename src/content-helper/editor-sidebar/{excerpt-generator => excerpt-suggestions}/provider.ts (77%) diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 21a56e7bc..8f8915222 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '1d9d5ab77ff12295ea21'); + 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '726d86e0f9227dd23c13'); diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index 5f7a45364..fb5e17630 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -1,7 +1,7 @@ !function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),L=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"})]})},E=function(){return E=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. -(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(L,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:E||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t||((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-generator",{render:function(){return(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Le,{})})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt")),e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-generator",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t||((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Le,{})})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt")),e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Lt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Et=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Et,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Lt,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,L(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,E(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ (0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=E||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-smart-linking-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ (0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:E,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(E?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:E,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(E?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(E?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ diff --git a/src/UI/class-settings-page.php b/src/UI/class-settings-page.php index a901ace8d..766568de1 100644 --- a/src/UI/class-settings-page.php +++ b/src/UI/class-settings-page.php @@ -10,7 +10,7 @@ namespace Parsely\UI; -use Parsely\Content_Helper\Excerpt_Generator; +use Parsely\Content_Helper\Excerpt_Suggestions; use Parsely\Parsely; use Parsely\Permissions; use Parsely\Utils\Utils; @@ -496,7 +496,7 @@ private function initialize_content_helper_section(): void { 'option_key' => $field_id, 'label_for' => $field_id, 'legend' => __( 'Excerpt Suggestions', 'wp-parsely' ), - 'filter' => Excerpt_Generator::get_feature_filter_name(), + 'filter' => Excerpt_Suggestions::get_feature_filter_name(), ); add_settings_field( $field_id, diff --git a/src/content-helper/editor-sidebar/class-editor-sidebar.php b/src/content-helper/editor-sidebar/class-editor-sidebar.php index 9b46dcf07..6de4c3c6a 100644 --- a/src/content-helper/editor-sidebar/class-editor-sidebar.php +++ b/src/content-helper/editor-sidebar/class-editor-sidebar.php @@ -49,7 +49,7 @@ public function __construct( Parsely $parsely ) { // Instantiate the features. $this->features = array( 'Smart_Linking' => new Smart_Linking( $this ), - 'Excerpt_Generator' => new Excerpt_Generator( $this->parsely ), + 'Excerpt_Generator' => new Excerpt_Suggestions( $this->parsely ), ); } diff --git a/src/content-helper/editor-sidebar/editor-sidebar.tsx b/src/content-helper/editor-sidebar/editor-sidebar.tsx index c6c3d3c3c..df39707db 100644 --- a/src/content-helper/editor-sidebar/editor-sidebar.tsx +++ b/src/content-helper/editor-sidebar/editor-sidebar.tsx @@ -31,7 +31,7 @@ import { isInEnum, } from '../common/utils/constants'; import { getContentHelperPermissions } from '../common/utils/permissions'; -import { initExcerptGenerator } from './excerpt-generator/excerpt-generator'; +import { initExcerptSuggestions } from './excerpt-suggestions/excerpt-suggestions'; import { DEFAULT_MAX_LINKS, initSmartLinking, @@ -280,9 +280,9 @@ const ContentHelperEditorSidebar = (): React.JSX.Element => { ); }; -// Initialize Excerpt Generator. -if ( initExcerptGenerator ) { - initExcerptGenerator(); +// Initialize Excerpt Suggestions. +if ( initExcerptSuggestions ) { + initExcerptSuggestions(); } // Registering Plugin to WordPress Block Editor. diff --git a/src/content-helper/editor-sidebar/excerpt-generator/class-excerpt-generator.php b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php similarity index 93% rename from src/content-helper/editor-sidebar/excerpt-generator/class-excerpt-generator.php rename to src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php index b0c022cc1..ce2360cdb 100644 --- a/src/content-helper/editor-sidebar/excerpt-generator/class-excerpt-generator.php +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php @@ -21,7 +21,7 @@ * * @since 3.13.0 */ -class Excerpt_Generator extends Content_Helper_Feature { +class Excerpt_Suggestions extends Content_Helper_Feature { /** * Constructor. @@ -42,7 +42,7 @@ public function __construct( Parsely $parsely ) { * @return string The filter name. */ public static function get_feature_filter_name(): string { - return self::get_global_filter_name() . '_excerpt_generator'; + return self::get_global_filter_name() . '_excerpt_suggestions'; } /** * Returns the feature's script ID. diff --git a/src/content-helper/editor-sidebar/excerpt-generator/component-panel-settings.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel-settings.tsx similarity index 100% rename from src/content-helper/editor-sidebar/excerpt-generator/component-panel-settings.tsx rename to src/content-helper/editor-sidebar/excerpt-suggestions/component-panel-settings.tsx diff --git a/src/content-helper/editor-sidebar/excerpt-generator/component-panel.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx similarity index 96% rename from src/content-helper/editor-sidebar/excerpt-generator/component-panel.tsx rename to src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx index ac6b22492..a9602fdb2 100644 --- a/src/content-helper/editor-sidebar/excerpt-generator/component-panel.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx @@ -35,7 +35,7 @@ import { useSettings, } from '../../common/settings'; import { getSettingsFromJson } from '../editor-sidebar'; -import { ExcerptGeneratorProvider } from './provider'; +import { ExcerptSuggestionsProvider } from './provider'; import { ExcerptSuggestionsSettings } from './component-panel-settings'; /** @@ -51,11 +51,11 @@ interface ExcerptData { } /** - * The PostExcerptGenerator component displays the excerpt textarea and the Parse.ly AI controls. + * The PostExcerptSuggestions component displays the excerpt textarea and the Parse.ly AI controls. * * @since 3.13.0 */ -const PostExcerptGenerator = () => { +const PostExcerptSuggestions = () => { const { settings, setSettings } = useSettings(); const [ error, setError ] = useState(); @@ -148,7 +148,7 @@ const PostExcerptGenerator = () => { try { Telemetry.trackEvent( 'excerpt_generator_pressed' ); - const requestedExcerpt = await ExcerptGeneratorProvider + const requestedExcerpt = await ExcerptSuggestionsProvider .getInstance() .generateExcerpt( postTitle, postContent, persona, tone ); @@ -369,7 +369,7 @@ const LoadingAnimation = (): React.JSX.Element => { /** * The ExcerptPanel component verifies that the current post type supports excerpts, - * and then renders the PostExcerptGenerator component. + * and then renders the PostExcerptSuggestions component. * * @since 3.13.0 */ @@ -386,7 +386,7 @@ export const ExcerptPanel = () => { window.wpParselyContentHelperSettings ) } > - +
diff --git a/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.scss b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.scss similarity index 100% rename from src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.scss rename to src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.scss diff --git a/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx similarity index 81% rename from src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.tsx rename to src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx index f4a13c7e0..ae42918c8 100644 --- a/src/content-helper/editor-sidebar/excerpt-generator/excerpt-generator.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx @@ -12,13 +12,13 @@ import { dispatchCoreEditPost } from '../../../@types/gutenberg/types'; import { SettingsProvider } from '../../common/settings'; import { ExcerptPanel } from './component-panel'; import { getSettingsFromJson } from '../editor-sidebar'; -import './excerpt-generator.scss'; +import './excerpt-suggestions.scss'; // TODO: Get the plugin ID from the editor sidebar file. const PARSELY_SIDEBAR_PLUGIN_ID = 'wp-parsely-block-editor-sidebar'; /** - * The ExcerptGenerator function registers the custom excerpt panel and removes + * The ExcerptSuggestions function registers the custom excerpt panel and removes * the default excerpt panel. * * @since 3.13.0 @@ -26,7 +26,7 @@ const PARSELY_SIDEBAR_PLUGIN_ID = 'wp-parsely-block-editor-sidebar'; * @param {never} settings Settings from the plugins.registerPlugin filter. Not used. * @param {string} name The plugin name. */ -const ExcerptGenerator = ( settings: never, name: string ) => { +const ExcerptSuggestions = ( settings: never, name: string ) => { if ( name !== PARSELY_SIDEBAR_PLUGIN_ID ) { return settings; } @@ -44,7 +44,7 @@ const ExcerptGenerator = ( settings: never, name: string ) => { } // Register the custom excerpt panel. - registerPlugin( 'wp-parsely-excerpt-generator', { + registerPlugin( 'wp-parsely-excerpt-suggestions', { render: () => ( { return settings; }; -export function initExcerptGenerator() { - // Add the ExcerptGenerator function to the plugins.registerPlugin filter. +export function initExcerptSuggestions() { + // Add the ExcerptSuggestions function to the plugins.registerPlugin filter. // Priority is set to 1000 to ensure that the function runs as late as possible. - addFilter( 'plugins.registerPlugin', 'wp-parsely-excerpt-generator', ExcerptGenerator, 1000 ); + addFilter( 'plugins.registerPlugin', 'wp-parsely-excerpt-suggestions', ExcerptSuggestions, 1000 ); } diff --git a/src/content-helper/editor-sidebar/excerpt-generator/provider.ts b/src/content-helper/editor-sidebar/excerpt-suggestions/provider.ts similarity index 77% rename from src/content-helper/editor-sidebar/excerpt-generator/provider.ts rename to src/content-helper/editor-sidebar/excerpt-suggestions/provider.ts index f10dc5dcf..29b50d808 100644 --- a/src/content-helper/editor-sidebar/excerpt-generator/provider.ts +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/provider.ts @@ -13,24 +13,24 @@ import { BaseProvider } from '../../common/base-provider'; * * @since 3.13.0 */ -export class ExcerptGeneratorProvider extends BaseProvider { +export class ExcerptSuggestionsProvider extends BaseProvider { /** - * The singleton instance of the ExcerptGeneratorProvider. + * The singleton instance of the ExcerptSuggestionsProvider. * * @since 3.16.0 */ - private static instance: ExcerptGeneratorProvider; + private static instance: ExcerptSuggestionsProvider; /** * Returns the singleton instance of the TitleSuggestionsProvider. * * @since 3.16.0 * - * @return {ExcerptGeneratorProvider} The singleton instance. + * @return {ExcerptSuggestionsProvider} The singleton instance. */ - public static getInstance(): ExcerptGeneratorProvider { + public static getInstance(): ExcerptSuggestionsProvider { if ( ! this.instance ) { - this.instance = new ExcerptGeneratorProvider(); + this.instance = new ExcerptSuggestionsProvider(); } return this.instance; diff --git a/tests/Integration/ContentHelper/ContentHelperFeatureTest.php b/tests/Integration/ContentHelper/ContentHelperFeatureTest.php index 45f4700c5..4a5b2174d 100644 --- a/tests/Integration/ContentHelper/ContentHelperFeatureTest.php +++ b/tests/Integration/ContentHelper/ContentHelperFeatureTest.php @@ -154,12 +154,12 @@ protected static function deregister_feature_assets_and_run( * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles @@ -210,12 +210,12 @@ public function test_assets_get_enqueued_by_default(): void { * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles @@ -266,12 +266,12 @@ public function test_assets_get_enqueued_when_global_filter_is_true(): void { * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -310,12 +310,12 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_false(): v * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -355,12 +355,12 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_invalid(): * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles @@ -411,12 +411,12 @@ public function test_assets_get_enqueued_when_feature_filter_is_true(): void { * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -455,12 +455,12 @@ public function test_assets_do_not_get_enqueued_when_feature_filter_is_false(): * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -499,12 +499,12 @@ public function test_assets_do_not_get_enqueued_when_feature_filter_is_invalid() * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles @@ -555,12 +555,12 @@ public function test_assets_get_enqueued_when_both_filters_are_true(): void { * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles @@ -606,12 +606,12 @@ public function test_assets_do_not_get_enqueued_when_both_filters_are_false(): v * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -650,12 +650,12 @@ public function test_assets_do_not_get_enqueued_when_both_filters_are_invalid(): * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -694,12 +694,12 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_true_and_f * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles @@ -751,12 +751,12 @@ public function test_assets_get_enqueued_when_global_filter_is_false_and_feature * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::get_feature_filter_name * @covers \Parsely\Content_Helper\Post_List_Stats::run @@ -795,12 +795,12 @@ public function test_assets_do_not_get_enqueued_when_global_filter_is_true_and_f * @covers \Parsely\Content_Helper\Editor_Sidebar::get_script_id * @covers \Parsely\Content_Helper\Editor_Sidebar::get_style_id * @covers \Parsely\Content_Helper\Editor_Sidebar::run - * @covers \Parsely\Content_Helper\Excerpt_Generator::__construct - * @covers \Parsely\Content_Helper\Excerpt_Generator::can_enable_feature - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_feature_filter_name - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_script_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::get_style_id - * @covers \Parsely\Content_Helper\Excerpt_Generator::run + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::__construct + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::can_enable_feature + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_feature_filter_name + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_script_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::get_style_id + * @covers \Parsely\Content_Helper\Excerpt_Suggestions::run * @covers \Parsely\Content_Helper\Post_List_Stats::__construct * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_script_with_data * @covers \Parsely\Content_Helper\Post_List_Stats::enqueue_parsely_stats_styles diff --git a/wp-parsely.php b/wp-parsely.php index 4cb3da398..4c301a742 100644 --- a/wp-parsely.php +++ b/wp-parsely.php @@ -28,7 +28,7 @@ use Parsely\Content_Helper\Dashboard_Widget; use Parsely\Content_Helper\Editor_Sidebar; -use Parsely\Content_Helper\Excerpt_Generator; +use Parsely\Content_Helper\Excerpt_Suggestions; use Parsely\Content_Helper\Post_List_Stats; use Parsely\Endpoints\GraphQL_Metadata; use Parsely\Endpoints\Rest_Metadata; From b2fe524c89da12cb13bc5338de3d0b45f6b1469c Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Tue, 24 Sep 2024 13:21:00 +0100 Subject: [PATCH 06/15] Clean-up --- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.js | 2 +- .../excerpt-suggestions/excerpt-suggestions.tsx | 11 +---------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 8f8915222..953fe7af0 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '726d86e0f9227dd23c13'); + 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'db69c114d741ca9a2460'); diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index fb5e17630..45c7cc6df 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -1,7 +1,7 @@ !function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),L=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"})]})},E=function(){return E=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. -(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(L,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:E||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t||((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Le,{})})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt")),e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t||((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Le,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt")),e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Lt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Et=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Et,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Lt,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,L(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,E(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ (0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=E||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-smart-linking-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ (0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:E,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(E?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:E,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(E?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(E?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx index ae42918c8..da7790eca 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx @@ -9,9 +9,7 @@ import { registerPlugin } from '@wordpress/plugins'; * Internal dependencies */ import { dispatchCoreEditPost } from '../../../@types/gutenberg/types'; -import { SettingsProvider } from '../../common/settings'; import { ExcerptPanel } from './component-panel'; -import { getSettingsFromJson } from '../editor-sidebar'; import './excerpt-suggestions.scss'; // TODO: Get the plugin ID from the editor sidebar file. @@ -46,14 +44,7 @@ const ExcerptSuggestions = ( settings: never, name: string ) => { // Register the custom excerpt panel. registerPlugin( 'wp-parsely-excerpt-suggestions', { render: () => ( - - - + ), } ); From 99be0e9883811803e7959c4af6c11065a01b0b21 Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Tue, 24 Sep 2024 14:25:48 +0100 Subject: [PATCH 07/15] Fix PCH permissions for Excerpt Suggestions --- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.js | 4 ++-- src/class-permissions.php | 5 +++-- src/content-helper/common/utils/permissions.ts | 2 ++ .../excerpt-suggestions/excerpt-suggestions.tsx | 7 +++++++ 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 953fe7af0..fce0af939 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'db69c114d741ca9a2460'); + 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '6cff2a59e0a708629834'); diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index 45c7cc6df..50701c66c 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -1,7 +1,7 @@ -!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),L=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"})]})},E=function(){return E=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( +!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),L=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"})]})},E=function(){return E=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. -(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(L,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:E||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t||((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Le,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt")),e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t?e:H().ExcerptSuggestions?((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Le,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt"),e):e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Lt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Et=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Et,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Lt,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,L(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,E(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ (0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=E||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-smart-linking-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ (0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:E,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(E?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:E,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(E?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(E?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ diff --git a/src/class-permissions.php b/src/class-permissions.php index fdb1c8b8c..8767f737a 100644 --- a/src/class-permissions.php +++ b/src/class-permissions.php @@ -154,8 +154,9 @@ public static function current_user_can_use_pch_feature( public static function get_pch_permissions_json( $pch_options ): string { $permissions = array(); $features = array( - 'SmartLinking' => 'smart_linking', - 'TitleSuggestions' => 'title_suggestions', + 'SmartLinking' => 'smart_linking', + 'TitleSuggestions' => 'title_suggestions', + 'ExcerptSuggestions' => 'excerpt_suggestions', ); foreach ( $features as $key => $value ) { diff --git a/src/content-helper/common/utils/permissions.ts b/src/content-helper/common/utils/permissions.ts index 541462987..1cfddbfc6 100644 --- a/src/content-helper/common/utils/permissions.ts +++ b/src/content-helper/common/utils/permissions.ts @@ -6,6 +6,7 @@ export interface ContentHelperPermissions { SmartLinking: boolean; TitleSuggestions: boolean; + ExcerptSuggestions: boolean; } /** @@ -19,6 +20,7 @@ export function getContentHelperPermissions(): ContentHelperPermissions { const defaultPermissions: ContentHelperPermissions = { SmartLinking: false, TitleSuggestions: false, + ExcerptSuggestions: false, }; try { diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx index da7790eca..5b323a364 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx @@ -9,6 +9,7 @@ import { registerPlugin } from '@wordpress/plugins'; * Internal dependencies */ import { dispatchCoreEditPost } from '../../../@types/gutenberg/types'; +import { getContentHelperPermissions } from '../../common/utils/permissions'; import { ExcerptPanel } from './component-panel'; import './excerpt-suggestions.scss'; @@ -29,6 +30,12 @@ const ExcerptSuggestions = ( settings: never, name: string ) => { return settings; } + // Check if the user has the necessary permissions to use the ExcerptSuggestions feature. + const permissions = getContentHelperPermissions(); + if ( ! permissions.ExcerptSuggestions ) { + return settings; + } + const isJetpackAiEnabled = window?.Jetpack_Editor_Initial_State?.available_blocks[ 'ai-content-lens' ]; From 7da5df225af6fdd904fe5880df51275aaacf7d63 Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Wed, 16 Oct 2024 12:54:27 +0100 Subject: [PATCH 08/15] Fix potential filter conflict with deprecated `wp_parsely_enable_content_helper_excerpt_generator` --- .../class-editor-sidebar-feature.php | 106 ++++++++++++++++++ .../editor-sidebar/class-editor-sidebar.php | 7 +- .../class-excerpt-suggestions.php | 99 ++++++++-------- .../smart-linking/class-smart-linking.php | 71 +++--------- 4 files changed, 177 insertions(+), 106 deletions(-) create mode 100644 src/content-helper/editor-sidebar/class-editor-sidebar-feature.php diff --git a/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php b/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php new file mode 100644 index 000000000..7c54b203c --- /dev/null +++ b/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php @@ -0,0 +1,106 @@ +parsely = $editor_sidebar->parsely; + } + + /** + * Returns whether the feature can be enabled for the current user. + * + * @since 3.16.0 + * @since 3.17.0 Moved to Editor_Sidebar_Feature class. + * + * @param bool ...$conditions Conditions that need to be met besides filters + * for the function to return true. + * @return bool Whether the feature can be enabled. + */ + protected function can_enable_feature( bool ...$conditions ): bool { + if ( ! parent::can_enable_feature( ...$conditions ) ) { + return false; + } + + return Permissions::current_user_can_use_pch_feature( + static::get_feature_name(), + $this->parsely->get_options()['content_helper'], + get_the_ID() + ); + } + + + /** + * Returns the feature's filter name. The feature filter controls the + * enabled/disabled state of a particular Content Helper feature. + * + * Not in use for Editor Sidebar features. + * + * @since 3.16.0 + * + * @return string The filter name. + */ + public static function get_feature_filter_name(): string { + return ''; // Not in use for this feature. + } + + + /** + * Returns the feature's script ID. + * + * Not in use for Editor Sidebar features. + * + * @since 3.17.0 + * + * @return string The script ID. + */ + public static function get_script_id(): string { + return ''; + } + + /** + * Returns the feature's style ID. + * + * Not in use for Editor Sidebar features. + * + * @since 3.17.0 + * + * @return string The style ID. + */ + public static function get_style_id(): string { + return ''; + } +} diff --git a/src/content-helper/editor-sidebar/class-editor-sidebar.php b/src/content-helper/editor-sidebar/class-editor-sidebar.php index 6de4c3c6a..f9b9f556a 100644 --- a/src/content-helper/editor-sidebar/class-editor-sidebar.php +++ b/src/content-helper/editor-sidebar/class-editor-sidebar.php @@ -10,6 +10,7 @@ namespace Parsely\Content_Helper; +use Parsely\Content_Helper\Editor_Sidebar\Editor_Sidebar_Feature; use Parsely\Content_Helper\Editor_Sidebar\Smart_Linking; use Parsely\Dashboard_Link; use Parsely\Parsely; @@ -32,7 +33,7 @@ class Editor_Sidebar extends Content_Helper_Feature { * * @since 3.16.0 * - * @var array + * @var array */ protected $features; @@ -49,7 +50,7 @@ public function __construct( Parsely $parsely ) { // Instantiate the features. $this->features = array( 'Smart_Linking' => new Smart_Linking( $this ), - 'Excerpt_Generator' => new Excerpt_Suggestions( $this->parsely ), + 'Excerpt_Generator' => new Excerpt_Suggestions( $this ), ); } @@ -133,7 +134,7 @@ public function init_features(): void { // Initialize the features. foreach ( $this->features as $feature ) { - $feature->run(); + $feature->run(); } } diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php index ce2360cdb..d222017a1 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php @@ -10,60 +10,90 @@ namespace Parsely\Content_Helper; -use Parsely\Parsely; -use Parsely\Permissions; - -use Parsely\Utils\Utils; -use const Parsely\PARSELY_FILE; +use Parsely\Content_Helper\Editor_Sidebar\Editor_Sidebar_Feature; /** * Content Helper: Excerpt Generator feature class * * @since 3.13.0 + * @since 3.17.0 Renamed to Excerpt Suggestions and converted to an Editor Sidebar feature. */ -class Excerpt_Suggestions extends Content_Helper_Feature { - +class Excerpt_Suggestions extends Editor_Sidebar_Feature { /** - * Constructor. + * Returns the feature's name. * - * @since 3.13.0 + * @since 3.17.0 * - * @param Parsely $parsely Instance of Parsely class. + * @return string */ - public function __construct( Parsely $parsely ) { - $this->parsely = $parsely; + public static function get_feature_name(): string { + return 'excerpt_suggestions'; } /** * Returns the feature's filter name. * - * @since 3.13.0 + * This is deprecated in favor of the new wp_parsely_current_user_can_use_pch_feature filter. + * + * @since 3.17.0 * * @return string The filter name. */ public static function get_feature_filter_name(): string { - return self::get_global_filter_name() . '_excerpt_suggestions'; + return self::get_global_filter_name() . '_excerpt_generator'; } + /** - * Returns the feature's script ID. + * Constructor. * - * @since 3.16.0 + * @since 3.17.0 * - * @return string The script ID. + * @param Editor_Sidebar $editor_sidebar Instance of Editor_Sidebar class. */ - public static function get_script_id(): string { - return ''; // Not in use for this feature. + public function __construct( Editor_Sidebar $editor_sidebar ) { + parent::__construct( $editor_sidebar ); + + // Check if the feature is disabled using the global and feature filters. + if ( has_filter( self::get_feature_filter_name() ) ) { + add_filter( + 'wp_parsely_current_user_can_use_pch_feature', + array( $this, 'callback_disable_feature_via_filters' ), + 10, + 2 + ); + } } /** - * Returns the feature's style ID. + * Checks and disables the feature if it is disabled via the global or feature filters. + * + * This throws a deprecated notice if the feature filter name is in use. * - * @since 3.16.0 + * @since 3.17.0 * - * @return string The style ID. + * @param ?bool $current_user_can_use_pch_feature Whether the current user can use the feature. + * @param string $feature_name The feature's name. + * @return ?bool Returns false if the feature is disabled via filters. */ - public static function get_style_id(): string { - return ''; // Not in use for this feature. + public function callback_disable_feature_via_filters( + ?bool $current_user_can_use_pch_feature, + string $feature_name + ): ?bool { + if ( static::get_feature_name() === $feature_name ) { + // Check if the feature is disabled using the global and feature filters. + $feature_enabled_with_filter = apply_filters_deprecated( + self::get_feature_filter_name(), + array( true ), + '3.17.0', + 'wp_parsely_current_user_can_use_pch_feature' + ); + + // If the feature is disabled via the global or feature filters, return false. + if ( false === $feature_enabled_with_filter ) { + return false; + } + } + return $current_user_can_use_pch_feature; } /** @@ -74,25 +104,4 @@ public static function get_style_id(): string { public function run(): void { // Do nothing. } - - /** - * Returns whether the feature can be enabled for the current user. - * - * @since 3.16.0 - * - * @param bool ...$conditions Conditions that need to be met besides filters - * for the function to return true. - * @return bool Whether the feature can be enabled. - */ - protected function can_enable_feature( bool ...$conditions ): bool { - if ( ! parent::can_enable_feature( ...$conditions ) ) { - return false; - } - - return Permissions::current_user_can_use_pch_feature( - 'excerpt_suggestions', - $this->parsely->get_options()['content_helper'], - get_the_ID() - ); - } } diff --git a/src/content-helper/editor-sidebar/smart-linking/class-smart-linking.php b/src/content-helper/editor-sidebar/smart-linking/class-smart-linking.php index 75148140f..56546772a 100644 --- a/src/content-helper/editor-sidebar/smart-linking/class-smart-linking.php +++ b/src/content-helper/editor-sidebar/smart-linking/class-smart-linking.php @@ -20,7 +20,17 @@ * * @since 3.16.0 */ -class Smart_Linking extends Content_Helper_Feature { +class Smart_Linking extends Editor_Sidebar_Feature { + /** + * Returns the feature's name. + * + * @since 3.17.0 + * + * @return string + */ + public static function get_feature_name(): string { + return 'smart_linking'; + } /** * Allowed blocks for the Smart Linking feature. @@ -34,53 +44,19 @@ class Smart_Linking extends Content_Helper_Feature { ); /** - * Instance of Editor_Sidebar class. + * Constructor. * * @since 3.16.0 * * @param Editor_Sidebar $editor_sidebar Instance of Editor_Sidebar class. */ public function __construct( Editor_Sidebar $editor_sidebar ) { - $this->parsely = $editor_sidebar->parsely; + parent::__construct( $editor_sidebar ); add_action( 'delete_post', array( $this, 'purge_smart_links' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'add_inline_script' ) ); } - /** - * Returns the feature's filter name. The feature filter controls the - * enabled/disabled state of a particular Content Helper feature. - * - * @since 3.16.0 - * - * @return string The filter name. - */ - public static function get_feature_filter_name(): string { - return ''; // Not in use for this feature. - } - - /** - * Returns the feature's script ID. - * - * @since 3.16.0 - * - * @return string The script ID. - */ - public static function get_script_id(): string { - return ''; // Not in use for this feature. - } - - /** - * Returns the feature's style ID. - * - * @since 3.16.0 - * - * @return string The style ID. - */ - public static function get_style_id(): string { - return ''; // Not in use for this feature. - } - /** * Runs the feature's initialization process. * @@ -101,27 +77,6 @@ public function run(): void { $this->register_taxonomy( 'smart_link_destination', __( 'Smart Link Destination', 'wp-parsely' ) ); } - /** - * Returns whether the feature can be enabled for the current user. - * - * @since 3.16.0 - * - * @param bool ...$conditions Conditions that need to be met besides filters - * for the function to return true. - * @return bool Whether the feature can be enabled. - */ - protected function can_enable_feature( bool ...$conditions ): bool { - if ( ! parent::can_enable_feature( ...$conditions ) ) { - return false; - } - - return Permissions::current_user_can_use_pch_feature( - 'smart_linking', - $this->parsely->get_options()['content_helper'], - get_the_ID() - ); - } - /** * Registers the custom post type for the Smart Links. * From 47a30feb4dd5c5a46dd5e91371dc90564535fdd2 Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Wed, 16 Oct 2024 12:59:32 +0100 Subject: [PATCH 09/15] Minor doc fixes per code review suggestions. --- src/content-helper/common/settings/types/sidebar-settings.d.ts | 2 +- .../excerpt-suggestions/class-excerpt-suggestions.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content-helper/common/settings/types/sidebar-settings.d.ts b/src/content-helper/common/settings/types/sidebar-settings.d.ts index b86aa566b..53412f91e 100644 --- a/src/content-helper/common/settings/types/sidebar-settings.d.ts +++ b/src/content-helper/common/settings/types/sidebar-settings.d.ts @@ -61,7 +61,7 @@ export interface SmartLinkingSettings { } /** - * Defines the settings structure for the PostExcerptGenerator component. + * Defines the settings structure for the PostExcerptSuggestions component. * * @since 3.17.0 */ diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php index d222017a1..2aaa365a8 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php @@ -99,7 +99,7 @@ public function callback_disable_feature_via_filters( /** * Inserts Content Helper Excerpt Generator inline scripts. * - * @since 3.13.0 + * @since 3.17.0 */ public function run(): void { // Do nothing. From 123976150d4e66e4ee95135f70621a7485b17221 Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Thu, 17 Oct 2024 11:50:12 +0100 Subject: [PATCH 10/15] Apply code review feedback --- .../editor-sidebar/class-editor-sidebar-feature.php | 4 +--- src/content-helper/editor-sidebar/class-editor-sidebar.php | 2 +- .../excerpt-suggestions/class-excerpt-suggestions.php | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php b/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php index 7c54b203c..5f0188129 100644 --- a/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php +++ b/src/content-helper/editor-sidebar/class-editor-sidebar-feature.php @@ -62,14 +62,13 @@ protected function can_enable_feature( bool ...$conditions ): bool { ); } - /** * Returns the feature's filter name. The feature filter controls the * enabled/disabled state of a particular Content Helper feature. * * Not in use for Editor Sidebar features. * - * @since 3.16.0 + * @since 3.17.0 * * @return string The filter name. */ @@ -77,7 +76,6 @@ public static function get_feature_filter_name(): string { return ''; // Not in use for this feature. } - /** * Returns the feature's script ID. * diff --git a/src/content-helper/editor-sidebar/class-editor-sidebar.php b/src/content-helper/editor-sidebar/class-editor-sidebar.php index f9b9f556a..630830bf4 100644 --- a/src/content-helper/editor-sidebar/class-editor-sidebar.php +++ b/src/content-helper/editor-sidebar/class-editor-sidebar.php @@ -134,7 +134,7 @@ public function init_features(): void { // Initialize the features. foreach ( $this->features as $feature ) { - $feature->run(); + $feature->run(); } } diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php index 2aaa365a8..c98cfae54 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php @@ -57,7 +57,7 @@ public function __construct( Editor_Sidebar $editor_sidebar ) { if ( has_filter( self::get_feature_filter_name() ) ) { add_filter( 'wp_parsely_current_user_can_use_pch_feature', - array( $this, 'callback_disable_feature_via_filters' ), + array( $this, 'callback_is_feature_enabled' ), 10, 2 ); @@ -75,7 +75,7 @@ public function __construct( Editor_Sidebar $editor_sidebar ) { * @param string $feature_name The feature's name. * @return ?bool Returns false if the feature is disabled via filters. */ - public function callback_disable_feature_via_filters( + public function callback_is_feature_enabled( ?bool $current_user_can_use_pch_feature, string $feature_name ): ?bool { @@ -93,6 +93,7 @@ public function callback_disable_feature_via_filters( return false; } } + return $current_user_can_use_pch_feature; } From 490bb4098edab60881720a5318133784958b9cfe Mon Sep 17 00:00:00 2001 From: Alex Cicovic <23142906+acicovic@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:13:54 +0300 Subject: [PATCH 11/15] Rebuild assets --- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index fce0af939..4fdd5fdda 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '6cff2a59e0a708629834'); + 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'dd5c16c4c1421deb60d2'); diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index 50701c66c..8e3c0aef5 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -3,7 +3,7 @@ // Translators: %1$s the number of words in the excerpt. (0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(L,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:E||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t?e:H().ExcerptSuggestions?((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Le,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt"),e):e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Lt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Et=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Et,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Lt,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,L(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,E(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ -(0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=E||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-smart-linking-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ +(0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=E||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/smart-linking/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ (0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:E,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(E?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:E,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(E?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(E?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ (0,x.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,x._n)("attempt","attempts",r.numRetries,"wp-parsely"))),console.error(r),[4,$(o)];case 9:return c.sent(),o.createErrorSnackbar(),[3,15];case 10:return[4,q(!1)];case 11:return c.sent(),[4,ne(t)];case 12:return c.sent(),[4,ie(!1)];case 13:return c.sent(),[4,me(E?"all":null==fe?void 0:fe.clientId)];case 14:return c.sent(),clearTimeout(e),[7];case 15:return[2]}var u}))}))},variant:"primary",isBusy:T,disabled:T,children:B?(0,x.sprintf)(/* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ /* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ (0,x.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,x.__)("Generating Smart Links…","wp-parsely"):(0,x.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,f.jsx)("div",{className:"smart-linking-manage",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t;return Mt(this,(function(n){switch(n.label){case 0:return[4,Je()];case 1:return e=n.sent(),t=Ze(),[4,Z(t)];case 2:return n.sent(),ce(!0),P.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,x.__)("Review Smart Links","wp-parsely")})})]}),L&&(0,f.jsx)(It,{isOpen:L,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){b(!0),ce(!1)}})]})},Gt=function(){return Gt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");et(t,e)}))})))},Xt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M7 11.5h10V13H7z"})}),en=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),tn=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,o=void 0===i?2:i,s=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,f.jsxs)("div",{className:"performance-stat-panel",children:[(0,f.jsxs)(h.__experimentalHStack,{className:"panel-header level-"+o,children:[(0,f.jsx)(h.__experimentalHeading,{level:o,children:t}),r&&!c&&(0,f.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,f.jsx)(h.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,f.jsx)("div",{className:"panel-body",children:u?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):s})]})};function nn(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,o=r.toString(),s="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,o=i.toFixed(u),s=l}a=c})),o+n+s}var rn=function(e){var t=e.data,n=e.isLoading,r=(0,_.useState)(w.Views),i=r[0],o=r[1],s=(0,_.useState)(!1),a=s[0],l=s[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,x.__)("Social","wp-parsely");case"search":return(0,x.__)("Search","wp-parsely");case"other":return(0,x.__)("Other","wp-parsely");case"internal":return(0,x.__)("Internal","wp-parsely");case"direct":return(0,x.__)("Direct","wp-parsely")}return e},u=(0,x.sprintf)((0,x.__)("By %s","wp-parsely"),G(i)); @@ -28,4 +28,4 @@ message:(0,x.sprintf)((0,x.__)('by author "%1$s"',"wp-parsely"),n.value)};throw (0,x.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),R.value,V(r,!0)):null!=E?E:""})}),j&&j.Message(),y&&(0,f.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,x.__)("Loading…","wp-parsely")}),!y&&!j&&0===A.length&&(0,f.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,x.__)("No related posts found.","wp-parsely")}),!y&&A.length>0&&(0,f.jsx)("div",{className:"related-posts-list",children:A.map((function(e){return(0,f.jsx)(zn,{metric:i,post:e,postContent:H},e.id)}))})]})]})]})},er=(0,f.jsx)(k.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(k.Path,{d:"M10.97 10.159a3.382 3.382 0 0 0-2.857.955l1.724 1.723-2.836 2.913L7 17h1.25l2.913-2.837 1.723 1.723a3.38 3.38 0 0 0 .606-.825c.33-.63.446-1.343.35-2.032L17 10.695 13.305 7l-2.334 3.159Z"})}),tr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M18.3 11.7c-.6-.6-1.4-.9-2.3-.9H6.7l2.9-3.3-1.1-1-4.5 5L8.5 16l1-1-2.7-2.7H16c.5 0 .9.2 1.3.5 1 1 1 3.4 1 4.5v.3h1.5v-.2c0-1.5 0-4.3-1.5-5.7z"})}),nr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 5.5A2.25 2.25 0 0 0 9.878 7h4.244A2.251 2.251 0 0 0 12 5.5ZM12 4a3.751 3.751 0 0 0-3.675 3H5v1.5h1.27l.818 8.997a2.75 2.75 0 0 0 2.739 2.501h4.347a2.75 2.75 0 0 0 2.738-2.5L17.73 8.5H19V7h-3.325A3.751 3.751 0 0 0 12 4Zm4.224 4.5H7.776l.806 8.861a1.25 1.25 0 0 0 1.245 1.137h4.347a1.25 1.25 0 0 0 1.245-1.137l.805-8.861Z"})}),rr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"m21.5 9.1-6.6-6.6-4.2 5.6c-1.2-.1-2.4.1-3.6.7-.1 0-.1.1-.2.1-.5.3-.9.6-1.2.9l3.7 3.7-5.7 5.7v1.1h1.1l5.7-5.7 3.7 3.7c.4-.4.7-.8.9-1.2.1-.1.1-.2.2-.3.6-1.1.8-2.4.6-3.6l5.6-4.1zm-7.3 3.5.1.9c.1.9 0 1.8-.4 2.6l-6-6c.8-.4 1.7-.5 2.6-.4l.9.1L15 4.9 19.1 9l-4.9 3.6z"})}),ir=function(){return ir=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]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]0?(0,f.jsx)("span",{className:"parsely-write-titles-text",children:(0,_.createInterpolateElement)( // translators: %1$s is the tone, %2$s is the persona. // translators: %1$s is the tone, %2$s is the persona. -(0,x.__)("We've generated a few titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,f.jsx)("strong",{children:me(a)}),persona:(0,f.jsx)("strong",{children:de(u)})})}):(0,x.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-title-suggestions-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,f.jsx)(pr,{title:k,type:Hn.PostTitle,isOriginal:!0}),00&&(0,f.jsx)(dr,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,f.jsx)(hr,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,f.jsx)(fr,{isLoading:g,onPersonaChange:function(e){N("Persona",e),p(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,f.jsx)("div",{className:"title-suggestions-generate",children:(0,f.jsxs)(h.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return mr(void 0,void 0,void 0,(function(){return wr(this,(function(e){switch(e.label){case 0:return o(void 0),!1!==g?[3,2]:(P.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=Hn.PostTitle,n=A,r=a,i=u,mr(void 0,void 0,void 0,(function(){var e,s,a;return wr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=gr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=l.sent(),[4,j(t,s)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),o(a),j(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,x.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,x.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,x.__)("Generate Titles","wp-parsely")]})})]})})},_r=function(){return _r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,f.jsx)("strong",{children:me(a)}),persona:(0,f.jsx)("strong",{children:de(u)})})}):(0,x.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,f.jsx)(pr,{title:k,type:Hn.PostTitle,isOriginal:!0}),00&&(0,f.jsx)(dr,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,f.jsx)(hr,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,f.jsx)(fr,{isLoading:g,onPersonaChange:function(e){N("Persona",e),p(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,f.jsx)("div",{className:"title-suggestions-generate",children:(0,f.jsxs)(h.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return mr(void 0,void 0,void 0,(function(){return wr(this,(function(e){switch(e.label){case 0:return o(void 0),!1!==g?[3,2]:(P.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=Hn.PostTitle,n=A,r=a,i=u,mr(void 0,void 0,void 0,(function(){var e,s,a;return wr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=gr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=l.sent(),[4,j(t,s)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),o(a),j(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,x.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,x.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,x.__)("Generate Titles","wp-parsely")]})})]})})},_r=function(){return _r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n Date: Fri, 25 Oct 2024 14:02:05 +0100 Subject: [PATCH 12/15] Improve documentation per code review suggestions --- .../excerpt-suggestions/class-excerpt-suggestions.php | 5 ++++- .../excerpt-suggestions/component-panel.tsx | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php index c98cfae54..015420197 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/class-excerpt-suggestions.php @@ -65,7 +65,10 @@ public function __construct( Editor_Sidebar $editor_sidebar ) { } /** - * Checks and disables the feature if it is disabled via the global or feature filters. + * Checks if the feature is disabled via the global or feature filters. + * + * If the feature is disabled via the global or feature filters, return false, + * thereby disabling the feature. * * This throws a deprecated notice if the feature filter name is in use. * diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx index a9602fdb2..73bd81c59 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx @@ -73,6 +73,15 @@ const PostExcerptSuggestions = () => { const { editPost } = useDispatch( editorStore ); + /** + * Handles changes to the excerpt suggestions settings. + * + * @since 3.17.0 + * + * @param {keyof ExcerptSuggestionsSettingsType} key The setting key that changed. + * + * @param {string|boolean} value The new value of the setting. + */ const onSettingChange = ( key: keyof ExcerptSuggestionsSettingsType, value: string | boolean ) => { setSettings( { ExcerptSuggestions: { From 9a02115571b8ad75756f9eb4136be3f37d4a1162 Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Fri, 25 Oct 2024 14:10:36 +0100 Subject: [PATCH 13/15] Add Excerpt Suggestions settings validation per code review suggestion --- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.js | 24 +++++++++---------- .../editor-sidebar/editor-sidebar.tsx | 12 ++++++++++ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 4fdd5fdda..efa377dbd 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'dd5c16c4c1421deb60d2'); + 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'b538347639826e62caaf'); diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index 8e3c0aef5..9ec473307 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"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),L=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"})]})},E=function(){return E=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( +!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),E=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"})]})},L=function(){return L=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. -(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(L,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:E||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Le=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Ee=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t?e:H().ExcerptSuggestions?((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Le,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt"),e):e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Ee,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Lt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Et=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Et,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Lt,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,E(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,L(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,E(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ -(0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=E||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!L,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/smart-linking/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ -(0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:E,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(E?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:E,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(E?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(E?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ -(0,x.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,x._n)("attempt","attempts",r.numRetries,"wp-parsely"))),console.error(r),[4,$(o)];case 9:return c.sent(),o.createErrorSnackbar(),[3,15];case 10:return[4,q(!1)];case 11:return c.sent(),[4,ne(t)];case 12:return c.sent(),[4,ie(!1)];case 13:return c.sent(),[4,me(E?"all":null==fe?void 0:fe.clientId)];case 14:return c.sent(),clearTimeout(e),[7];case 15:return[2]}var u}))}))},variant:"primary",isBusy:T,disabled:T,children:B?(0,x.sprintf)(/* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ /* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ -(0,x.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,x.__)("Generating Smart Links…","wp-parsely"):(0,x.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,f.jsx)("div",{className:"smart-linking-manage",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t;return Mt(this,(function(n){switch(n.label){case 0:return[4,Je()];case 1:return e=n.sent(),t=Ze(),[4,Z(t)];case 2:return n.sent(),ce(!0),P.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,x.__)("Review Smart Links","wp-parsely")})})]}),L&&(0,f.jsx)(It,{isOpen:L,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){b(!0),ce(!1)}})]})},Gt=function(){return Gt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");et(t,e)}))})))},Xt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M7 11.5h10V13H7z"})}),en=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),tn=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,o=void 0===i?2:i,s=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,f.jsxs)("div",{className:"performance-stat-panel",children:[(0,f.jsxs)(h.__experimentalHStack,{className:"panel-header level-"+o,children:[(0,f.jsx)(h.__experimentalHeading,{level:o,children:t}),r&&!c&&(0,f.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,f.jsx)(h.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,f.jsx)("div",{className:"panel-body",children:u?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):s})]})};function nn(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,o=r.toString(),s="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,o=i.toFixed(u),s=l}a=c})),o+n+s}var rn=function(e){var t=e.data,n=e.isLoading,r=(0,_.useState)(w.Views),i=r[0],o=r[1],s=(0,_.useState)(!1),a=s[0],l=s[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,x.__)("Social","wp-parsely");case"search":return(0,x.__)("Search","wp-parsely");case"other":return(0,x.__)("Other","wp-parsely");case"internal":return(0,x.__)("Internal","wp-parsely");case"direct":return(0,x.__)("Direct","wp-parsely")}return e},u=(0,x.sprintf)((0,x.__)("By %s","wp-parsely"),G(i)); +(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(E,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:L||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Ee=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Le=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t?e:H().ExcerptSuggestions?((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Ee,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt"),e):e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Le,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Et=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Lt=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Lt,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Et,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,L(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,E(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,L(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ +(0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=L||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!E,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/smart-linking/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ +(0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:L,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(L?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:L,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(L?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(L?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ +(0,x.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,x._n)("attempt","attempts",r.numRetries,"wp-parsely"))),console.error(r),[4,$(o)];case 9:return c.sent(),o.createErrorSnackbar(),[3,15];case 10:return[4,q(!1)];case 11:return c.sent(),[4,ne(t)];case 12:return c.sent(),[4,ie(!1)];case 13:return c.sent(),[4,me(L?"all":null==fe?void 0:fe.clientId)];case 14:return c.sent(),clearTimeout(e),[7];case 15:return[2]}var u}))}))},variant:"primary",isBusy:T,disabled:T,children:B?(0,x.sprintf)(/* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ /* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ +(0,x.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,x.__)("Generating Smart Links…","wp-parsely"):(0,x.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,f.jsx)("div",{className:"smart-linking-manage",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t;return Mt(this,(function(n){switch(n.label){case 0:return[4,Je()];case 1:return e=n.sent(),t=Ze(),[4,Z(t)];case 2:return n.sent(),ce(!0),P.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,x.__)("Review Smart Links","wp-parsely")})})]}),E&&(0,f.jsx)(It,{isOpen:E,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){b(!0),ce(!1)}})]})},Gt=function(){return Gt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");et(t,e)}))})))},Xt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M7 11.5h10V13H7z"})}),en=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),tn=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,o=void 0===i?2:i,s=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,f.jsxs)("div",{className:"performance-stat-panel",children:[(0,f.jsxs)(h.__experimentalHStack,{className:"panel-header level-"+o,children:[(0,f.jsx)(h.__experimentalHeading,{level:o,children:t}),r&&!c&&(0,f.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,f.jsx)(h.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,f.jsx)("div",{className:"panel-body",children:u?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):s})]})};function nn(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,o=r.toString(),s="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,o=i.toFixed(u),s=l}a=c})),o+n+s}var rn=function(e){var t=e.data,n=e.isLoading,r=(0,_.useState)(w.Views),i=r[0],o=r[1],s=(0,_.useState)(!1),a=s[0],l=s[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,x.__)("Social","wp-parsely");case"search":return(0,x.__)("Search","wp-parsely");case"other":return(0,x.__)("Other","wp-parsely");case"internal":return(0,x.__)("Internal","wp-parsely");case"direct":return(0,x.__)("Direct","wp-parsely")}return e},u=(0,x.sprintf)((0,x.__)("By %s","wp-parsely"),G(i)); /* translators: %s: metric description */return(0,f.jsxs)(tn,{title:(0,x.__)("Categories","wp-parsely"),level:3,subtitle:u,isOpen:a,onClick:function(){return l(!a)},children:[a&&(0,f.jsx)("div",{className:"panel-settings",children:(0,f.jsx)(h.SelectControl,{value:i,prefix:(0,x.__)("By:","wp-parsely"),onChange:function(e){F(e,w)&&o(e)},children:Object.values(w).map((function(e){return(0,f.jsxs)("option",{value:e,disabled:"avg_engaged"===e,children:[G(e),"avg_engaged"===e&&" "+(0,x.__)("(coming soon)","wp-parsely")]},e)}))})}),n?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):(0,f.jsxs)("div",{children:[(0,f.jsx)("div",{className:"multi-percentage-bar",children:Object.entries(t.referrers.types).map((function(e){var t=e[0],n=e[1],r=(0,x.sprintf)(/* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ /* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ (0,x.__)("%1$s: %2$s%%","wp-parsely"),c(t),n.viewsPercentage);return(0,f.jsx)(h.Tooltip /* translators: %s: percentage value */,{ /* translators: %s: percentage value */ -text:"".concat(c(t)," - ").concat((0,x.sprintf)((0,x.__)("%s%%","wp-parsely"),n.viewsPercentage)),delay:150,children:(0,f.jsx)("div",{"aria-label":r,className:"bar-fill "+t,style:{width:n.viewsPercentage+"%"}})},t)}))}),(0,f.jsx)("div",{className:"percentage-bar-labels",children:Object.entries(t.referrers.types).map((function(e){var t=e[0],n=e[1];return(0,f.jsxs)("div",{className:"single-label "+t,children:[(0,f.jsx)("div",{className:"label-color "+t}),(0,f.jsx)("div",{className:"label-text",children:c(t)}),(0,f.jsx)("div",{className:"label-value",children:nn(n.views)})]},t)}))})]})]})},on=(0,f.jsx)(k.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(k.Path,{d:"M3.99961 13C4.67043 13.3354 4.6703 13.3357 4.67017 13.3359L4.67298 13.3305C4.67621 13.3242 4.68184 13.3135 4.68988 13.2985C4.70595 13.2686 4.7316 13.2218 4.76695 13.1608C4.8377 13.0385 4.94692 12.8592 5.09541 12.6419C5.39312 12.2062 5.84436 11.624 6.45435 11.0431C7.67308 9.88241 9.49719 8.75 11.9996 8.75C14.502 8.75 16.3261 9.88241 17.5449 11.0431C18.1549 11.624 18.6061 12.2062 18.9038 12.6419C19.0523 12.8592 19.1615 13.0385 19.2323 13.1608C19.2676 13.2218 19.2933 13.2686 19.3093 13.2985C19.3174 13.3135 19.323 13.3242 19.3262 13.3305L19.3291 13.3359C19.3289 13.3357 19.3288 13.3354 19.9996 13C20.6704 12.6646 20.6703 12.6643 20.6701 12.664L20.6697 12.6632L20.6688 12.6614L20.6662 12.6563L20.6583 12.6408C20.6517 12.6282 20.6427 12.6108 20.631 12.5892C20.6078 12.5459 20.5744 12.4852 20.5306 12.4096C20.4432 12.2584 20.3141 12.0471 20.1423 11.7956C19.7994 11.2938 19.2819 10.626 18.5794 9.9569C17.1731 8.61759 14.9972 7.25 11.9996 7.25C9.00203 7.25 6.82614 8.61759 5.41987 9.9569C4.71736 10.626 4.19984 11.2938 3.85694 11.7956C3.68511 12.0471 3.55605 12.2584 3.4686 12.4096C3.42484 12.4852 3.39142 12.5459 3.36818 12.5892C3.35656 12.6108 3.34748 12.6282 3.34092 12.6408L3.33297 12.6563L3.33041 12.6614L3.32948 12.6632L3.32911 12.664C3.32894 12.6643 3.32879 12.6646 3.99961 13ZM11.9996 16C13.9326 16 15.4996 14.433 15.4996 12.5C15.4996 10.567 13.9326 9 11.9996 9C10.0666 9 8.49961 10.567 8.49961 12.5C8.49961 14.433 10.0666 16 11.9996 16Z"})}),sn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})}),an=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 4V2.2L9 4.8l3 2.5V5.5c3.6 0 6.5 2.9 6.5 6.5 0 2.9-1.9 5.3-4.5 6.2v.2l-.1-.2c-.4.1-.7.2-1.1.2l.2 1.5c.3 0 .6-.1 1-.2 3.5-.9 6-4 6-7.7 0-4.4-3.6-8-8-8zm-7.9 7l1.5.2c.1-1.2.5-2.3 1.2-3.2l-1.1-.9C4.8 8.2 4.3 9.6 4.1 11zm1.5 1.8l-1.5.2c.1.7.3 1.4.5 2 .3.7.6 1.3 1 1.8l1.2-.8c-.3-.5-.6-1-.8-1.5s-.4-1.1-.4-1.7zm1.5 5.5c1.1.9 2.4 1.4 3.8 1.6l.2-1.5c-1.1-.1-2.2-.5-3.1-1.2l-.9 1.1z"})}),ln=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M11 13h2v-2h-2v2zm-6 0h2v-2H5v2zm12-2v2h2v-2h-2z"})}),cn=function(){return cn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]1?[2,Promise.reject(new te((0,x.sprintf)(/* translators: URL of the published post */ /* translators: URL of the published post */ -(0,x.__)("Multiple results were returned for the post %d by the Parse.ly API.","wp-parsely"),t),U.ParselyApiReturnedTooManyResults))]:[2,n[0]]}}))}))},t.prototype.fetchReferrerDataFromWpEndpoint=function(e,t,n){return xn(this,void 0,void 0,(function(){return kn(this,(function(r){switch(r.label){case 0:return[4,this.fetch({path:(0,ne.addQueryArgs)("/wp-parsely/v2/stats/post/".concat(t,"/referrers"),bn(bn({},mn(e)),{itm_source:this.itmSource,total_views:n}))})];case 1:return[2,r.sent()]}}))}))},t}(re),jn=function(){return jn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return t.sent(),[4,n(r-1)];case 2:return t.sent(),[3,4];case 3:a(e),i(!1),t.label=4;case 4:return[2]}}))}))})),[2]}))}))};return i(!0),n(1),function(){a(void 0)}}),[t]),(0,f.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,f.jsx)(tn,{title:(0,x.__)("Performance Stats","wp-parsely"),icon:en,dropdownChildren:function(e){var t=e.onClose;return(0,f.jsx)(Nn,{onClose:t})},children:(0,f.jsx)("div",{className:"panel-settings",children:(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:d.PerformanceStats.Period,prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Period:","wp-parsely")}),onChange:function(e){F(e,m)&&(v({PerformanceStats:jn(jn({},d.PerformanceStats),{Period:e})}),P.trackEvent("editor_sidebar_performance_period_changed",{period:e}))},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})})}),s?s.Message():(0,f.jsxs)(f.Fragment,{children:[Cn(d,"overview")&&(0,f.jsx)(gn,{data:c,isLoading:r}),Cn(d,"categories")&&(0,f.jsx)(rn,{data:c,isLoading:r}),Cn(d,"referrers")&&(0,f.jsx)(yn,{data:c,isLoading:r})]}),window.wpParselyPostUrl&&(0,f.jsx)(h.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){P.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,x.__)("View this in Parse.ly","wp-parsely")})]})},On=function(e){var t=e.period;return(0,f.jsx)(h.Panel,{children:(0,f.jsx)(Ie,{children:(0,f.jsx)(An,{period:t})})})},In=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Tag,label:(0,x.__)("Tag","wp-parsely")}),r.categories.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Section,label:(0,x.__)("Section","wp-parsely")}),r.authors.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Author,label:(0,x.__)("Author","wp-parsely")})]})})},Bn=function(e){var t=e.filter,n=e.label,r=e.postData,i=In(e,["filter","label","postData"]);return(0,f.jsx)("div",{className:"related-posts-filter-values",children:(0,f.jsx)(h.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return i.onFilterValueChange(e)},options:b.Tag===t.type?r.tags.map((function(e){return{value:e,label:e}})):b.Section===t.type?r.categories.map((function(e){return{value:e,label:e}})):b.Author===t.type?r.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},Mn=function(e){var t=e.filter,n=e.postData,r=e.label,i=In(e,["filter","postData","label"]),o=function(){return n.authors.length>0&&n.categories.length>0||n.authors.length>0&&n.tags.length>0||n.tags.length>0&&n.categories.length>0},s=function(){return b.Tag===t.type&&n.tags.length>1||b.Section===t.type&&n.categories.length>1||b.Author===t.type&&n.authors.length>1};return o()||s()?(0,f.jsxs)("div",{className:"related-posts-filter-settings",children:[o()&&(0,f.jsx)(Rn,{filter:t,label:r,onFilterTypeChange:i.onFilterTypeChange,postData:n}),s()&&(0,f.jsx)(Bn,{filter:t,label:o()?void 0:r,onFilterValueChange:i.onFilterValueChange,postData:n})]}):null},Dn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"})}),Fn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5.625 5.5h9.75c.069 0 .125.056.125.125v9.75a.125.125 0 0 1-.125.125h-9.75a.125.125 0 0 1-.125-.125v-9.75c0-.069.056-.125.125-.125ZM4 5.625C4 4.728 4.728 4 5.625 4h9.75C16.273 4 17 4.728 17 5.625v9.75c0 .898-.727 1.625-1.625 1.625h-9.75A1.625 1.625 0 0 1 4 15.375v-9.75Zm14.5 11.656v-9H20v9C20 18.8 18.77 20 17.251 20H6.25v-1.5h11.001c.69 0 1.249-.528 1.249-1.219Z"})}),Vn=function(){return(0,f.jsx)(h.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,f.jsx)(h.Rect,{width:"1",height:"40",fill:"#cccccc"})})};function Gn(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Number of Views","wp-parsely")}),i,nn(n.views.toString())]}):"avg_engaged"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,f.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var Hn,zn=function(e){var t,n,r=e.metric,i=e.post,o=e.postContent,s=(0,v.useDispatch)("core/notices").createNotice,a=o&&(t=o,n=Ae(i.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,f.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,f.jsx)("div",{className:"related-post-title",children:(0,f.jsxs)("a",{href:i.url,target:"_blank",rel:"noreferrer",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("View on website (opens new tab)","wp-parsely")}),i.title]})}),(0,f.jsx)("div",{className:"related-post-actions",children:(0,f.jsxs)("div",{className:"related-post-info",children:[(0,f.jsxs)("div",{children:[(0,f.jsx)("div",{className:"related-post-metric",children:(0,f.jsx)(Gn,{metric:r,post:i,viewsIcon:(0,f.jsx)(le,{icon:on}),avgEngagedIcon:(0,f.jsx)(h.Dashicon,{icon:"clock",size:24})})}),a&&(0,f.jsx)("div",{className:"related-post-linked",children:(0,f.jsx)(h.Tooltip,{text:(0,x.__)("This post is linked in the content","wp-parsely"),children:(0,f.jsx)(le,{icon:Dn,size:24})})})]}),(0,f.jsx)(Vn,{}),(0,f.jsxs)("div",{children:[(0,f.jsx)(h.Button,{icon:Fn,iconSize:24,onClick:function(){navigator.clipboard.writeText(i.rawUrl).then((function(){s("success",(0,x.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,x.__)("Copy URL to clipboard","wp-parsely")}),(0,f.jsx)(h.Button,{icon:(0,f.jsx)(L,{}),iconSize:18,href:i.dashUrl,target:"_blank",label:(0,x.__)("View in Parse.ly","wp-parsely")})]})]})})]})},Un=window.wp.coreData,qn=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)}}(),$n=function(){return $n=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return t.sent(),[4,n(r-1)];case 2:return t.sent(),[3,4];case 3:a(e),i(!1),t.label=4;case 4:return[2]}}))}))})),[2]}))}))};return i(!0),n(1),function(){a(void 0)}}),[t]),(0,f.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,f.jsx)(tn,{title:(0,x.__)("Performance Stats","wp-parsely"),icon:en,dropdownChildren:function(e){var t=e.onClose;return(0,f.jsx)(Nn,{onClose:t})},children:(0,f.jsx)("div",{className:"panel-settings",children:(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:d.PerformanceStats.Period,prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Period:","wp-parsely")}),onChange:function(e){F(e,m)&&(v({PerformanceStats:jn(jn({},d.PerformanceStats),{Period:e})}),P.trackEvent("editor_sidebar_performance_period_changed",{period:e}))},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})})}),s?s.Message():(0,f.jsxs)(f.Fragment,{children:[Cn(d,"overview")&&(0,f.jsx)(gn,{data:c,isLoading:r}),Cn(d,"categories")&&(0,f.jsx)(rn,{data:c,isLoading:r}),Cn(d,"referrers")&&(0,f.jsx)(yn,{data:c,isLoading:r})]}),window.wpParselyPostUrl&&(0,f.jsx)(h.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){P.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,x.__)("View this in Parse.ly","wp-parsely")})]})},On=function(e){var t=e.period;return(0,f.jsx)(h.Panel,{children:(0,f.jsx)(Ie,{children:(0,f.jsx)(An,{period:t})})})},In=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Tag,label:(0,x.__)("Tag","wp-parsely")}),r.categories.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Section,label:(0,x.__)("Section","wp-parsely")}),r.authors.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Author,label:(0,x.__)("Author","wp-parsely")})]})})},Bn=function(e){var t=e.filter,n=e.label,r=e.postData,i=In(e,["filter","label","postData"]);return(0,f.jsx)("div",{className:"related-posts-filter-values",children:(0,f.jsx)(h.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return i.onFilterValueChange(e)},options:b.Tag===t.type?r.tags.map((function(e){return{value:e,label:e}})):b.Section===t.type?r.categories.map((function(e){return{value:e,label:e}})):b.Author===t.type?r.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},Mn=function(e){var t=e.filter,n=e.postData,r=e.label,i=In(e,["filter","postData","label"]),o=function(){return n.authors.length>0&&n.categories.length>0||n.authors.length>0&&n.tags.length>0||n.tags.length>0&&n.categories.length>0},s=function(){return b.Tag===t.type&&n.tags.length>1||b.Section===t.type&&n.categories.length>1||b.Author===t.type&&n.authors.length>1};return o()||s()?(0,f.jsxs)("div",{className:"related-posts-filter-settings",children:[o()&&(0,f.jsx)(Rn,{filter:t,label:r,onFilterTypeChange:i.onFilterTypeChange,postData:n}),s()&&(0,f.jsx)(Bn,{filter:t,label:o()?void 0:r,onFilterValueChange:i.onFilterValueChange,postData:n})]}):null},Dn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"})}),Fn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5.625 5.5h9.75c.069 0 .125.056.125.125v9.75a.125.125 0 0 1-.125.125h-9.75a.125.125 0 0 1-.125-.125v-9.75c0-.069.056-.125.125-.125ZM4 5.625C4 4.728 4.728 4 5.625 4h9.75C16.273 4 17 4.728 17 5.625v9.75c0 .898-.727 1.625-1.625 1.625h-9.75A1.625 1.625 0 0 1 4 15.375v-9.75Zm14.5 11.656v-9H20v9C20 18.8 18.77 20 17.251 20H6.25v-1.5h11.001c.69 0 1.249-.528 1.249-1.219Z"})}),Vn=function(){return(0,f.jsx)(h.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,f.jsx)(h.Rect,{width:"1",height:"40",fill:"#cccccc"})})};function Gn(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Number of Views","wp-parsely")}),i,nn(n.views.toString())]}):"avg_engaged"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,f.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var Hn,zn=function(e){var t,n,r=e.metric,i=e.post,o=e.postContent,s=(0,v.useDispatch)("core/notices").createNotice,a=o&&(t=o,n=Ae(i.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,f.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,f.jsx)("div",{className:"related-post-title",children:(0,f.jsxs)("a",{href:i.url,target:"_blank",rel:"noreferrer",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("View on website (opens new tab)","wp-parsely")}),i.title]})}),(0,f.jsx)("div",{className:"related-post-actions",children:(0,f.jsxs)("div",{className:"related-post-info",children:[(0,f.jsxs)("div",{children:[(0,f.jsx)("div",{className:"related-post-metric",children:(0,f.jsx)(Gn,{metric:r,post:i,viewsIcon:(0,f.jsx)(le,{icon:on}),avgEngagedIcon:(0,f.jsx)(h.Dashicon,{icon:"clock",size:24})})}),a&&(0,f.jsx)("div",{className:"related-post-linked",children:(0,f.jsx)(h.Tooltip,{text:(0,x.__)("This post is linked in the content","wp-parsely"),children:(0,f.jsx)(le,{icon:Dn,size:24})})})]}),(0,f.jsx)(Vn,{}),(0,f.jsxs)("div",{children:[(0,f.jsx)(h.Button,{icon:Fn,iconSize:24,onClick:function(){navigator.clipboard.writeText(i.rawUrl).then((function(){s("success",(0,x.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,x.__)("Copy URL to clipboard","wp-parsely")}),(0,f.jsx)(h.Button,{icon:(0,f.jsx)(E,{}),iconSize:18,href:i.dashUrl,target:"_blank",label:(0,x.__)("View in Parse.ly","wp-parsely")})]})]})})]})},Un=window.wp.coreData,qn=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)}}(),$n=function(){return $n=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]0&&f.every(Number.isInteger)?null!==(n=l("taxonomy","category",{include:f,context:"view"}))&&void 0!==n?n:void 0:null,tagRecords:s=Array.isArray(h)&&h.length>0&&h.every(Number.isInteger)?null!==(r=l("taxonomy","post_tag",{include:h,context:"view"}))&&void 0!==r?r:void 0:null,isLoading:u("getEntityRecords",["root","user",{include:[d],context:"view"}])||u("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||u("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}]),hasResolved:(c("getEntityRecords",["root","user",{include:[d],context:"view"}])||null===i)&&(c("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||null===o)&&(c("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}])||null===s)}}),[]);return(0,_.useEffect)((function(){var e=r.authorRecords,t=r.categoryRecords,i=r.tagRecords,o=r.isLoading;r.hasResolved&&!o&&n({authors:e,categories:t,tags:i,isReady:!0})}),[r]),t}(),c=l.authors,u=l.categories,p=l.tags,d=l.isReady;(0,_.useEffect)((function(){if(d){var e=function(e){return function(e){return!(!Array.isArray(e)||0===e.length)&&e.every((function(e){return"name"in e&&"id"in e&&"slug"in e&&"description"in e&&"link"in e}))}(e)?e.map((function(e){return e.name})):[]};a({authors:e(c),categories:e(u),tags:e(p)})}}),[c,u,p,d]);var g=(0,_.useState)(!0),y=g[0],k=g[1],S=(0,_.useState)(),j=S[0],T=S[1],L=(0,_.useState)(),E=L[0],C=L[1],N=(0,_.useState)([]),A=N[0],O=N[1],I=(0,_.useState)({type:t.RelatedPosts.FilterBy,value:t.RelatedPosts.FilterValue}),R=I[0],B=I[1],D=(0,_.useState)(void 0),H=D[0],z=D[1],U=(0,se.useDebounce)(z,1e3);(0,v.useSelect)((function(e){if("undefined"==typeof jest){var t=e("core/editor").getEditedPostContent;U(t())}else U("Jest test is running")}),[U]);var q=function(e,r){n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{FilterBy:e,FilterValue:r})})};return(0,_.useEffect)((function(){var e,t,n=function(e){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(t){return Kn.getInstance().getRelatedPosts(r,i,R).then((function(e){O(e.posts),C(e.message),k(!1)})).catch((function(t){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(r){switch(r.label){case 0:return e>0&&t.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,n(e-1)];case 2:return r.sent(),[3,4];case 3:k(!1),T(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},o=b.Author===R.type,a=b.Tag===R.type,l=b.Section===R.type,c=b.Unavailable===R.type,u=0===s.authors.length,p=0===s.tags.length,d=0===s.categories.length,f=o&&!s.authors.includes(R.value),h=a&&!s.tags.includes(R.value),v=l&&!s.categories.includes(R.value);return k(!0),c||a&&p||l&&d||o&&u?Object.values(s).every((function(e){return 0===e.length}))||B((e="",t=b.Unavailable,s.tags.length>=1?(t=b.Tag,e=s.tags[0]):s.categories.length>=1?(t=b.Section,e=s.categories[0]):s.authors.length>=1&&(t=b.Author,e=s.authors[0]),{type:t,value:e})):h?B({type:b.Tag,value:s.tags[0]}):v?B({type:b.Section,value:s.categories[0]}):f?B({type:b.Author,value:s.authors[0]}):n(1),function(){k(!1),O([]),C(""),T(void 0)}}),[r,i,R,s]),0===s.authors.length&&0===s.categories.length&&0===s.tags.length&&d?(0,f.jsx)("div",{className:"wp-parsely-related-posts",children:(0,f.jsx)("div",{className:"related-posts-body",children:(0,x.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,f.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,f.jsx)("div",{className:"related-posts-description",children:(0,x.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,f.jsxs)("div",{className:"related-posts-body",children:[(0,f.jsxs)("div",{className:"related-posts-settings",children:[(0,f.jsx)(h.SelectControl,{size:"__unstable-large",onChange:function(e){var r;F(r=e,w)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Metric:r})}),P.trackEvent("related_posts_metric_changed",{metric:r}))},prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Metric:","wp-parsely")}),value:i,children:Object.values(w).map((function(e){return(0,f.jsx)("option",{value:e,children:G(e)},e)}))}),(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:r,prefix:(0,f.jsxs)(h.__experimentalInputControlPrefixWrapper,{children:[(0,x.__)("Period:","wp-parsely")," "]}),onChange:function(e){return function(e){F(e,m)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Period:e})}),P.trackEvent("related_posts_period_changed",{period:e}))}(e)},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})]}),(0,f.jsx)(Mn,{label:(0,x.__)("Filter by","wp-parsely"),filter:R,onFilterTypeChange:function(e){if(F(e,b)){var t="",n=e;b.Tag===n&&(t=s.tags[0]),b.Section===n&&(t=s.categories[0]),b.Author===n&&(t=s.authors[0]),""!==t&&(q(n,t),B({type:n,value:t}),P.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(q(R.type,e),B(Yn(Yn({},R),{value:e})))},postData:s}),(0,f.jsxs)("div",{className:"related-posts-wrapper",children:[(0,f.jsx)("div",{children:(0,f.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:b.Tag===R.type?(0,x.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ +message:(0,x.sprintf)((0,x.__)('by author "%1$s"',"wp-parsely"),n.value)};throw new te((0,x.__)("No valid filter type has been specified.","wp-parsely"),U.CannotFormulateApiQuery)},t}(re),Yn=function(){return Yn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&f.every(Number.isInteger)?null!==(n=l("taxonomy","category",{include:f,context:"view"}))&&void 0!==n?n:void 0:null,tagRecords:s=Array.isArray(h)&&h.length>0&&h.every(Number.isInteger)?null!==(r=l("taxonomy","post_tag",{include:h,context:"view"}))&&void 0!==r?r:void 0:null,isLoading:u("getEntityRecords",["root","user",{include:[d],context:"view"}])||u("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||u("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}]),hasResolved:(c("getEntityRecords",["root","user",{include:[d],context:"view"}])||null===i)&&(c("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||null===o)&&(c("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}])||null===s)}}),[]);return(0,_.useEffect)((function(){var e=r.authorRecords,t=r.categoryRecords,i=r.tagRecords,o=r.isLoading;r.hasResolved&&!o&&n({authors:e,categories:t,tags:i,isReady:!0})}),[r]),t}(),c=l.authors,u=l.categories,p=l.tags,d=l.isReady;(0,_.useEffect)((function(){if(d){var e=function(e){return function(e){return!(!Array.isArray(e)||0===e.length)&&e.every((function(e){return"name"in e&&"id"in e&&"slug"in e&&"description"in e&&"link"in e}))}(e)?e.map((function(e){return e.name})):[]};a({authors:e(c),categories:e(u),tags:e(p)})}}),[c,u,p,d]);var g=(0,_.useState)(!0),y=g[0],k=g[1],S=(0,_.useState)(),j=S[0],T=S[1],E=(0,_.useState)(),L=E[0],C=E[1],N=(0,_.useState)([]),A=N[0],O=N[1],I=(0,_.useState)({type:t.RelatedPosts.FilterBy,value:t.RelatedPosts.FilterValue}),R=I[0],B=I[1],D=(0,_.useState)(void 0),H=D[0],z=D[1],U=(0,se.useDebounce)(z,1e3);(0,v.useSelect)((function(e){if("undefined"==typeof jest){var t=e("core/editor").getEditedPostContent;U(t())}else U("Jest test is running")}),[U]);var q=function(e,r){n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{FilterBy:e,FilterValue:r})})};return(0,_.useEffect)((function(){var e,t,n=function(e){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(t){return Kn.getInstance().getRelatedPosts(r,i,R).then((function(e){O(e.posts),C(e.message),k(!1)})).catch((function(t){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(r){switch(r.label){case 0:return e>0&&t.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,n(e-1)];case 2:return r.sent(),[3,4];case 3:k(!1),T(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},o=b.Author===R.type,a=b.Tag===R.type,l=b.Section===R.type,c=b.Unavailable===R.type,u=0===s.authors.length,p=0===s.tags.length,d=0===s.categories.length,f=o&&!s.authors.includes(R.value),h=a&&!s.tags.includes(R.value),v=l&&!s.categories.includes(R.value);return k(!0),c||a&&p||l&&d||o&&u?Object.values(s).every((function(e){return 0===e.length}))||B((e="",t=b.Unavailable,s.tags.length>=1?(t=b.Tag,e=s.tags[0]):s.categories.length>=1?(t=b.Section,e=s.categories[0]):s.authors.length>=1&&(t=b.Author,e=s.authors[0]),{type:t,value:e})):h?B({type:b.Tag,value:s.tags[0]}):v?B({type:b.Section,value:s.categories[0]}):f?B({type:b.Author,value:s.authors[0]}):n(1),function(){k(!1),O([]),C(""),T(void 0)}}),[r,i,R,s]),0===s.authors.length&&0===s.categories.length&&0===s.tags.length&&d?(0,f.jsx)("div",{className:"wp-parsely-related-posts",children:(0,f.jsx)("div",{className:"related-posts-body",children:(0,x.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,f.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,f.jsx)("div",{className:"related-posts-description",children:(0,x.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,f.jsxs)("div",{className:"related-posts-body",children:[(0,f.jsxs)("div",{className:"related-posts-settings",children:[(0,f.jsx)(h.SelectControl,{size:"__unstable-large",onChange:function(e){var r;F(r=e,w)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Metric:r})}),P.trackEvent("related_posts_metric_changed",{metric:r}))},prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Metric:","wp-parsely")}),value:i,children:Object.values(w).map((function(e){return(0,f.jsx)("option",{value:e,children:G(e)},e)}))}),(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:r,prefix:(0,f.jsxs)(h.__experimentalInputControlPrefixWrapper,{children:[(0,x.__)("Period:","wp-parsely")," "]}),onChange:function(e){return function(e){F(e,m)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Period:e})}),P.trackEvent("related_posts_period_changed",{period:e}))}(e)},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})]}),(0,f.jsx)(Mn,{label:(0,x.__)("Filter by","wp-parsely"),filter:R,onFilterTypeChange:function(e){if(F(e,b)){var t="",n=e;b.Tag===n&&(t=s.tags[0]),b.Section===n&&(t=s.categories[0]),b.Author===n&&(t=s.authors[0]),""!==t&&(q(n,t),B({type:n,value:t}),P.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(q(R.type,e),B(Yn(Yn({},R),{value:e})))},postData:s}),(0,f.jsxs)("div",{className:"related-posts-wrapper",children:[(0,f.jsx)("div",{children:(0,f.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:b.Tag===R.type?(0,x.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ (0,x.__)("Top related posts with the “%1$s” tag in the %2$s.","wp-parsely"),R.value,V(r,!0)):b.Section===R.type?(0,x.sprintf)(/* translators: 1: section name, 2: period */ /* translators: 1: section name, 2: period */ (0,x.__)("Top related posts in the “%1$s” section in the %2$s.","wp-parsely"),R.value,V(r,!0)):b.Author===R.type?(0,x.sprintf)(/* translators: 1: author name, 2: period */ /* translators: 1: author name, 2: period */ -(0,x.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),R.value,V(r,!0)):null!=E?E:""})}),j&&j.Message(),y&&(0,f.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,x.__)("Loading…","wp-parsely")}),!y&&!j&&0===A.length&&(0,f.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,x.__)("No related posts found.","wp-parsely")}),!y&&A.length>0&&(0,f.jsx)("div",{className:"related-posts-list",children:A.map((function(e){return(0,f.jsx)(zn,{metric:i,post:e,postContent:H},e.id)}))})]})]})]})},er=(0,f.jsx)(k.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(k.Path,{d:"M10.97 10.159a3.382 3.382 0 0 0-2.857.955l1.724 1.723-2.836 2.913L7 17h1.25l2.913-2.837 1.723 1.723a3.38 3.38 0 0 0 .606-.825c.33-.63.446-1.343.35-2.032L17 10.695 13.305 7l-2.334 3.159Z"})}),tr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M18.3 11.7c-.6-.6-1.4-.9-2.3-.9H6.7l2.9-3.3-1.1-1-4.5 5L8.5 16l1-1-2.7-2.7H16c.5 0 .9.2 1.3.5 1 1 1 3.4 1 4.5v.3h1.5v-.2c0-1.5 0-4.3-1.5-5.7z"})}),nr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 5.5A2.25 2.25 0 0 0 9.878 7h4.244A2.251 2.251 0 0 0 12 5.5ZM12 4a3.751 3.751 0 0 0-3.675 3H5v1.5h1.27l.818 8.997a2.75 2.75 0 0 0 2.739 2.501h4.347a2.75 2.75 0 0 0 2.738-2.5L17.73 8.5H19V7h-3.325A3.751 3.751 0 0 0 12 4Zm4.224 4.5H7.776l.806 8.861a1.25 1.25 0 0 0 1.245 1.137h4.347a1.25 1.25 0 0 0 1.245-1.137l.805-8.861Z"})}),rr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"m21.5 9.1-6.6-6.6-4.2 5.6c-1.2-.1-2.4.1-3.6.7-.1 0-.1.1-.2.1-.5.3-.9.6-1.2.9l3.7 3.7-5.7 5.7v1.1h1.1l5.7-5.7 3.7 3.7c.4-.4.7-.8.9-1.2.1-.1.1-.2.2-.3.6-1.1.8-2.4.6-3.6l5.6-4.1zm-7.3 3.5.1.9c.1.9 0 1.8-.4 2.6l-6-6c.8-.4 1.7-.5 2.6-.4l.9.1L15 4.9 19.1 9l-4.9 3.6z"})}),ir=function(){return ir=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]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]0?(0,f.jsx)("span",{className:"parsely-write-titles-text",children:(0,_.createInterpolateElement)( +(0,x.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),R.value,V(r,!0)):null!=L?L:""})}),j&&j.Message(),y&&(0,f.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,x.__)("Loading…","wp-parsely")}),!y&&!j&&0===A.length&&(0,f.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,x.__)("No related posts found.","wp-parsely")}),!y&&A.length>0&&(0,f.jsx)("div",{className:"related-posts-list",children:A.map((function(e){return(0,f.jsx)(zn,{metric:i,post:e,postContent:H},e.id)}))})]})]})]})},er=(0,f.jsx)(k.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(k.Path,{d:"M10.97 10.159a3.382 3.382 0 0 0-2.857.955l1.724 1.723-2.836 2.913L7 17h1.25l2.913-2.837 1.723 1.723a3.38 3.38 0 0 0 .606-.825c.33-.63.446-1.343.35-2.032L17 10.695 13.305 7l-2.334 3.159Z"})}),tr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M18.3 11.7c-.6-.6-1.4-.9-2.3-.9H6.7l2.9-3.3-1.1-1-4.5 5L8.5 16l1-1-2.7-2.7H16c.5 0 .9.2 1.3.5 1 1 1 3.4 1 4.5v.3h1.5v-.2c0-1.5 0-4.3-1.5-5.7z"})}),nr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 5.5A2.25 2.25 0 0 0 9.878 7h4.244A2.251 2.251 0 0 0 12 5.5ZM12 4a3.751 3.751 0 0 0-3.675 3H5v1.5h1.27l.818 8.997a2.75 2.75 0 0 0 2.739 2.501h4.347a2.75 2.75 0 0 0 2.738-2.5L17.73 8.5H19V7h-3.325A3.751 3.751 0 0 0 12 4Zm4.224 4.5H7.776l.806 8.861a1.25 1.25 0 0 0 1.245 1.137h4.347a1.25 1.25 0 0 0 1.245-1.137l.805-8.861Z"})}),rr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"m21.5 9.1-6.6-6.6-4.2 5.6c-1.2-.1-2.4.1-3.6.7-.1 0-.1.1-.2.1-.5.3-.9.6-1.2.9l3.7 3.7-5.7 5.7v1.1h1.1l5.7-5.7 3.7 3.7c.4-.4.7-.8.9-1.2.1-.1.1-.2.2-.3.6-1.1.8-2.4.6-3.6l5.6-4.1zm-7.3 3.5.1.9c.1.9 0 1.8-.4 2.6l-6-6c.8-.4 1.7-.5 2.6-.4l.9.1L15 4.9 19.1 9l-4.9 3.6z"})}),ir=function(){return ir=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]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]0?(0,f.jsx)("span",{className:"parsely-write-titles-text",children:(0,_.createInterpolateElement)( // translators: %1$s is the tone, %2$s is the persona. // translators: %1$s is the tone, %2$s is the persona. -(0,x.__)("We've generated a few titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,f.jsx)("strong",{children:me(a)}),persona:(0,f.jsx)("strong",{children:de(u)})})}):(0,x.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,f.jsx)(pr,{title:k,type:Hn.PostTitle,isOriginal:!0}),00&&(0,f.jsx)(dr,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,f.jsx)(hr,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,f.jsx)(fr,{isLoading:g,onPersonaChange:function(e){N("Persona",e),p(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,f.jsx)("div",{className:"title-suggestions-generate",children:(0,f.jsxs)(h.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return mr(void 0,void 0,void 0,(function(){return wr(this,(function(e){switch(e.label){case 0:return o(void 0),!1!==g?[3,2]:(P.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=Hn.PostTitle,n=A,r=a,i=u,mr(void 0,void 0,void 0,(function(){var e,s,a;return wr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=gr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=l.sent(),[4,j(t,s)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),o(a),j(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,x.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,x.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,x.__)("Generate Titles","wp-parsely")]})})]})})},_r=function(){return _r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,f.jsx)("strong",{children:me(a)}),persona:(0,f.jsx)("strong",{children:de(u)})})}):(0,x.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,f.jsx)(pr,{title:k,type:Hn.PostTitle,isOriginal:!0}),00&&(0,f.jsx)(dr,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,f.jsx)(hr,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,f.jsx)(fr,{isLoading:g,onPersonaChange:function(e){N("Persona",e),p(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,f.jsx)("div",{className:"title-suggestions-generate",children:(0,f.jsxs)(h.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return mr(void 0,void 0,void 0,(function(){return wr(this,(function(e){switch(e.label){case 0:return o(void 0),!1!==g?[3,2]:(P.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=Hn.PostTitle,n=A,r=a,i=u,mr(void 0,void 0,void 0,(function(){var e,s,a;return wr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=gr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=l.sent(),[4,j(t,s)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),o(a),j(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,x.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,x.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,x.__)("Generate Titles","wp-parsely")]})})]})})},_r=function(){return _r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n Date: Fri, 25 Oct 2024 14:25:04 +0100 Subject: [PATCH 14/15] Remove empty line Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> --- .../editor-sidebar/excerpt-suggestions/component-panel.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx index 73bd81c59..9895d6b5b 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx @@ -79,7 +79,6 @@ const PostExcerptSuggestions = () => { * @since 3.17.0 * * @param {keyof ExcerptSuggestionsSettingsType} key The setting key that changed. - * * @param {string|boolean} value The new value of the setting. */ const onSettingChange = ( key: keyof ExcerptSuggestionsSettingsType, value: string | boolean ) => { From 4510ea3092ae6f75d7f419e8e495703b6741883d Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Fri, 25 Oct 2024 17:06:50 +0100 Subject: [PATCH 15/15] PCH Excerpt Suggestions: Add feature to the PCH sidebar (#2811) * Add new Rest API base classes * Implement the Content Helper API namespace * Add tests for the new REST API classes * Update UI providers to use the new API endpoints * Remove unused code and initializations * Fix sonarcloud issues * Refactor to avoid consts and use getters instead * Fix minor docblock issues per code review * Apply code review suggestions by @acicovic * Rename API parameter `content` to `text` * Add `stats` endpoint * Update the UI to use the new API endpoints * Delete the old endpoints * Add tests * Apply code review suggestions by @acicovic * Add `stats` endpoint * Update the UI to use the new API endpoints * Delete the old endpoints * Add tests * Fix E2E test * Add `settings` endpoints * Update UI to use the new settings API * Add tests * Remove old code * Improve comments and whitespace * class-base-endpoint.php: Fix incorrect whitespace * Endpoints/class-base-endpoint.php: Fix incorrect whitespace * Improve comments and whitespace * Improve comments and whitespace * PCH Excerpt Suggestions: Add persona and tone settings * Add SettingsProvider to the ExcerptGenerator component * Rename front-end component to Excerpt Suggestions * Clean-up * Fix PCH permissions for Excerpt Suggestions * Adds PCH panel for the Excerpt Suggestions feature * Apply code review suggestions * Add `rel="noopener"` to links in the Excerpt Panel * Update comments & rebuild assets * Export PARSELY_SIDEBAR_PLUGIN_ID and remove pending TODO * Fix minor merge issues & rebuild assets --------- Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> --- build/content-helper/editor-sidebar-rtl.css | 2 +- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.css | 2 +- build/content-helper/editor-sidebar.js | 22 +-- .../editor-sidebar/class-editor-sidebar.php | 1 - .../editor-sidebar/editor-sidebar.tsx | 1 + .../excerpt-suggestions/component-panel.tsx | 129 +++++++++--------- .../excerpt-suggestions.scss | 13 +- .../excerpt-suggestions.tsx | 38 +++++- .../smart-linking/component.tsx | 16 +-- .../editor-sidebar/tabs/sidebar-tools-tab.tsx | 25 ++++ 11 files changed, 161 insertions(+), 90 deletions(-) diff --git a/build/content-helper/editor-sidebar-rtl.css b/build/content-helper/editor-sidebar-rtl.css index b7bdfb98e..79ce5a621 100644 --- a/build/content-helper/editor-sidebar-rtl.css +++ b/build/content-helper/editor-sidebar-rtl.css @@ -1,4 +1,4 @@ -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{right:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.wp-parsely-excerpt-generator{margin-top:1.25rem}.wp-parsely-excerpt-generator .excerpt-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-right:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-right:.375rem}.wp-parsely-excerpt-generator .excerpt-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;margin:var(--grid-unit-10) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{right:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.editor-post-excerpt .excerpt-suggestions-text{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator.is-doc-set-panel{margin-top:1.25rem}.wp-parsely-excerpt-generator .excerpt-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-right:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-right:.375rem}.wp-parsely-excerpt-generator .excerpt-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;margin:var(--grid-unit-10) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-block-overlay{align-items:center;background-color:hsla(0,0%,100%,.85);box-sizing:border-box;display:flex;font-size:1.125rem;height:100%;justify-content:center;right:0;position:absolute;top:0;width:100%}.wp-parsely-block-overlay .wp-parsely-block-overlay-label{align-items:center;display:flex;flex-direction:column;flex-grow:1;gap:var(--grid-unit-10);justify-content:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--grid-unit-10)}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel{font-size:1.125rem;padding:0;pointer-events:all;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:10}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel:focus{box-shadow:none;outline:none}.wp-parsely-block-overlay svg{height:1.5625rem;width:1.5625rem}.wp-parsely-block-overlay.full-content-overlay{font-size:1.25rem;z-index:999}.wp-parsely-block-overlay.full-content-overlay span{margin-top:.9375rem}.wp-parsely-block-overlay.full-content-overlay svg{height:3.125rem;width:3.125rem}.wp-parsely-panel .components-panel__icon{height:1.5rem;margin:0 0 0 var(--grid-unit-15);order:-1;width:1.5rem}.wp-parsely-smart-linking .components-panel__row{flex-direction:column;margin-bottom:0}.wp-parsely-smart-linking .components-base-control,.wp-parsely-smart-linking .components-base-control .components-panel__row,.wp-parsely-smart-linking .components-base-control:last-child{margin-bottom:0}.wp-parsely-smart-linking .smart-linking-text{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings{width:100%}.wp-parsely-smart-linking .parsely-panel-settings-body{display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select{align-self:stretch;display:flex;flex-direction:column;gap:1.5rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control-option-base{padding:.625rem 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control{height:40px;overflow:hidden}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s,color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button:not([data-active-item]){transition:color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-settings{align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-smart-linking .smart-linking-generate,.wp-parsely-smart-linking .smart-linking-manage{align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .smart-linking-generate button,.wp-parsely-smart-linking .smart-linking-manage button{align-items:center;align-self:stretch;display:flex;justify-content:center;width:100%}.wp-parsely-smart-linking .wp-parsely-smart-linking-suggested-links{margin:0}.wp-parsely-smart-linking .wp-parsely-smart-linking-hint{margin-top:calc(var(--grid-unit-10)*-1)}.wp-parsely-smart-linking-review-modal{align-items:flex-start;display:flex;flex-direction:column;width:47.875rem}.wp-parsely-smart-linking-review-modal .smart-linking-modal-body{align-self:stretch;display:flex;flex-direction:row;gap:var(--grid-unit-30)}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details{height:auto;margin-bottom:var(--grid-unit-20);text-align:right}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details .components-menu-item__item{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .linking-post-details{align-items:center;display:flex;justify-content:space-between;width:100%}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image{margin-left:.625rem;max-width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image .icon-container{align-items:center;display:flex;height:3.125rem;justify-content:center;width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title a{text-decoration:none}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info{display:flex;flex-direction:column;flex-grow:1}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info .linking-post-meta{color:var(--Gutenberg-Gray-700,#757575);font-size:.9em}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-type{color:var(--Gutenberg-Gray-700,#757575);margin-right:.625rem;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);min-width:13.75rem;padding:.1875rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs{margin-bottom:var(--grid-unit-20)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:var(--grid-unit-40)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item{color:var(--sidebar-black);font-size:.6875rem;font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item:focus-visible:before{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tab-content{max-height:23.125rem;overflow-y:auto}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip{align-items:center;display:flex;font-size:var(--font-size--small);margin-bottom:.3125rem;margin-top:-.5625rem;padding:.3125rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip .review-sidebar-tip svg{flex-shrink:0;height:1.5rem;margin-right:auto;width:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header{align-items:center;align-self:stretch;color:var(--sidebar-black);display:flex;font-size:.6875rem;font-style:normal;font-weight:600;gap:.375rem;line-height:var(--grid-unit-20);margin-bottom:var(--grid-unit-15);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header>span{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button{align-items:center;display:flex;justify-content:space-between;width:13.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button:focus{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-label{align-items:center;color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));display:flex;padding-right:var(--grid-unit-10);white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected{background-color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected .smart-linking-menu-label{color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .components-menu-item__item{padding-left:0;width:100%}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-item{display:inline;flex-grow:1;overflow:hidden;text-align:right;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion{align-items:flex-start;align-self:stretch;display:flex;flex:1;flex-direction:column;gap:1rem;max-width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs{font-size:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-separator{margin:0 var(--grid-unit-5)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-block{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block .breadcrumbs-current-block-name{margin-right:var(--grid-unit-10)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestion-post-title{font-size:var(--font-size--large);font-weight:500;line-height:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .components-divider{border-color:#ccc;height:1px;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots{color:#ccc;font-size:1rem;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-top{margin-bottom:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-bottom{margin-top:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls{align-items:center;align-self:stretch;display:flex;flex-shrink:0;justify-content:space-between;margin:0 var(--grid-unit-20);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .reviews-controls-middle{align-items:center;display:flex;flex:1 0 0;gap:var(--grid-unit-20);justify-content:center}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-next,.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-previous{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-reject{background:var(--Gutenberg-White,#fff);border-radius:2px;box-shadow:inset 0 0 0 1px var(--Gutenberg-Alert-Red,#cc1818);color:var(--Gutenberg-Alert-Red,#cc1818)}.wp-parsely-smart-linking-close-dialog{align-items:flex-start;display:flex;flex-direction:column;width:24rem}.wp-parsely-smart-linking-close-dialog .smart-linking-close-dialog-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;padding-top:var(--grid-unit-30)}.wp-parsely-preview-editor .editor-styles-wrapper{background:var(--Gutenberg-White,#fff);font-size:var(--font-size--medium);padding-bottom:0}.wp-parsely-preview-editor p[role=document]{margin:0}.wp-parsely-preview-editor .smart-linking-highlight{background:hsla(var(--parsely-green-components),.5);border-radius:2px;color:var(--sidebar-black)!important;mix-blend-mode:multiply;text-decoration-line:underline} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-performance-panel{border-top:1px solid #ddd;margin-top:-1px;padding:16px}.wp-parsely-content-helper .wp-parsely-performance-panel .content-helper-error-message{margin:0!important}.wp-parsely-content-helper .wp-parsely-performance-panel .components-button.wp-parsely-view-post{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .panel-body{width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.5rem;padding:.375rem 0 1rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header{align-items:center;display:flex;gap:.375rem;height:1rem;margin-bottom:0;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2{margin-bottom:.9375rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2 h2{margin-bottom:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-3 h3{font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:1rem;margin-bottom:0;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-subtitle{align-items:center;align-self:stretch;color:var(--Gutenberg-Gray-700,#757575);display:flex;flex:1 0 0;font-size:var(--font-size--smaller);font-style:normal;font-weight:600;gap:.375rem;height:1rem;line-height:1rem;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .components-heading{display:block;font-weight:500;line-height:normal;margin:0}.wp-parsely-content-helper .wp-parsely-performance-panel .components-dropdown-menu{line-height:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points{align-content:flex-start;align-items:flex-start;align-self:stretch;display:flex;flex-wrap:wrap;gap:1rem var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point{align-items:center;background:var(--sidebar-white);border-radius:.25rem;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-5);justify-content:center;min-width:100px;padding:var(--grid-unit-20) var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point svg{align-items:flex-start;border-radius:.125rem;display:flex}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-title{align-self:stretch;color:var(--sidebar-black);font-size:.75rem;font-style:normal;font-weight:400;line-height:1rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value{align-self:stretch;color:var(--sidebar-black);font-size:1.25rem;font-style:normal;font-weight:590;line-height:1.75rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value.is-small{font-size:var(--font-size--medium)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar{align-items:flex-start;align-self:stretch;display:flex;height:1rem;margin:1rem 0;position:relative}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill{--radius:2px;align-self:stretch;position:relative;transition:filter .1s ease,transform .1s ease}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:hover{filter:opacity(1)!important;transform:scaleX(1) scaleY(1)!important}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:first-child{border-radius:0 var(--radius) var(--radius) 0}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:last-child{border-radius:var(--radius) 0 0 var(--radius)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar:hover .bar-fill{filter:opacity(.5);transform:scaleX(1) scaleY(.7)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label{align-items:center;align-self:stretch;display:flex;gap:.5rem;justify-content:center}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color{align-items:center;border-radius:.09375rem;display:flex;flex-direction:column;gap:.625rem;height:.625rem;justify-content:center;width:.1875rem}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-text{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1 0 0;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-value{color:var(--sidebar-black);font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;text-align:left}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:1rem 0}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10);justify-content:space-between}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar{display:flex;flex:1;flex-direction:column;gap:.625rem;justify-content:center;max-width:6.25rem}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar{--radius:1.5px;background:var(--gray-400);border-radius:var(--radius);display:flex;height:.1875rem;margin:0;overflow:hidden}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar:after{background:var(--blueberry,#3858e9);border-radius:var(--radius);content:"";height:100%;width:var(--bar-fill)}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-value{color:var(--sidebar-black);flex-shrink:0;font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;min-width:3.125rem;text-align:left} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-related-posts{align-items:flex-start;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-description{font-size:.8125rem;font-style:normal;font-weight:400;gap:.625rem;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body,.wp-parsely-related-posts .related-posts-description{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body{gap:1rem}.wp-parsely-related-posts .related-posts-body>div{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings{align-self:stretch;display:flex;flex-direction:column;gap:1rem;width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings{display:flex;flex-direction:column;gap:var(--grid-unit-20);width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control{height:2.5rem;overflow:hidden}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex{height:2.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex input{margin:0 var(--grid-unit-15)}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-descr{font-size:.8125rem;font-style:normal;font-weight:400;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-empty,.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-loading-message{color:var(--gray-900);font-size:.75rem;font-style:normal;font-weight:700;line-height:var(--grid-unit-20);overflow:hidden;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-title{align-items:center;align-self:stretch;display:flex;flex-direction:column;font-size:.875rem;font-style:normal;font-weight:600;gap:.5rem;justify-content:center;line-height:1.25rem;overflow:hidden;padding:var(--grid-unit-20);text-decoration-line:underline;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions{align-items:center;align-self:stretch;border-top:1px solid var(--gray-400);display:flex;flex-wrap:wrap;padding:0 var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:first-child,.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:last-child{display:flex;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric{align-items:center;display:flex}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric .parsely-post-metric-data{align-items:center;display:flex;gap:var(--grid-unit-5)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-linked{align-items:center;display:flex;margin-right:auto;fill:#008a20}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon path{fill:#1e1e1e}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon:hover path{fill:#0073aa} diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index efa377dbd..e2025f33a 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'b538347639826e62caaf'); + 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-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'd6febeb9486e0cff901d'); diff --git a/build/content-helper/editor-sidebar.css b/build/content-helper/editor-sidebar.css index 69f7d4425..a338d1802 100644 --- a/build/content-helper/editor-sidebar.css +++ b/build/content-helper/editor-sidebar.css @@ -1,4 +1,4 @@ -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{left:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.wp-parsely-excerpt-generator{margin-top:1.25rem}.wp-parsely-excerpt-generator .excerpt-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-left:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-left:.375rem}.wp-parsely-excerpt-generator .excerpt-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;margin:var(--grid-unit-10) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.editor-post-excerpt__loading_animation{left:.5625rem;position:absolute;top:1.8125rem}.editor-post-excerpt__textarea{margin-bottom:var(--grid-unit-10)}.editor-post-excerpt .excerpt-suggestions-text{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator.is-doc-set-panel{margin-top:1.25rem}.wp-parsely-excerpt-generator .excerpt-suggestions-settings{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-settings>div{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header{align-items:center;display:flex;justify-content:flex-start}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1.4;margin-left:.3125rem;padding:0;text-transform:uppercase}.wp-parsely-excerpt-generator .wp-parsely-excerpt-generator-header .wp-parsely-excerpt-generator-header-label span.beta-label{color:var(--Gutenberg-Gray-700,#757575);padding-left:.375rem}.wp-parsely-excerpt-generator .excerpt-suggestions-generate{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;margin:var(--grid-unit-10) 0}.wp-parsely-excerpt-generator .excerpt-suggestions-generate .components-button{align-items:center;align-self:stretch;border-radius:2px;display:flex;height:2.5rem;justify-content:center;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls{display:flex;gap:var(--grid-unit-10)}.wp-parsely-excerpt-generator .wp-parsely-excerpt-suggestions-review-controls button{flex-grow:1;height:2.5rem;justify-content:center;margin-bottom:var(--grid-unit-10);margin-top:var(--grid-unit-10);padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-excerpt-generator .components-notice{margin:var(--grid-unit-20) 0 var(--grid-unit-15) 0}.wp-parsely-excerpt-generator .components-notice .components-notice__content{margin:0}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message{margin-top:0!important}.wp-parsely-excerpt-generator .components-notice .components-notice__content .content-helper-error-message p:last-child{margin-bottom:0!important} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-block-overlay{align-items:center;background-color:hsla(0,0%,100%,.85);box-sizing:border-box;display:flex;font-size:1.125rem;height:100%;justify-content:center;left:0;position:absolute;top:0;width:100%}.wp-parsely-block-overlay .wp-parsely-block-overlay-label{align-items:center;display:flex;flex-direction:column;flex-grow:1;gap:var(--grid-unit-10);justify-content:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--grid-unit-10)}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel{font-size:1.125rem;padding:0;pointer-events:all;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:10}.wp-parsely-block-overlay .wp-parsely-block-overlay-cancel:focus{box-shadow:none;outline:none}.wp-parsely-block-overlay svg{height:1.5625rem;width:1.5625rem}.wp-parsely-block-overlay.full-content-overlay{font-size:1.25rem;z-index:999}.wp-parsely-block-overlay.full-content-overlay span{margin-top:.9375rem}.wp-parsely-block-overlay.full-content-overlay svg{height:3.125rem;width:3.125rem}.wp-parsely-panel .components-panel__icon{height:1.5rem;margin:0 var(--grid-unit-15) 0 0;order:-1;width:1.5rem}.wp-parsely-smart-linking .components-panel__row{flex-direction:column;margin-bottom:0}.wp-parsely-smart-linking .components-base-control,.wp-parsely-smart-linking .components-base-control .components-panel__row,.wp-parsely-smart-linking .components-base-control:last-child{margin-bottom:0}.wp-parsely-smart-linking .smart-linking-text{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings{width:100%}.wp-parsely-smart-linking .parsely-panel-settings-body{display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select{align-self:stretch;display:flex;flex-direction:column;gap:1.5rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control-option-base{padding:.625rem 0}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control{height:40px;overflow:hidden}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s,color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-block-select .components-toggle-group-control button:not([data-active-item]){transition:color .2s .1s}.wp-parsely-smart-linking .parsely-panel-settings-body .smart-linking-settings{align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-smart-linking .smart-linking-generate,.wp-parsely-smart-linking .smart-linking-manage{align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .smart-linking-generate button,.wp-parsely-smart-linking .smart-linking-manage button{align-items:center;align-self:stretch;display:flex;justify-content:center;width:100%}.wp-parsely-smart-linking .wp-parsely-smart-linking-suggested-links{margin:0}.wp-parsely-smart-linking .wp-parsely-smart-linking-hint{margin-top:calc(var(--grid-unit-10)*-1)}.wp-parsely-smart-linking-review-modal{align-items:flex-start;display:flex;flex-direction:column;width:47.875rem}.wp-parsely-smart-linking-review-modal .smart-linking-modal-body{align-self:stretch;display:flex;flex-direction:row;gap:var(--grid-unit-30)}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details{height:auto;margin-bottom:var(--grid-unit-20);text-align:left}.wp-parsely-smart-linking-review-modal .wp-parsely-link-suggestion-link-details .components-menu-item__item{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .linking-post-details{align-items:center;display:flex;justify-content:space-between;width:100%}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image{margin-right:.625rem;max-width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-image .icon-container{align-items:center;display:flex;height:3.125rem;justify-content:center;width:3.125rem}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-title a{text-decoration:none}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info{display:flex;flex-direction:column;flex-grow:1}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-info .linking-post-meta{color:var(--Gutenberg-Gray-700,#757575);font-size:.9em}.wp-parsely-smart-linking-review-modal .linking-post-details .linking-post-type{color:var(--Gutenberg-Gray-700,#757575);margin-left:.625rem;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);min-width:13.75rem;padding:.1875rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs{margin-bottom:var(--grid-unit-20)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs button{align-items:center;display:flex;flex:1 0 0;flex-direction:column;height:var(--grid-unit-40)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item{color:var(--sidebar-black);font-size:.6875rem;font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tabs-item:focus-visible:before{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .smart-linking-review-sidebar-tabs .components-tab-panel__tab-content{max-height:23.125rem;overflow-y:auto}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip{align-items:center;display:flex;font-size:var(--font-size--small);margin-bottom:.3125rem;margin-top:-.5625rem;padding:.3125rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-tip .review-sidebar-tip svg{flex-shrink:0;height:1.5rem;margin-left:auto;width:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header{align-items:center;align-self:stretch;color:var(--sidebar-black);display:flex;font-size:.6875rem;font-style:normal;font-weight:600;gap:.375rem;line-height:var(--grid-unit-20);margin-bottom:var(--grid-unit-15);text-transform:uppercase}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .review-sidebar-header>span{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button{align-items:center;display:flex;justify-content:space-between;width:13.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button:focus{box-shadow:none;outline:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-label{align-items:center;color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));display:flex;padding-left:var(--grid-unit-10);white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected{background-color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9));color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button.is-selected .smart-linking-menu-label{color:#fff}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .components-menu-item__item{padding-right:0;width:100%}.wp-parsely-smart-linking-review-modal .smart-linking-review-sidebar .components-button.components-menu-item__button .smart-linking-menu-item{display:inline;flex-grow:1;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion{align-items:flex-start;align-self:stretch;display:flex;flex:1;flex-direction:column;gap:1rem;max-width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs{font-size:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-separator{margin:0 var(--grid-unit-5)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-parent-block{color:var(--Gutenberg-Gray-700,#757575)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block{color:var(--sidebar-black)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestions-breadcrumbs .breadcrumbs-current-block .breadcrumbs-current-block-name{margin-left:var(--grid-unit-10)}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-suggestion-post-title{font-size:var(--font-size--large);font-weight:500;line-height:1.5rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .components-divider{border-color:#ccc;height:1px;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots{color:#ccc;font-size:1rem;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-top{margin-bottom:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .three-dots.is-bottom{margin-top:.75rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls{align-items:center;align-self:stretch;display:flex;flex-shrink:0;justify-content:space-between;margin:0 var(--grid-unit-20);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:28.25rem}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .reviews-controls-middle{align-items:center;display:flex;flex:1 0 0;gap:var(--grid-unit-20);justify-content:center}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-next,.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-previous{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.wp-parsely-smart-linking-review-modal .smart-linking-review-suggestion .review-controls .wp-parsely-review-suggestion-reject{background:var(--Gutenberg-White,#fff);border-radius:2px;box-shadow:inset 0 0 0 1px var(--Gutenberg-Alert-Red,#cc1818);color:var(--Gutenberg-Alert-Red,#cc1818)}.wp-parsely-smart-linking-close-dialog{align-items:flex-start;display:flex;flex-direction:column;width:24rem}.wp-parsely-smart-linking-close-dialog .smart-linking-close-dialog-actions{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-15);justify-content:flex-end;padding-top:var(--grid-unit-30)}.wp-parsely-preview-editor .editor-styles-wrapper{background:var(--Gutenberg-White,#fff);font-size:var(--font-size--medium);padding-bottom:0}.wp-parsely-preview-editor p[role=document]{margin:0}.wp-parsely-preview-editor .smart-linking-highlight{background:hsla(var(--parsely-green-components),.5);border-radius:2px;color:var(--sidebar-black)!important;mix-blend-mode:multiply;text-decoration-line:underline} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-content-helper .wp-parsely-performance-panel{border-top:1px solid #ddd;margin-top:-1px;padding:16px}.wp-parsely-content-helper .wp-parsely-performance-panel .content-helper-error-message{margin:0!important}.wp-parsely-content-helper .wp-parsely-performance-panel .components-button.wp-parsely-view-post{align-items:center;display:flex;justify-content:center;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .panel-body{width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:.5rem;padding:.375rem 0 1rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header{align-items:center;display:flex;gap:.375rem;height:1rem;margin-bottom:0;width:100%}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2{margin-bottom:.9375rem}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-2 h2{margin-bottom:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-header.level-3 h3{font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:1rem;margin-bottom:0;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-stat-panel .panel-subtitle{align-items:center;align-self:stretch;color:var(--Gutenberg-Gray-700,#757575);display:flex;flex:1 0 0;font-size:var(--font-size--smaller);font-style:normal;font-weight:600;gap:.375rem;height:1rem;line-height:1rem;text-transform:uppercase}.wp-parsely-content-helper .wp-parsely-performance-panel .components-heading{display:block;font-weight:500;line-height:normal;margin:0}.wp-parsely-content-helper .wp-parsely-performance-panel .components-dropdown-menu{line-height:0}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points{align-content:flex-start;align-items:flex-start;align-self:stretch;display:flex;flex-wrap:wrap;gap:1rem var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point{align-items:center;background:var(--sidebar-white);border-radius:.25rem;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-5);justify-content:center;min-width:100px;padding:var(--grid-unit-20) var(--grid-unit-10)}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point svg{align-items:flex-start;border-radius:.125rem;display:flex}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-title{align-self:stretch;color:var(--sidebar-black);font-size:.75rem;font-style:normal;font-weight:400;line-height:1rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value{align-self:stretch;color:var(--sidebar-black);font-size:1.25rem;font-style:normal;font-weight:590;line-height:1.75rem;text-align:center}.wp-parsely-content-helper .wp-parsely-performance-panel .performance-data-points .data-point .data-point-value.is-small{font-size:var(--font-size--medium)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar{align-items:flex-start;align-self:stretch;display:flex;height:1rem;margin:1rem 0;position:relative}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill{--radius:2px;align-self:stretch;position:relative;transition:filter .1s ease,transform .1s ease}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:hover{filter:opacity(1)!important;transform:scaleX(1) scaleY(1)!important}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:first-child{border-radius:var(--radius) 0 0 var(--radius)}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill:last-child{border-radius:0 var(--radius) var(--radius) 0}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar .bar-fill.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel div.multi-percentage-bar:hover .bar-fill{filter:opacity(.5);transform:scaleX(1) scaleY(.7)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20)}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label{align-items:center;align-self:stretch;display:flex;gap:.5rem;justify-content:center}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color{align-items:center;border-radius:.09375rem;display:flex;flex-direction:column;gap:.625rem;height:.625rem;justify-content:center;width:.1875rem}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.direct{background-color:hsl(var(--ref-direct))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.internal{background-color:hsl(var(--ref-internal))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.search{background-color:hsl(var(--ref-search))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.social{background-color:hsl(var(--ref-social))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-color.other{background-color:hsl(var(--ref-other))}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-text{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1 0 0;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .percentage-bar-labels .single-label .label-value{color:var(--sidebar-black);font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;text-align:right}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:1rem 0}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10);justify-content:space-between}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;color:var(--sidebar-black);flex:1;font-feature-settings:"ss06" on;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:1rem;overflow:hidden;text-overflow:ellipsis}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar{display:flex;flex:1;flex-direction:column;gap:.625rem;justify-content:center;max-width:6.25rem}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar{--radius:1.5px;background:var(--gray-400);border-radius:var(--radius);display:flex;height:.1875rem;margin:0;overflow:hidden}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-bar .percentage-bar:after{background:var(--blueberry,#3858e9);border-radius:var(--radius);content:"";height:100%;width:var(--bar-fill)}.wp-parsely-content-helper .wp-parsely-performance-panel .referrers-list .referrers-row .referrers-row-value{color:var(--sidebar-black);flex-shrink:0;font-size:var(--font-size--small);font-style:normal;font-weight:590;line-height:1rem;min-width:3.125rem;text-align:right} #wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.wp-parsely-related-posts{align-items:flex-start;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-description{font-size:.8125rem;font-style:normal;font-weight:400;gap:.625rem;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body,.wp-parsely-related-posts .related-posts-description{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body{gap:1rem}.wp-parsely-related-posts .related-posts-body>div{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings{align-self:stretch;display:flex;flex-direction:column;gap:1rem;width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings{display:flex;flex-direction:column;gap:var(--grid-unit-20);width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .components-base-control__field{margin-bottom:0}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control{height:2.5rem;overflow:hidden}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button{background:transparent;outline:2px solid transparent;outline-offset:-3px}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-types .components-toggle-group-control button[data-active-item]{background:var(--sidebar-black);border-radius:3px;box-shadow:0 -3px 0 0 #fff,0 3px 0 0 #fff;transition:background 0s .5s,border-radius 0s .5s,box-shadow 0s .5s}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values{width:100%}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex{height:2.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-filter-settings .related-posts-filter-values .components-combobox-control__suggestions-container .components-flex input{margin:0 var(--grid-unit-15)}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-descr{font-size:.8125rem;font-style:normal;font-weight:400;line-height:1.25rem}.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-empty,.wp-parsely-related-posts .related-posts-body .related-posts-wrapper .related-posts-loading-message{color:var(--gray-900);font-size:.75rem;font-style:normal;font-weight:700;line-height:var(--grid-unit-20);overflow:hidden;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single{align-items:flex-start;align-self:stretch;border:1px solid var(--Gutenberg-Gray-400,#ccc);border-radius:2px;display:flex;flex-direction:column}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-title{align-items:center;align-self:stretch;display:flex;flex-direction:column;font-size:.875rem;font-style:normal;font-weight:600;gap:.5rem;justify-content:center;line-height:1.25rem;overflow:hidden;padding:var(--grid-unit-20);text-decoration-line:underline;text-overflow:ellipsis}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions{align-items:center;align-self:stretch;border-top:1px solid var(--gray-400);display:flex;flex-wrap:wrap;padding:0 var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info{align-items:center;display:flex;flex-grow:1;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:first-child,.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info>div:last-child{display:flex;gap:var(--grid-unit-10)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric{align-items:center;display:flex}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-metric .parsely-post-metric-data{align-items:center;display:flex;gap:var(--grid-unit-5)}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .related-post-linked{align-items:center;display:flex;margin-left:auto;fill:#008a20}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon path{fill:#1e1e1e}.wp-parsely-related-posts .related-posts-body .related-posts-list .related-post-single .related-post-actions .related-post-info .wp-parsely-icon:hover path{fill:#0073aa} diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index 9ec473307..80fb50636 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -1,12 +1,12 @@ -!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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({},{_:function(){return Sr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),E=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"})]})},L=function(){return L=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( +!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),o=Symbol.for("react.fragment"),s=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,o={},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)s.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:o,_owner:a.current}}t.Fragment=o,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 o=t[r]={exports:{}};return e[r](o,o.exports,n),o.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 Sr},_:function(){return jr}});var e,t,r,i,o,s,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);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===(o=window.wp.editSite)||void 0===o?void 0:o.PluginDocumentSettingPanel,d=null!==(a=null===(s=window.wp.editor)||void 0===s?void 0:s.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 m,w,b,_=window.wp.element,x=window.wp.i18n,k=window.wp.primitives,S=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),j=window.wp.plugins,P=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,o=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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}(),T=(P.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"})})}),E=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"})]})},L=function(){return L=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.AccessToFeatureDisabled,U.ParselyApiForbidden,U.ParselyApiResponseContainsError,U.ParselyApiReturnedNoData,U.ParselyApiReturnedTooManyResults,U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsApiSecretNotSet,U.PluginSettingsSiteIdNotSet,U.PostIsNotPublished,U.UnknownError,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiNoAuthentication,U.ParselySuggestionsApiNoAuthorization,U.ParselySuggestionsApiNoData,U.ParselySuggestionsApiSchemaError];return o.retryFetch=!s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.code===U.AccessToFeatureDisabled?o.message=(0,x.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):o.code===U.ParselySuggestionsApiNoAuthorization?o.message=(0,x.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiError||o.code===U.ParselySuggestionsApiOpenAiUnavailable?o.message=(0,x.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):o.code===U.HttpRequestFailed&&o.message.includes("cURL error 28")?o.message=(0,x.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiSchemaError?o.message=(0,x.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):o.code===U.ParselySuggestionsApiNoData?o.message=(0,x.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):o.code===U.ParselySuggestionsApiOpenAiSchema?o.message=(0,x.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):o.code===U.ParselySuggestionsApiAuthUnavailable&&(o.message=(0,x.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),o}return ee(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[U.PluginCredentialsNotSetMessageDetected,U.PluginSettingsSiteIdNotSet,U.PluginSettingsApiSecretNotSet].includes(this.code)?X(e):(this.code===U.FetchError&&(this.hint=this.Hint((0,x.__)("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,x.__)("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,x.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,f.jsx)(Q,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},t.prototype.Hint=function(e){return'

'.concat((0,x.__)("Hint:","wp-parsely")," ").concat(e,"

")},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ne=window.wp.url,re=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,t){return n=this,r=void 0,o=function(){var n,r,i,o,s,a;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]32&&(e=e.slice(0,32)),s(e),o(e)}})})},ve=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,x.__)("Select a persona…","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Persona","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[o&&(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:fe(t)?ue.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:pe.map((function(e){if(!p&&"custom"===e)return null;var r=ue[e],i=e===t||fe(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&fe(t)&&(0,f.jsx)(he,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ge={neutral:{label:(0,x.__)("Neutral","wp-parsely")},formal:{label:(0,x.__)("Formal","wp-parsely")},humorous:{label:(0,x.__)("Humorous","wp-parsely")},confident:{label:(0,x.__)("Confident","wp-parsely")},provocative:{label:(0,x.__)("Provocative","wp-parsely")},serious:{label:(0,x.__)("Serious","wp-parsely")},inspirational:{label:(0,x.__)("Inspirational","wp-parsely")},skeptical:{label:(0,x.__)("Skeptical","wp-parsely")},conversational:{label:(0,x.__)("Conversational","wp-parsely")},analytical:{label:(0,x.__)("Analytical","wp-parsely")},custom:{label:(0,x.__)("Custom Tone","wp-parsely"),icon:ae}},ye=Object.keys(ge),me=function(e){return"custom"===e||""===e?ge.custom.label:we(e)?e:ge[e].label},we=function(e){return!ye.includes(e)||"custom"===e},be=function(e){var t=e.value,n=e.onChange,r=(0,_.useState)(""),i=r[0],o=r[1],s=(0,se.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,x.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),s(e),o(e)}})})},_e=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,x.__)("Select a tone","wp-parsely"):n,i=e.label,o=void 0===i?(0,x.__)("Tone","wp-parsely"):i,s=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u;return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,f.jsx)(h.DropdownMenu,{label:(0,x.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:we(t)?ge.custom.label:r}),(0,f.jsx)(ce,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,x.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:ye.map((function(e){if(!p&&"custom"===e)return null;var r=ge[e],i=e===t||we(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),s(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)(le,{icon:r.icon}),r.label]},e)}))})})}}),p&&we(t)&&(0,f.jsx)(be,{onChange:function(e){s(""!==e?e:"custom")},value:"custom"===t?"":t})]})},xe=function(e){var t=e.isLoading,n=e.onPersonaChange,r=e.onToneChange,i=e.persona,o=e.tone;return(0,f.jsxs)("div",{className:"excerpt-suggestions-settings",children:[(0,f.jsx)(_e,{tone:o,value:me(o),onChange:function(e){r(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t,allowCustom:!0}),(0,f.jsx)(ve,{persona:i,value:de(i),onChange:function(e){n(e)},onDropdownChange:function(e){P.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t,allowCustom:!0})]})},ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?(0,x.sprintf)( // Translators: %1$s the number of words in the excerpt. // Translators: %1$s the number of words in the excerpt. -(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[a.currentExcerpt,I]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[a.newExcerptGeneratedCount]);var D=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(E,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]});return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[(0,f.jsxs)("div",{style:{position:"relative"},children:[u&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:(0,x.__)("Write an excerpt (optional)","wp-parsely"),className:"editor-post-excerpt__textarea",onChange:function(e){a.isUnderReview||N({excerpt:e}),l(ke(ke({},a),{currentExcerpt:e})),y(!0)},onKeyUp:function(){var e;if(g)y(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";l(ke(ke({},a),{currentExcerpt:n}))}},value:u?"":a.isUnderReview?a.currentExcerpt:I,help:L||null})]}),(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt","wp-parsely"),target:"_blank",variant:"link",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator",children:[i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),a.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[D,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,N({excerpt:a.currentExcerpt})];case 1:return e.sent(),l(ke(ke({},a),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return N({excerpt:a.oldExcerpt}),l(ke(ke({},a),{currentExcerpt:a.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:u,onPersonaChange:function(e){A("Persona",e),b(e)},onSettingChange:A,onToneChange:function(e){A("Tone",e),j(e)},persona:t.ExcerptSuggestions.Persona,tone:t.ExcerptSuggestions.Tone}),D,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:p(!0),o(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(B,R,w,S)];case 2:return e=n.sent(),l({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:a.newExcerptGeneratedCount+1,oldExcerpt:I}),[3,5];case 3:return(t=n.sent())instanceof te?o(t):(o(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return p(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:u,disabled:u||!R,children:[u&&(0,x.__)("Generating Excerpt…","wp-parsely"),!u&&a.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!u&&0===a.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),(0,f.jsxs)(h.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-excerpt-generator-beta",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Ee=function(){return(0,f.jsx)(K.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:Sr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{})})})})},Le=function(e,t){var n,r,i;return"wp-parsely-block-editor-sidebar"!==t?e:H().ExcerptSuggestions?((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,q.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Ee,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt"),e):e};function Ce(){(0,q.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Le,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Et=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Lt=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Lt,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Et,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),$.updateBlockAttributes(n,{content:o.innerHTML}))),[4,L(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,E(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,L(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){$.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ -(0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=L||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!E,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/smart-linking/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ -(0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,q(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,$(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:L,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(L?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;q(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:L,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(L?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=We(L?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ -(0,x.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,x._n)("attempt","attempts",r.numRetries,"wp-parsely"))),console.error(r),[4,$(o)];case 9:return c.sent(),o.createErrorSnackbar(),[3,15];case 10:return[4,q(!1)];case 11:return c.sent(),[4,ne(t)];case 12:return c.sent(),[4,ie(!1)];case 13:return c.sent(),[4,me(L?"all":null==fe?void 0:fe.clientId)];case 14:return c.sent(),clearTimeout(e),[7];case 15:return[2]}var u}))}))},variant:"primary",isBusy:T,disabled:T,children:B?(0,x.sprintf)(/* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ /* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ -(0,x.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,x.__)("Generating Smart Links…","wp-parsely"):(0,x.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,f.jsx)("div",{className:"smart-linking-manage",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t;return Mt(this,(function(n){switch(n.label){case 0:return[4,Je()];case 1:return e=n.sent(),t=Ze(),[4,Z(t)];case 2:return n.sent(),ce(!0),P.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,x.__)("Review Smart Links","wp-parsely")})})]}),E&&(0,f.jsx)(It,{isOpen:E,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){b(!0),ce(!1)}})]})},Gt=function(){return Gt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");et(t,e)}))})))},Xt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M7 11.5h10V13H7z"})}),en=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),tn=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,o=void 0===i?2:i,s=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,f.jsxs)("div",{className:"performance-stat-panel",children:[(0,f.jsxs)(h.__experimentalHStack,{className:"panel-header level-"+o,children:[(0,f.jsx)(h.__experimentalHeading,{level:o,children:t}),r&&!c&&(0,f.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,f.jsx)(h.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,f.jsx)("div",{className:"panel-body",children:u?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):s})]})};function nn(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,o=r.toString(),s="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,o=i.toFixed(u),s=l}a=c})),o+n+s}var rn=function(e){var t=e.data,n=e.isLoading,r=(0,_.useState)(w.Views),i=r[0],o=r[1],s=(0,_.useState)(!1),a=s[0],l=s[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,x.__)("Social","wp-parsely");case"search":return(0,x.__)("Search","wp-parsely");case"other":return(0,x.__)("Other","wp-parsely");case"internal":return(0,x.__)("Internal","wp-parsely");case"direct":return(0,x.__)("Direct","wp-parsely")}return e},u=(0,x.sprintf)((0,x.__)("By %s","wp-parsely"),G(i)); +(0,x._n)("%1$s word","%1$s words",e,"wp-parsely"),e):"")}),[u.currentExcerpt,D]),(0,_.useEffect)((function(){var e=document.querySelector(".editor-post-excerpt textarea");e&&(e.scrollTop=0)}),[u.newExcerptGeneratedCount]);var G=(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header",children:[(0,f.jsx)(E,{size:16}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator-header-label",children:[(0,x.__)("Generate With Parse.ly","wp-parsely"),(0,f.jsx)("span",{className:"beta-label",children:(0,x.__)("Beta","wp-parsely")})]})]}),H=n?(0,x.__)("Write an excerpt (optional)","wp-parsely"):(0,x.__)("Excerpt","wp-parsely");return(0,f.jsxs)("div",{className:"editor-post-excerpt",children:[!n&&(0,f.jsxs)("div",{className:"excerpt-suggestions-text",children:[(0,x.__)("Use Parse.ly AI to generate a concise, engaging excerpt for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/excerpt-generator/",target:"_blank",variant:"link",rel:"noopener",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),(0,f.jsxs)("div",{style:{position:"relative"},children:[g&&(0,f.jsx)("div",{className:"editor-post-excerpt__loading_animation",children:(0,f.jsx)(Te,{})}),(0,f.jsx)(h.TextareaControl,{__nextHasNoMarginBottom:!0,label:H,className:"editor-post-excerpt__textarea",onChange:function(e){u.isUnderReview||I({excerpt:e}),p(ke(ke({},u),{currentExcerpt:e})),b(!0)},onKeyUp:function(){var e;if(w)b(!1);else{var t=document.querySelector(".editor-post-excerpt textarea"),n=null!==(e=null==t?void 0:t.textContent)&&void 0!==e?e:"";p(ke(ke({},u),{currentExcerpt:n}))}},value:g?"":u.isUnderReview?u.currentExcerpt:D,help:A||null})]}),n&&(0,f.jsxs)(h.Button,{href:(0,x.__)("https://wordpress.org/documentation/article/page-post-settings-sidebar/#excerpt"),target:"_blank",variant:"link",rel:"noopener",children:[(0,x.__)("Learn more about manual excerpts","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]}),(0,f.jsxs)("div",{className:"wp-parsely-excerpt-generator"+(n?" is-doc-set-panel":""),children:[a&&(0,f.jsx)(h.Notice,{className:"wp-parsely-excerpt-generator-error",onRemove:function(){return l(void 0)},status:"info",children:a.Message()}),u.isUnderReview?(0,f.jsxs)(f.Fragment,{children:[n&&G,(0,f.jsxs)("div",{className:"wp-parsely-excerpt-suggestions-review-controls",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){switch(e.label){case 0:return[4,I({excerpt:u.currentExcerpt})];case 1:return e.sent(),p(ke(ke({},u),{isUnderReview:!1})),P.trackEvent("excerpt_generator_accepted"),[2]}}))}))},children:(0,x.__)("Accept","wp-parsely")}),(0,f.jsx)(h.Button,{isDestructive:!0,variant:"secondary",onClick:function(){return Se(void 0,void 0,void 0,(function(){return je(this,(function(e){return I({excerpt:u.oldExcerpt}),p(ke(ke({},u),{currentExcerpt:u.oldExcerpt,isUnderReview:!1})),P.trackEvent("excerpt_generator_discarded"),[2]}))}))},children:(0,x.__)("Discard","wp-parsely")})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(xe,{isLoading:g,onPersonaChange:function(e){R("Persona",e),j(e)},onSettingChange:R,onToneChange:function(e){R("Tone",e),C(e)},persona:i.ExcerptSuggestions.Persona,tone:i.ExcerptSuggestions.Tone}),n&&G,(0,f.jsx)("div",{className:"excerpt-suggestions-generate",children:(0,f.jsxs)(h.Button,{onClick:function(){return Se(void 0,void 0,void 0,(function(){var e,t;return je(this,(function(n){switch(n.label){case 0:y(!0),l(void 0),n.label=1;case 1:return n.trys.push([1,3,4,5]),P.trackEvent("excerpt_generator_pressed"),[4,oe.getInstance().generateExcerpt(V,F,S,L)];case 2:return e=n.sent(),p({currentExcerpt:e,isUnderReview:!0,newExcerptGeneratedCount:u.newExcerptGeneratedCount+1,oldExcerpt:D}),[3,5];case 3:return(t=n.sent())instanceof te?l(t):(l(new te((0,x.__)("An unknown error occurred.","wp-parsely"),U.UnknownError)),console.error(t)),[3,5];case 4:return y(!1),[7];case 5:return[2]}}))}))},variant:"primary",isBusy:g,disabled:g||!F,children:[g&&(0,x.__)("Generating Excerpt…","wp-parsely"),!g&&u.newExcerptGeneratedCount>0&&(0,x.__)("Regenerate Excerpt","wp-parsely"),!g&&0===u.newExcerptGeneratedCount&&(0,x.__)("Generate Excerpt","wp-parsely")]})})]}),n&&(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/excerpt-generator/",target:"_blank",variant:"link",rel:"noopener",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(h.Icon,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]})]})},Te=function(){return(0,f.jsx)(h.Animate,{type:"loading",children:function(e){var t=e.className;return(0,f.jsx)("span",{className:t,children:(0,x.__)("Generating…","wp-parsely")})}})},Ee=function(){return(0,f.jsx)(q.PostTypeSupportCheck,{supportKeys:"excerpt",children:(0,f.jsx)(p,{name:"parsely-post-excerpt",title:(0,x.__)("Excerpt","wp-parsely"),children:(0,f.jsx)(D,{endpoint:"editor-sidebar",defaultSettings:jr(window.wpParselyContentHelperSettings),children:(0,f.jsx)(Pe,{isDocumentSettingPanel:!0})})})})},Le=function(e,t){var n,r,i;return t!==Sr?e:H().ExcerptSuggestions?((null===(n=null===window||void 0===window?void 0:window.Jetpack_Editor_Initial_State)||void 0===n?void 0:n.available_blocks["ai-content-lens"])&&(console.log("Parse.ly: Jetpack AI is enabled and will be disabled."),(0,$.removeFilter)("blocks.registerBlockType","jetpack/ai-content-lens-features")),(0,j.registerPlugin)("wp-parsely-excerpt-suggestions",{render:function(){return(0,f.jsx)(Ee,{})}}),(null===(r=(0,v.dispatch)("core/editor"))||void 0===r?void 0:r.removeEditorPanel)?null===(i=(0,v.dispatch)("core/editor"))||void 0===i||i.removeEditorPanel("post-excerpt"):null==Z||Z.removeEditorPanel("post-excerpt"),e):e};function Ce(){(0,$.addFilter)("plugins.registerPlugin","wp-parsely-excerpt-suggestions",Le,1e3)}var Ne=window.wp.blockEditor;function Ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Oe=function(){return Oe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)return r(e.innerBlocks,t[o].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[o])){var s=t[o],a=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==s?void 0:s.attributes.content)||"","text/html"),c=Array.from(a.querySelectorAll("a[data-smartlink]")),u=Array.from(l.querySelectorAll("a[data-smartlink]")),p=c.filter((function(e){return!u.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),d=u.filter((function(e){return!c.some((function(t){return t.dataset.smartlink===e.dataset.smartlink}))})),f=c.filter((function(e){var t=u.find((function(t){return t.dataset.smartlink===e.dataset.smartlink}));return t&&t.outerHTML!==e.outerHTML}));(p.length>0||d.length>0||f.length>0)&&n.push({block:e,prevBlock:s,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(a,l.current);s.length>0&&(s.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),l.current=a)}),s);return e(t),function(){e.cancel()}}),[a,s,t,i,n,r]),null},Me=function(e){var t=e.value,n=e.onChange,r=e.max,i=e.min,o=e.suffix,s=e.size,a=e.label,l=e.initialPosition,c=e.disabled,u=e.className;return(0,f.jsxs)("div",{className:"parsely-inputrange-control ".concat(u||""),children:[(0,f.jsx)(h.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:a}),(0,f.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,f.jsx)(h.__experimentalNumberControl,{disabled:c,value:t,suffix:(0,f.jsx)(h.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=s?s:"__unstable-large",min:i,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,f.jsx)(h.RangeControl,{disabled:c,value:t,showTooltip:!1,initialPosition:l,onChange:function(e){n(e)},withInputField:!1,min:i,max:r})]})]})},De=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Fe=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]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]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]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]

","\n\x3c!-- /wp:paragraph --\x3e");t&&d((0,Re.parse)(n))}),[o]),(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:s,right:a,up:s,down:a}}),(0,f.jsx)("div",{className:"review-suggestion-post-title",children:null===(t=o.post_data)||void 0===t?void 0:t.title}),(0,f.jsxs)("div",{className:"review-suggestion-preview",children:[!(null===(n=o.post_data)||void 0===n?void 0:n.is_first_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"top"}),(0,f.jsx)(bt,{block:p[0],link:o,useOriginalBlock:!0}),!(null===(r=o.post_data)||void 0===r?void 0:r.is_last_paragraph)&&(0,f.jsx)(_t,{topOrBottom:"bottom"})]}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(xt,{link:o}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:s,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsx)("div",{className:"reviews-controls-middle",children:(0,f.jsx)(h.Button,{target:"_blank",href:(null===(i=o.post_data)||void 0===i?void 0:i.edit_link)+"&smart-link="+o.uid,variant:"secondary",onClick:function(){P.trackEvent("smart_linking_open_in_editor_pressed",{type:"inbound",uid:o.uid})},children:(0,x.__)("Open in the Editor","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:a,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]})},St=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:"none",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"})]})},jt=function(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;ii.bottom)&&(n.scrollTop=r.offsetTop-n.offsetTop)}}}}),[t,l]);var u=function(){var e=document.querySelector(".smart-linking-review-sidebar-tabs [data-active-item]"),t=null==e?void 0:e.nextElementSibling;t||(t=document.querySelector('.smart-linking-review-sidebar-tabs [role="tab"]')),t&&t.click()},p=(0,f.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,x.__)("NEW","wp-parsely"),(0,f.jsx)(St,{})]}),d=[];n&&n.length>0&&d.push({name:"outbound",title:(0,x.__)("Outbound","wp-parsely")}),r&&r.length>0&&d.push({name:"inbound",title:(0,x.__)("Inbound","wp-parsely")});var v="outbound";return d=d.filter((function(e){return"outbound"===e.name&&r&&0===r.length&&(e.title=(0,x.__)("Outbound Smart Links","wp-parsely"),v="outbound"),"inbound"===e.name&&n&&0===n.length&&(e.title=(0,x.__)("Inbound Smart Links","wp-parsely"),v="inbound"),e})),(0,f.jsxs)("div",{className:"smart-linking-review-sidebar",ref:o,children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{tab:function(){return u()},"shift+tab":function(){return u()}}}),(0,f.jsx)(h.TabPanel,{className:"smart-linking-review-sidebar-tabs",initialTabName:v,tabs:d,onSelect:function(e){var t,o;"outbound"===e&&n&&n.length>0&&i(n[0]),"inbound"===e&&r&&r.length>0&&i(r[0]),P.trackEvent("smart_linking_modal_tab_selected",{tab:e,total_inbound:null!==(t=null==r?void 0:r.length)&&void 0!==t?t:0,total_outbound:null!==(o=null==n?void 0:n.length)&&void 0!==o?o:0})},children:function(e){return(0,f.jsxs)(f.Fragment,{children:["outbound"===e.name&&(0,f.jsx)(f.Fragment,{children:n&&0!==n.length?n.map((function(e,n){return(0,f.jsxs)(h.MenuItem,{ref:function(e){s.current[n]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:[(0,f.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&p]},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No outbound links found.","wp-parsely")]})}),"inbound"===e.name&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"review-sidebar-tip",children:(0,x.__)("This section shows external posts that link back to the current post.","wp-parsely")}),r&&0!==r.length?r.map((function(e,r){var o;return(0,f.jsx)(h.MenuItem,{ref:function(e){s.current[(n?n.length:0)+r]=e},className:(null==t?void 0:t.uid)===e.uid?"is-selected":"",role:"menuitemradio",isSelected:(null==t?void 0:t.uid)===e.uid,onClick:function(){return i(e)},children:(0,f.jsx)("span",{className:"smart-linking-menu-item",children:null===(o=e.post_data)||void 0===o?void 0:o.title})},e.uid)})):(0,f.jsxs)(f.Fragment,{children:[" ",(0,x.__)("No inbound links found.","wp-parsely")]})]})]})}})]})},Tt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),Et=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Lt=function(e){var t,n,r,i,o=null===(t=e.link.match)||void 0===t?void 0:t.blockId,s=(0,v.useSelect)((function(e){var t=e("core/block-editor"),n=t.getBlock,r=t.getBlockParents;return o?{block:n(o),parents:r(o).map((function(e){return n(e)})).filter((function(e){return void 0!==e}))}:{block:void 0,parents:[]}}),[o]),a=s.block,l=s.parents;return a?(0,f.jsxs)("div",{className:"review-suggestions-breadcrumbs",children:[l.map((function(e,t){var n;return(0,f.jsxs)("span",{children:[(0,f.jsx)("span",{className:"breadcrumbs-parent-block",children:null===(n=(0,Re.getBlockType)(e.name))||void 0===n?void 0:n.title}),(0,f.jsx)("span",{className:"breadcrumbs-parent-separator",children:" / "})]},t)})),(0,f.jsxs)("span",{className:"breadcrumbs-current-block",children:[(0,f.jsx)("span",{className:"breadcrumbs-current-block-type",children:null===(n=(0,Re.getBlockType)(a.name))||void 0===n?void 0:n.title}),(null===(i=null===(r=a.attributes)||void 0===r?void 0:r.metadata)||void 0===i?void 0:i.name)&&(0,f.jsx)("span",{className:"breadcrumbs-current-block-name",children:a.attributes.metadata.name})]})]}):(0,f.jsx)(f.Fragment,{})},Ct=function(e){var t,n=e.link,r=(0,_.useState)(n.href),i=r[0],o=r[1],s=(0,_.useState)(null===(t=n.destination)||void 0===t?void 0:t.post_type),a=s[0],l=s[1],c=(0,_.useRef)(null),u=(0,v.useDispatch)(it).updateSmartLink;return(0,_.useEffect)((function(){n.destination?l(n.destination.post_type):(l((0,x.__)("External","wp-parsely")),dt.getInstance().getPostTypeByURL(n.href).then((function(e){e&&l(e.post_type),n.destination=e,u(n)})))}),[n,u]),(0,_.useEffect)((function(){var e=function(){if(c.current){var e=c.current.offsetWidth,t=Math.floor(e/8);o(function(e,t){var n=e.replace(/(^\w+:|^)\/\//,"").replace(/^www\./,"");if(!t||n.length<=t)return n;var r=n.split("/")[0],i=n.substring(r.length);t-=r.length;var o=Math.floor((t-3)/2),s=i.substring(0,o),a=i.substring(i.length-o);return"".concat(r).concat(s,"...").concat(a)}(n.href,t))}};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[n]),(0,f.jsx)(h.MenuItem,{ref:c,info:i,iconPosition:"left",icon:vt,shortcut:a,className:"block-editor-link-control__search-item wp-parsely-link-suggestion-link-details",children:n.title})},Nt=function(e){var t=e.link,n=e.onNext,r=e.onPrevious,i=e.onAccept,o=e.onReject,s=e.onRemove,a=e.onSelectInEditor,l=e.hasPrevious,c=e.hasNext;if(t&&void 0!==t.post_data)return(0,f.jsx)(kt,{link:t,onNext:n,onPrevious:r,onAccept:i,onReject:o,onRemove:s,onSelectInEditor:a,hasPrevious:l,hasNext:c});if(!(null==t?void 0:t.match))return(0,f.jsx)(f.Fragment,{children:(0,x.__)("This Smart Link does not have any matches in the current content.","wp-parsely")});var u=t.match.blockId,p=(0,v.select)("core/block-editor").getBlock(u),d=t.applied;return p?(0,f.jsxs)("div",{className:"smart-linking-review-suggestion",children:[(0,f.jsx)(h.KeyboardShortcuts,{shortcuts:{left:r,right:n,up:r,down:n,a:function(){t&&!t.applied&&i()},r:function(){t&&(t.applied?s():o())}}}),(0,f.jsx)(Lt,{link:t}),(0,f.jsx)("div",{className:"review-suggestion-preview",children:(0,f.jsx)(bt,{block:p,link:t})}),(0,f.jsx)(h.__experimentalDivider,{}),(0,f.jsx)(Ct,{link:t}),(0,f.jsxs)("div",{className:"review-controls",children:[(0,f.jsx)(h.Tooltip,{shortcut:"←",text:(0,x.__)("Previous","wp-parsely"),children:(0,f.jsx)(h.Button,{disabled:!l,className:"wp-parsely-review-suggestion-previous",onClick:r,icon:gt,children:(0,x.__)("Previous","wp-parsely")})}),(0,f.jsxs)("div",{className:"reviews-controls-middle",children:[!d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Reject","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:o,variant:"secondary",children:(0,x.__)("Reject","wp-parsely")})}),(0,f.jsx)(h.Tooltip,{shortcut:"A",text:(0,x.__)("Accept","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",icon:Et,onClick:i,variant:"secondary",children:(0,x.__)("Accept","wp-parsely")})})]}),d&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(h.Tooltip,{shortcut:"R",text:(0,x.__)("Remove","wp-parsely"),children:(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-reject",icon:Tt,onClick:s,variant:"secondary",children:(0,x.__)("Remove","wp-parsely")})}),(0,f.jsx)(h.Button,{className:"wp-parsely-review-suggestion-accept",onClick:a,variant:"secondary",children:(0,x.__)("Select in Editor","wp-parsely")})]})]}),(0,f.jsx)(h.Tooltip,{shortcut:"→",text:(0,x.__)("Next","wp-parsely"),children:(0,f.jsxs)(h.Button,{disabled:!c,onClick:n,className:"wp-parsely-review-suggestion-next",children:[(0,x.__)("Next","wp-parsely"),(0,f.jsx)(le,{icon:yt})]})})]})]}):(0,f.jsx)(f.Fragment,{children:(0,x.__)("No block is selected.","wp-parsely")})},At=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))},Ot=function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)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 o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((i=(i=o.trys).length>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]0&&(a=s[0],(l=a.parentNode)&&(c=document.createTextNode(null!==(u=a.textContent)&&void 0!==u?u:""),l.replaceChild(c,a),K.updateBlockAttributes(n,{content:o.innerHTML}))),[4,L(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},N=(0,_.useCallback)((function(){c(!1),w().filter((function(e){return!e.applied})).length>0?s(!0):(W.unlockPostAutosaving("smart-linking-review-modal"),t())}),[w,t]),A=function(e){s(!1),e?(c(!1),T().then((function(){N()}))):c(!0)},O=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e+1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e+1])return;S(d[t])}},I=function(){if(Ge(k)){var e=g.indexOf(k);if(!g[t=e-1])return;S(g[t])}else{var t;if(e=d.indexOf(k),!d[t=e-1])return;S(d[t])}};return(0,_.useEffect)((function(){l?W.lockPostAutosaving("smart-linking-review-modal"):l&&0===p.length&&N()}),[l,t,p,N]),(0,_.useEffect)((function(){c(n)}),[n]),(0,f.jsxs)(f.Fragment,{children:[l&&(0,f.jsx)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:N,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:(0,f.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,f.jsx)(Pt,{outboundLinks:d,inboundLinks:g,activeLink:k,setSelectedLink:S}),k&&(Ge(k)?(0,f.jsx)(kt,{link:k,onNext:O,onPrevious:I,hasNext:g.indexOf(k)0}):(0,f.jsx)(Nt,{link:k,hasNext:m().indexOf(k)0,onNext:O,onPrevious:I,onAccept:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return k.match?(r(k),[4,(i=k.match.blockId,o=k,At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return(e=document.createElement("a")).href=o.href,e.title=o.title,e.setAttribute("data-smartlink",o.uid),(t=(0,v.select)("core/block-editor").getBlock(i))?(Ue(t,o,e),o.applied=!0,[4,E(o)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),P.trackEvent("smart_linking_link_accepted",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===y().length?(N(),[2]):(e=d.indexOf(k),d[t=e+1]?S(d[t]):S(d[0]),[2])}var i,o}))}))},onReject:function(){return At(void 0,void 0,void 0,(function(){var e,t;return Ot(this,(function(n){switch(n.label){case 0:return e=d.indexOf(k),d[t=e+1]?S(d[t]):d[0]?S(d[0]):N(),[4,L(k.uid)];case 1:return n.sent(),P.trackEvent("smart_linking_link_rejected",{link:k.href,title:k.title,text:k.text,uid:k.uid}),[2]}}))}))},onRemove:function(){return At(void 0,void 0,void 0,(function(){var e,t,n,r;return Ot(this,(function(i){switch(i.label){case 0:return k.match?(e=(0,v.select)("core/block-editor").getBlock(k.match.blockId))?(t=m(),n=t.indexOf(k),r=n-1,[4,C(e,k)]):[3,2]:[2];case 1:if(i.sent(),P.trackEvent("smart_linking_link_removed",{link:k.href,title:k.title,text:k.text,uid:k.uid}),0===(t=m()).length&&g.length>0)return S(g[0]),[2];if(0===t.length&&0===g.length)return N(),[2];if(t[r])return S(t[r]),[2];S(t[0]),i.label=2;case 2:return[2]}}))}))},onSelectInEditor:function(){if(k.match){var e=(0,v.select)("core/block-editor").getBlock(k.match.blockId);if(e){K.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));t&&et(t,k.uid),P.trackEvent("smart_linking_select_in_editor_pressed",{type:"outbound",uid:k.uid}),N()}}}}))]})}),o&&(0,f.jsxs)(h.Modal,{title:(0,x.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return A(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,x.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,f.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,f.jsx)(h.Button,{variant:"secondary",onClick:function(){return A(!1)},children:(0,x.__)("Go Back","wp-parsely")}),(0,f.jsx)(h.Button,{variant:"primary",onClick:function(){return A(!0)},children:(0,x.__)("Close","wp-parsely")})]})]})]})})),Rt=function(){return Rt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&k("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ +(0,x.sprintf)((0,x.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,_.useEffect)((function(){if(!(Object.keys(I).length>0)){var e={maxLinksPerPost:a.SmartLinking.MaxLinks};ee(e)}}),[ee,a]);var pe=(0,v.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,o=t.getBlocks,s=e("core/editor"),a=s.getEditedPostContent,l=s.getCurrentPostAttribute;return{allBlocks:o(),selectedBlock:n?i(n):r(),postContent:a(),postPermalink:l("link")}}),[n]),de=pe.allBlocks,fe=pe.selectedBlock,he=pe.postContent,ve=pe.postPermalink,ge=function(e){return Bt(void 0,void 0,void 0,(function(){var t,n,r,i,o;return Mt(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,ne((n=L||!fe)?Qe.All:Qe.Selected)];case 2:return s.sent(),a=ve.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],i=function(e){return e.map((function(e){return e.href}))}(F),r.push.apply(r,i),[4,dt.getInstance().generateSmartLinks(fe&&!n?(0,Re.getBlockContent)(fe):he,O,r)];case 3:return t=s.sent(),[3,9];case 4:if((o=s.sent()).code&&o.code===U.ParselyAborted)throw o.numRetries=3-e,o;return e>0&&o.retryFetch?(console.error(o),[4,ie(!0)]):[3,8];case 5:return s.sent(),[4,oe()];case 6:return s.sent(),[4,ge(e-1)];case 7:return[2,s.sent()];case 8:throw o;case 9:return[2,t]}var a}))}))},ye=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},be=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),W.unlockPostSaving("wp-parsely-block-overlay")};return(0,f.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,f.jsx)(Be,{isDetectingEnabled:!E,onLinkRemove:function(e){!function(e){De(this,void 0,void 0,(function(){var t,n,r;return Fe(this,(function(i){switch(i.label){case 0:return[4,Ye((0,Re.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,v.dispatch)(it).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,f.jsxs)(h.PanelRow,{className:t,children:[(0,f.jsxs)("div",{className:"smart-linking-text",children:[(0,x.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/smart-linking/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),N&&(0,f.jsx)(h.Notice,{status:"info",onRemove:function(){return K(null)},className:"wp-parsely-content-helper-error",children:N.Message()}),w&&g>0&&(0,f.jsx)(h.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,x.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ +(0,x.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:A.length)}),(0,f.jsx)(lt,{disabled:T,selectedBlock:fe,onSettingChange:function(e,t){var n;p({SmartLinking:Rt(Rt({},a.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&re(t)}}),(0,f.jsx)("div",{className:"smart-linking-generate",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t,n,r,o,s,a,l;return Mt(this,(function(c){switch(c.label){case 0:return[4,$(!0)];case 1:return c.sent(),[4,ae()];case 2:return c.sent(),[4,K(null)];case 3:return c.sent(),b(!1),P.trackEvent("smart_linking_generate_pressed",{is_full_content:L,selected_block:null!==(s=null==fe?void 0:fe.name)&&void 0!==s?s:"none",context:i}),[4,ye(L?"all":null==fe?void 0:fe.clientId)];case 4:c.sent(),e=setTimeout((function(){var e;$(!1),P.trackEvent("smart_linking_generate_timeout",{is_full_content:L,selected_block:null!==(e=null==fe?void 0:fe.name)&&void 0!==e?e:"none",context:i}),me(L?"all":null==fe?void 0:fe.clientId)}),18e4),t=R,c.label=5;case 5:return c.trys.push([5,8,10,15]),[4,ge(3)];case 6:return n=c.sent(),[4,(u=n,Bt(void 0,void 0,void 0,(function(){var e;return Mt(this,(function(t){switch(t.label){case 0:return u=u.filter((function(e){return!F.some((function(t){return t.uid===e.uid&&t.applied}))})),e=ve.replace(/^https?:\/\//,"").replace(/\/+$/,""),u=(u=u.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)}))).filter((function(e){return!F.some((function(t){return t.href===e.href?(console.warn("PCH Smart Linking: Skipping duplicate link: ".concat(e.href)),!0):t.text===e.text&&t.offset!==e.offset&&(console.warn("PCH Smart Linking: Skipping duplicate link text: ".concat(e.text)),!0)}))})),u=(u=Ke(L?de:[fe],u,{}).filter((function(e){return e.match}))).filter((function(e){if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!F.some((function(r){if(!r.match)return!1;if(e.match.blockId!==r.match.blockId)return!1;var i=r.match.blockLinkPosition,o=i+r.text.length;return t>=i&&n<=o}))})),[4,Z(u)];case 1:return t.sent(),[2,u]}}))})))];case 7:if(0===c.sent().length)throw new te((0,x.__)("No smart links were generated.","wp-parsely"),U.ParselySuggestionsApiNoData,"");return ce(!0),[3,15];case 8:return r=c.sent(),o=new te(null!==(a=r.message)&&void 0!==a?a:"An unknown error has occurred.",null!==(l=r.code)&&void 0!==l?l:U.UnknownError),r.code&&r.code===U.ParselyAborted&&(o.message=(0,x.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ +(0,x.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,x._n)("attempt","attempts",r.numRetries,"wp-parsely"))),console.error(r),[4,K(o)];case 9:return c.sent(),o.createErrorSnackbar(),[3,15];case 10:return[4,$(!1)];case 11:return c.sent(),[4,ne(t)];case 12:return c.sent(),[4,ie(!1)];case 13:return c.sent(),[4,me(L?"all":null==fe?void 0:fe.clientId)];case 14:return c.sent(),clearTimeout(e),[7];case 15:return[2]}var u}))}))},variant:"primary",isBusy:T,disabled:T,children:B?(0,x.sprintf)(/* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ /* translators: %1$d: number of retry attempts, %2$d: maximum number of retries */ +(0,x.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),D,3):T?(0,x.__)("Generating Smart Links…","wp-parsely"):(0,x.__)("Add Smart Links","wp-parsely")})}),(G.length>0||V.length>0)&&(0,f.jsx)("div",{className:"smart-linking-manage",children:(0,f.jsx)(h.Button,{onClick:function(){return Bt(void 0,void 0,void 0,(function(){var e,t;return Mt(this,(function(n){switch(n.label){case 0:return[4,Je()];case 1:return e=n.sent(),t=We(),[4,Z(t)];case 2:return n.sent(),ce(!0),P.trackEvent("smart_linking_review_pressed",{num_smart_links:F.length,has_fixed_links:e,context:i}),[2]}}))}))},variant:"secondary",disabled:T,children:(0,x.__)("Review Smart Links","wp-parsely")})})]}),E&&(0,f.jsx)(It,{isOpen:E,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){b(!0),ce(!1)}})]})},Gt=function(){return Gt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0)&&(t(),e())}))}))]}))},new((n=void 0)||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}));var e,t,n,r}().then((function(){var t=document.querySelector(".wp-block-post-content");et(t,e)}))})))},Xt=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M7 11.5h10V13H7z"})}),en=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M13 19h-2v-2h2v2zm0-6h-2v-2h2v2zm0-6h-2V5h2v2z"})}),tn=function(e){var t=e.title,n=e.icon,r=e.subtitle,i=e.level,o=void 0===i?2:i,s=e.children,a=e.controls,l=e.onClick,c=e.isOpen,u=e.isLoading,p=e.dropdownChildren;return(0,f.jsxs)("div",{className:"performance-stat-panel",children:[(0,f.jsxs)(h.__experimentalHStack,{className:"panel-header level-"+o,children:[(0,f.jsx)(h.__experimentalHeading,{level:o,children:t}),r&&!c&&(0,f.jsx)("span",{className:"panel-subtitle",children:r}),a&&!p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",controls:a}),p&&(0,f.jsx)(h.DropdownMenu,{icon:n,label:(0,x.__)("Settings","wp-parsely"),className:"panel-settings-button",children:p}),n&&!p&&!a&&(0,f.jsx)(h.Button,{icon:n,className:"panel-settings-button",isPressed:c,onClick:l})]}),(0,f.jsx)("div",{className:"panel-body",children:u?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):s})]})};function nn(e,t,n){void 0===t&&(t=1),void 0===n&&(n="");var r=parseInt(e.replace(/\D/g,""),10);if(r<1e3)return e;r<1e4&&(t=1);var i=r,o=r.toString(),s="",a=0;return Object.entries({1e3:"k","1,000,000":"M","1,000,000,000":"B","1,000,000,000,000":"T","1,000,000,000,000,000":"Q"}).forEach((function(e){var n=e[0],l=e[1],c=parseInt(n.replace(/\D/g,""),10);if(r>=c){var u=t;(i=r/c)%1>1/a&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,o=i.toFixed(u),s=l}a=c})),o+n+s}var rn=function(e){var t=e.data,n=e.isLoading,r=(0,_.useState)(w.Views),i=r[0],o=r[1],s=(0,_.useState)(!1),a=s[0],l=s[1];n||delete t.referrers.types.totals;var c=function(e){switch(e){case"social":return(0,x.__)("Social","wp-parsely");case"search":return(0,x.__)("Search","wp-parsely");case"other":return(0,x.__)("Other","wp-parsely");case"internal":return(0,x.__)("Internal","wp-parsely");case"direct":return(0,x.__)("Direct","wp-parsely")}return e},u=(0,x.sprintf)((0,x.__)("By %s","wp-parsely"),G(i)); /* translators: %s: metric description */return(0,f.jsxs)(tn,{title:(0,x.__)("Categories","wp-parsely"),level:3,subtitle:u,isOpen:a,onClick:function(){return l(!a)},children:[a&&(0,f.jsx)("div",{className:"panel-settings",children:(0,f.jsx)(h.SelectControl,{value:i,prefix:(0,x.__)("By:","wp-parsely"),onChange:function(e){F(e,w)&&o(e)},children:Object.values(w).map((function(e){return(0,f.jsxs)("option",{value:e,disabled:"avg_engaged"===e,children:[G(e),"avg_engaged"===e&&" "+(0,x.__)("(coming soon)","wp-parsely")]},e)}))})}),n?(0,f.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,f.jsx)(h.Spinner,{})}):(0,f.jsxs)("div",{children:[(0,f.jsx)("div",{className:"multi-percentage-bar",children:Object.entries(t.referrers.types).map((function(e){var t=e[0],n=e[1],r=(0,x.sprintf)(/* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ /* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ (0,x.__)("%1$s: %2$s%%","wp-parsely"),c(t),n.viewsPercentage);return(0,f.jsx)(h.Tooltip /* translators: %s: percentage value */,{ @@ -14,18 +14,18 @@ text:"".concat(c(t)," - ").concat((0,x.sprintf)((0,x.__)("%s%%","wp-parsely"),n.viewsPercentage)),delay:150,children:(0,f.jsx)("div",{"aria-label":r,className:"bar-fill "+t,style:{width:n.viewsPercentage+"%"}})},t)}))}),(0,f.jsx)("div",{className:"percentage-bar-labels",children:Object.entries(t.referrers.types).map((function(e){var t=e[0],n=e[1];return(0,f.jsxs)("div",{className:"single-label "+t,children:[(0,f.jsx)("div",{className:"label-color "+t}),(0,f.jsx)("div",{className:"label-text",children:c(t)}),(0,f.jsx)("div",{className:"label-value",children:nn(n.views)})]},t)}))})]})]})},on=(0,f.jsx)(k.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(k.Path,{d:"M3.99961 13C4.67043 13.3354 4.6703 13.3357 4.67017 13.3359L4.67298 13.3305C4.67621 13.3242 4.68184 13.3135 4.68988 13.2985C4.70595 13.2686 4.7316 13.2218 4.76695 13.1608C4.8377 13.0385 4.94692 12.8592 5.09541 12.6419C5.39312 12.2062 5.84436 11.624 6.45435 11.0431C7.67308 9.88241 9.49719 8.75 11.9996 8.75C14.502 8.75 16.3261 9.88241 17.5449 11.0431C18.1549 11.624 18.6061 12.2062 18.9038 12.6419C19.0523 12.8592 19.1615 13.0385 19.2323 13.1608C19.2676 13.2218 19.2933 13.2686 19.3093 13.2985C19.3174 13.3135 19.323 13.3242 19.3262 13.3305L19.3291 13.3359C19.3289 13.3357 19.3288 13.3354 19.9996 13C20.6704 12.6646 20.6703 12.6643 20.6701 12.664L20.6697 12.6632L20.6688 12.6614L20.6662 12.6563L20.6583 12.6408C20.6517 12.6282 20.6427 12.6108 20.631 12.5892C20.6078 12.5459 20.5744 12.4852 20.5306 12.4096C20.4432 12.2584 20.3141 12.0471 20.1423 11.7956C19.7994 11.2938 19.2819 10.626 18.5794 9.9569C17.1731 8.61759 14.9972 7.25 11.9996 7.25C9.00203 7.25 6.82614 8.61759 5.41987 9.9569C4.71736 10.626 4.19984 11.2938 3.85694 11.7956C3.68511 12.0471 3.55605 12.2584 3.4686 12.4096C3.42484 12.4852 3.39142 12.5459 3.36818 12.5892C3.35656 12.6108 3.34748 12.6282 3.34092 12.6408L3.33297 12.6563L3.33041 12.6614L3.32948 12.6632L3.32911 12.664C3.32894 12.6643 3.32879 12.6646 3.99961 13ZM11.9996 16C13.9326 16 15.4996 14.433 15.4996 12.5C15.4996 10.567 13.9326 9 11.9996 9C10.0666 9 8.49961 10.567 8.49961 12.5C8.49961 14.433 10.0666 16 11.9996 16Z"})}),sn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})}),an=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M12 4V2.2L9 4.8l3 2.5V5.5c3.6 0 6.5 2.9 6.5 6.5 0 2.9-1.9 5.3-4.5 6.2v.2l-.1-.2c-.4.1-.7.2-1.1.2l.2 1.5c.3 0 .6-.1 1-.2 3.5-.9 6-4 6-7.7 0-4.4-3.6-8-8-8zm-7.9 7l1.5.2c.1-1.2.5-2.3 1.2-3.2l-1.1-.9C4.8 8.2 4.3 9.6 4.1 11zm1.5 1.8l-1.5.2c.1.7.3 1.4.5 2 .3.7.6 1.3 1 1.8l1.2-.8c-.3-.5-.6-1-.8-1.5s-.4-1.1-.4-1.7zm1.5 5.5c1.1.9 2.4 1.4 3.8 1.6l.2-1.5c-1.1-.1-2.2-.5-3.1-1.2l-.9 1.1z"})}),ln=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M11 13h2v-2h-2v2zm-6 0h2v-2H5v2zm12-2v2h2v-2h-2z"})}),cn=function(){return cn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]1?[2,Promise.reject(new te((0,x.sprintf)(/* translators: URL of the published post */ /* translators: URL of the published post */ -(0,x.__)("Multiple results were returned for the post %d by the Parse.ly API.","wp-parsely"),t),U.ParselyApiReturnedTooManyResults))]:[2,n[0]]}}))}))},t.prototype.fetchReferrerDataFromWpEndpoint=function(e,t,n){return xn(this,void 0,void 0,(function(){return kn(this,(function(r){switch(r.label){case 0:return[4,this.fetch({path:(0,ne.addQueryArgs)("/wp-parsely/v2/stats/post/".concat(t,"/referrers"),bn(bn({},mn(e)),{itm_source:this.itmSource,total_views:n}))})];case 1:return[2,r.sent()]}}))}))},t}(re),jn=function(){return jn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return t.sent(),[4,n(r-1)];case 2:return t.sent(),[3,4];case 3:a(e),i(!1),t.label=4;case 4:return[2]}}))}))})),[2]}))}))};return i(!0),n(1),function(){a(void 0)}}),[t]),(0,f.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,f.jsx)(tn,{title:(0,x.__)("Performance Stats","wp-parsely"),icon:en,dropdownChildren:function(e){var t=e.onClose;return(0,f.jsx)(Nn,{onClose:t})},children:(0,f.jsx)("div",{className:"panel-settings",children:(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:d.PerformanceStats.Period,prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Period:","wp-parsely")}),onChange:function(e){F(e,m)&&(v({PerformanceStats:jn(jn({},d.PerformanceStats),{Period:e})}),P.trackEvent("editor_sidebar_performance_period_changed",{period:e}))},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})})}),s?s.Message():(0,f.jsxs)(f.Fragment,{children:[Cn(d,"overview")&&(0,f.jsx)(gn,{data:c,isLoading:r}),Cn(d,"categories")&&(0,f.jsx)(rn,{data:c,isLoading:r}),Cn(d,"referrers")&&(0,f.jsx)(yn,{data:c,isLoading:r})]}),window.wpParselyPostUrl&&(0,f.jsx)(h.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){P.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,x.__)("View this in Parse.ly","wp-parsely")})]})},On=function(e){var t=e.period;return(0,f.jsx)(h.Panel,{children:(0,f.jsx)(Ie,{children:(0,f.jsx)(An,{period:t})})})},In=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Tag,label:(0,x.__)("Tag","wp-parsely")}),r.categories.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Section,label:(0,x.__)("Section","wp-parsely")}),r.authors.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Author,label:(0,x.__)("Author","wp-parsely")})]})})},Bn=function(e){var t=e.filter,n=e.label,r=e.postData,i=In(e,["filter","label","postData"]);return(0,f.jsx)("div",{className:"related-posts-filter-values",children:(0,f.jsx)(h.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return i.onFilterValueChange(e)},options:b.Tag===t.type?r.tags.map((function(e){return{value:e,label:e}})):b.Section===t.type?r.categories.map((function(e){return{value:e,label:e}})):b.Author===t.type?r.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},Mn=function(e){var t=e.filter,n=e.postData,r=e.label,i=In(e,["filter","postData","label"]),o=function(){return n.authors.length>0&&n.categories.length>0||n.authors.length>0&&n.tags.length>0||n.tags.length>0&&n.categories.length>0},s=function(){return b.Tag===t.type&&n.tags.length>1||b.Section===t.type&&n.categories.length>1||b.Author===t.type&&n.authors.length>1};return o()||s()?(0,f.jsxs)("div",{className:"related-posts-filter-settings",children:[o()&&(0,f.jsx)(Rn,{filter:t,label:r,onFilterTypeChange:i.onFilterTypeChange,postData:n}),s()&&(0,f.jsx)(Bn,{filter:t,label:o()?void 0:r,onFilterValueChange:i.onFilterValueChange,postData:n})]}):null},Dn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"})}),Fn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5.625 5.5h9.75c.069 0 .125.056.125.125v9.75a.125.125 0 0 1-.125.125h-9.75a.125.125 0 0 1-.125-.125v-9.75c0-.069.056-.125.125-.125ZM4 5.625C4 4.728 4.728 4 5.625 4h9.75C16.273 4 17 4.728 17 5.625v9.75c0 .898-.727 1.625-1.625 1.625h-9.75A1.625 1.625 0 0 1 4 15.375v-9.75Zm14.5 11.656v-9H20v9C20 18.8 18.77 20 17.251 20H6.25v-1.5h11.001c.69 0 1.249-.528 1.249-1.219Z"})}),Vn=function(){return(0,f.jsx)(h.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,f.jsx)(h.Rect,{width:"1",height:"40",fill:"#cccccc"})})};function Gn(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Number of Views","wp-parsely")}),i,nn(n.views.toString())]}):"avg_engaged"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,f.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var Hn,zn=function(e){var t,n,r=e.metric,i=e.post,o=e.postContent,s=(0,v.useDispatch)("core/notices").createNotice,a=o&&(t=o,n=Ae(i.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,f.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,f.jsx)("div",{className:"related-post-title",children:(0,f.jsxs)("a",{href:i.url,target:"_blank",rel:"noreferrer",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("View on website (opens new tab)","wp-parsely")}),i.title]})}),(0,f.jsx)("div",{className:"related-post-actions",children:(0,f.jsxs)("div",{className:"related-post-info",children:[(0,f.jsxs)("div",{children:[(0,f.jsx)("div",{className:"related-post-metric",children:(0,f.jsx)(Gn,{metric:r,post:i,viewsIcon:(0,f.jsx)(le,{icon:on}),avgEngagedIcon:(0,f.jsx)(h.Dashicon,{icon:"clock",size:24})})}),a&&(0,f.jsx)("div",{className:"related-post-linked",children:(0,f.jsx)(h.Tooltip,{text:(0,x.__)("This post is linked in the content","wp-parsely"),children:(0,f.jsx)(le,{icon:Dn,size:24})})})]}),(0,f.jsx)(Vn,{}),(0,f.jsxs)("div",{children:[(0,f.jsx)(h.Button,{icon:Fn,iconSize:24,onClick:function(){navigator.clipboard.writeText(i.rawUrl).then((function(){s("success",(0,x.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,x.__)("Copy URL to clipboard","wp-parsely")}),(0,f.jsx)(h.Button,{icon:(0,f.jsx)(E,{}),iconSize:18,href:i.dashUrl,target:"_blank",label:(0,x.__)("View in Parse.ly","wp-parsely")})]})]})})]})},Un=window.wp.coreData,qn=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)}}(),$n=function(){return $n=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return t.sent(),[4,n(r-1)];case 2:return t.sent(),[3,4];case 3:a(e),i(!1),t.label=4;case 4:return[2]}}))}))})),[2]}))}))};return i(!0),n(1),function(){a(void 0)}}),[t]),(0,f.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,f.jsx)(tn,{title:(0,x.__)("Performance Stats","wp-parsely"),icon:en,dropdownChildren:function(e){var t=e.onClose;return(0,f.jsx)(Nn,{onClose:t})},children:(0,f.jsx)("div",{className:"panel-settings",children:(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:d.PerformanceStats.Period,prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Period:","wp-parsely")}),onChange:function(e){F(e,m)&&(v({PerformanceStats:jn(jn({},d.PerformanceStats),{Period:e})}),P.trackEvent("editor_sidebar_performance_period_changed",{period:e}))},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})})}),s?s.Message():(0,f.jsxs)(f.Fragment,{children:[Cn(d,"overview")&&(0,f.jsx)(gn,{data:c,isLoading:r}),Cn(d,"categories")&&(0,f.jsx)(rn,{data:c,isLoading:r}),Cn(d,"referrers")&&(0,f.jsx)(yn,{data:c,isLoading:r})]}),window.wpParselyPostUrl&&(0,f.jsx)(h.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){P.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,x.__)("View this in Parse.ly","wp-parsely")})]})},On=function(e){var t=e.period;return(0,f.jsx)(h.Panel,{children:(0,f.jsx)(Ie,{children:(0,f.jsx)(An,{period:t})})})},In=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Tag,label:(0,x.__)("Tag","wp-parsely")}),r.categories.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Section,label:(0,x.__)("Section","wp-parsely")}),r.authors.length>=1&&(0,f.jsx)(h.__experimentalToggleGroupControlOption,{value:b.Author,label:(0,x.__)("Author","wp-parsely")})]})})},Bn=function(e){var t=e.filter,n=e.label,r=e.postData,i=In(e,["filter","label","postData"]);return(0,f.jsx)("div",{className:"related-posts-filter-values",children:(0,f.jsx)(h.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return i.onFilterValueChange(e)},options:b.Tag===t.type?r.tags.map((function(e){return{value:e,label:e}})):b.Section===t.type?r.categories.map((function(e){return{value:e,label:e}})):b.Author===t.type?r.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},Mn=function(e){var t=e.filter,n=e.postData,r=e.label,i=In(e,["filter","postData","label"]),o=function(){return n.authors.length>0&&n.categories.length>0||n.authors.length>0&&n.tags.length>0||n.tags.length>0&&n.categories.length>0},s=function(){return b.Tag===t.type&&n.tags.length>1||b.Section===t.type&&n.categories.length>1||b.Author===t.type&&n.authors.length>1};return o()||s()?(0,f.jsxs)("div",{className:"related-posts-filter-settings",children:[o()&&(0,f.jsx)(Rn,{filter:t,label:r,onFilterTypeChange:i.onFilterTypeChange,postData:n}),s()&&(0,f.jsx)(Bn,{filter:t,label:o()?void 0:r,onFilterValueChange:i.onFilterValueChange,postData:n})]}):null},Dn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"})}),Fn=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5.625 5.5h9.75c.069 0 .125.056.125.125v9.75a.125.125 0 0 1-.125.125h-9.75a.125.125 0 0 1-.125-.125v-9.75c0-.069.056-.125.125-.125ZM4 5.625C4 4.728 4.728 4 5.625 4h9.75C16.273 4 17 4.728 17 5.625v9.75c0 .898-.727 1.625-1.625 1.625h-9.75A1.625 1.625 0 0 1 4 15.375v-9.75Zm14.5 11.656v-9H20v9C20 18.8 18.77 20 17.251 20H6.25v-1.5h11.001c.69 0 1.249-.528 1.249-1.219Z"})}),Vn=function(){return(0,f.jsx)(h.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,f.jsx)(h.Rect,{width:"1",height:"40",fill:"#cccccc"})})};function Gn(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Number of Views","wp-parsely")}),i,nn(n.views.toString())]}):"avg_engaged"===t?(0,f.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,f.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var Hn,zn=function(e){var t,n,r=e.metric,i=e.post,o=e.postContent,s=(0,v.useDispatch)("core/notices").createNotice,a=o&&(t=o,n=Ae(i.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,f.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,f.jsx)("div",{className:"related-post-title",children:(0,f.jsxs)("a",{href:i.url,target:"_blank",rel:"noreferrer",children:[(0,f.jsx)("span",{className:"screen-reader-text",children:(0,x.__)("View on website (opens new tab)","wp-parsely")}),i.title]})}),(0,f.jsx)("div",{className:"related-post-actions",children:(0,f.jsxs)("div",{className:"related-post-info",children:[(0,f.jsxs)("div",{children:[(0,f.jsx)("div",{className:"related-post-metric",children:(0,f.jsx)(Gn,{metric:r,post:i,viewsIcon:(0,f.jsx)(le,{icon:on}),avgEngagedIcon:(0,f.jsx)(h.Dashicon,{icon:"clock",size:24})})}),a&&(0,f.jsx)("div",{className:"related-post-linked",children:(0,f.jsx)(h.Tooltip,{text:(0,x.__)("This post is linked in the content","wp-parsely"),children:(0,f.jsx)(le,{icon:Dn,size:24})})})]}),(0,f.jsx)(Vn,{}),(0,f.jsxs)("div",{children:[(0,f.jsx)(h.Button,{icon:Fn,iconSize:24,onClick:function(){navigator.clipboard.writeText(i.rawUrl).then((function(){s("success",(0,x.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,x.__)("Copy URL to clipboard","wp-parsely")}),(0,f.jsx)(h.Button,{icon:(0,f.jsx)(E,{}),iconSize:18,href:i.dashUrl,target:"_blank",label:(0,x.__)("View in Parse.ly","wp-parsely")})]})]})})]})},Un=window.wp.coreData,qn=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)}}(),$n=function(){return $n=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]0&&f.every(Number.isInteger)?null!==(n=l("taxonomy","category",{include:f,context:"view"}))&&void 0!==n?n:void 0:null,tagRecords:s=Array.isArray(h)&&h.length>0&&h.every(Number.isInteger)?null!==(r=l("taxonomy","post_tag",{include:h,context:"view"}))&&void 0!==r?r:void 0:null,isLoading:u("getEntityRecords",["root","user",{include:[d],context:"view"}])||u("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||u("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}]),hasResolved:(c("getEntityRecords",["root","user",{include:[d],context:"view"}])||null===i)&&(c("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||null===o)&&(c("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}])||null===s)}}),[]);return(0,_.useEffect)((function(){var e=r.authorRecords,t=r.categoryRecords,i=r.tagRecords,o=r.isLoading;r.hasResolved&&!o&&n({authors:e,categories:t,tags:i,isReady:!0})}),[r]),t}(),c=l.authors,u=l.categories,p=l.tags,d=l.isReady;(0,_.useEffect)((function(){if(d){var e=function(e){return function(e){return!(!Array.isArray(e)||0===e.length)&&e.every((function(e){return"name"in e&&"id"in e&&"slug"in e&&"description"in e&&"link"in e}))}(e)?e.map((function(e){return e.name})):[]};a({authors:e(c),categories:e(u),tags:e(p)})}}),[c,u,p,d]);var g=(0,_.useState)(!0),y=g[0],k=g[1],S=(0,_.useState)(),j=S[0],T=S[1],E=(0,_.useState)(),L=E[0],C=E[1],N=(0,_.useState)([]),A=N[0],O=N[1],I=(0,_.useState)({type:t.RelatedPosts.FilterBy,value:t.RelatedPosts.FilterValue}),R=I[0],B=I[1],D=(0,_.useState)(void 0),H=D[0],z=D[1],U=(0,se.useDebounce)(z,1e3);(0,v.useSelect)((function(e){if("undefined"==typeof jest){var t=e("core/editor").getEditedPostContent;U(t())}else U("Jest test is running")}),[U]);var q=function(e,r){n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{FilterBy:e,FilterValue:r})})};return(0,_.useEffect)((function(){var e,t,n=function(e){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(t){return Kn.getInstance().getRelatedPosts(r,i,R).then((function(e){O(e.posts),C(e.message),k(!1)})).catch((function(t){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(r){switch(r.label){case 0:return e>0&&t.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,n(e-1)];case 2:return r.sent(),[3,4];case 3:k(!1),T(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},o=b.Author===R.type,a=b.Tag===R.type,l=b.Section===R.type,c=b.Unavailable===R.type,u=0===s.authors.length,p=0===s.tags.length,d=0===s.categories.length,f=o&&!s.authors.includes(R.value),h=a&&!s.tags.includes(R.value),v=l&&!s.categories.includes(R.value);return k(!0),c||a&&p||l&&d||o&&u?Object.values(s).every((function(e){return 0===e.length}))||B((e="",t=b.Unavailable,s.tags.length>=1?(t=b.Tag,e=s.tags[0]):s.categories.length>=1?(t=b.Section,e=s.categories[0]):s.authors.length>=1&&(t=b.Author,e=s.authors[0]),{type:t,value:e})):h?B({type:b.Tag,value:s.tags[0]}):v?B({type:b.Section,value:s.categories[0]}):f?B({type:b.Author,value:s.authors[0]}):n(1),function(){k(!1),O([]),C(""),T(void 0)}}),[r,i,R,s]),0===s.authors.length&&0===s.categories.length&&0===s.tags.length&&d?(0,f.jsx)("div",{className:"wp-parsely-related-posts",children:(0,f.jsx)("div",{className:"related-posts-body",children:(0,x.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,f.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,f.jsx)("div",{className:"related-posts-description",children:(0,x.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,f.jsxs)("div",{className:"related-posts-body",children:[(0,f.jsxs)("div",{className:"related-posts-settings",children:[(0,f.jsx)(h.SelectControl,{size:"__unstable-large",onChange:function(e){var r;F(r=e,w)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Metric:r})}),P.trackEvent("related_posts_metric_changed",{metric:r}))},prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Metric:","wp-parsely")}),value:i,children:Object.values(w).map((function(e){return(0,f.jsx)("option",{value:e,children:G(e)},e)}))}),(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:r,prefix:(0,f.jsxs)(h.__experimentalInputControlPrefixWrapper,{children:[(0,x.__)("Period:","wp-parsely")," "]}),onChange:function(e){return function(e){F(e,m)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Period:e})}),P.trackEvent("related_posts_period_changed",{period:e}))}(e)},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})]}),(0,f.jsx)(Mn,{label:(0,x.__)("Filter by","wp-parsely"),filter:R,onFilterTypeChange:function(e){if(F(e,b)){var t="",n=e;b.Tag===n&&(t=s.tags[0]),b.Section===n&&(t=s.categories[0]),b.Author===n&&(t=s.authors[0]),""!==t&&(q(n,t),B({type:n,value:t}),P.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(q(R.type,e),B(Yn(Yn({},R),{value:e})))},postData:s}),(0,f.jsxs)("div",{className:"related-posts-wrapper",children:[(0,f.jsx)("div",{children:(0,f.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:b.Tag===R.type?(0,x.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ +message:(0,x.sprintf)((0,x.__)('by author "%1$s"',"wp-parsely"),n.value)};throw new te((0,x.__)("No valid filter type has been specified.","wp-parsely"),U.CannotFormulateApiQuery)},t}(re),Yn=function(){return Yn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&f.every(Number.isInteger)?null!==(n=l("taxonomy","category",{include:f,context:"view"}))&&void 0!==n?n:void 0:null,tagRecords:s=Array.isArray(h)&&h.length>0&&h.every(Number.isInteger)?null!==(r=l("taxonomy","post_tag",{include:h,context:"view"}))&&void 0!==r?r:void 0:null,isLoading:u("getEntityRecords",["root","user",{include:[d],context:"view"}])||u("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||u("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}]),hasResolved:(c("getEntityRecords",["root","user",{include:[d],context:"view"}])||null===i)&&(c("getEntityRecords",["taxonomy","category",{include:f,context:"view"}])||null===o)&&(c("getEntityRecords",["taxonomy","post_tag",{include:h,context:"view"}])||null===s)}}),[]);return(0,_.useEffect)((function(){var e=r.authorRecords,t=r.categoryRecords,i=r.tagRecords,o=r.isLoading;r.hasResolved&&!o&&n({authors:e,categories:t,tags:i,isReady:!0})}),[r]),t}(),c=l.authors,u=l.categories,p=l.tags,d=l.isReady;(0,_.useEffect)((function(){if(d){var e=function(e){return function(e){return!(!Array.isArray(e)||0===e.length)&&e.every((function(e){return"name"in e&&"id"in e&&"slug"in e&&"description"in e&&"link"in e}))}(e)?e.map((function(e){return e.name})):[]};a({authors:e(c),categories:e(u),tags:e(p)})}}),[c,u,p,d]);var g=(0,_.useState)(!0),y=g[0],k=g[1],S=(0,_.useState)(),j=S[0],T=S[1],E=(0,_.useState)(),L=E[0],C=E[1],N=(0,_.useState)([]),A=N[0],O=N[1],I=(0,_.useState)({type:t.RelatedPosts.FilterBy,value:t.RelatedPosts.FilterValue}),R=I[0],B=I[1],D=(0,_.useState)(void 0),H=D[0],z=D[1],U=(0,se.useDebounce)(z,1e3);(0,v.useSelect)((function(e){if("undefined"==typeof jest){var t=e("core/editor").getEditedPostContent;U(t())}else U("Jest test is running")}),[U]);var q=function(e,r){n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{FilterBy:e,FilterValue:r})})};return(0,_.useEffect)((function(){var e,t,n=function(e){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(t){return Zn.getInstance().getRelatedPosts(r,i,R).then((function(e){O(e.posts),C(e.message),k(!1)})).catch((function(t){return Jn(void 0,void 0,void 0,(function(){return Qn(this,(function(r){switch(r.label){case 0:return e>0&&t.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return r.sent(),[4,n(e-1)];case 2:return r.sent(),[3,4];case 3:k(!1),T(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},o=b.Author===R.type,a=b.Tag===R.type,l=b.Section===R.type,c=b.Unavailable===R.type,u=0===s.authors.length,p=0===s.tags.length,d=0===s.categories.length,f=o&&!s.authors.includes(R.value),h=a&&!s.tags.includes(R.value),v=l&&!s.categories.includes(R.value);return k(!0),c||a&&p||l&&d||o&&u?Object.values(s).every((function(e){return 0===e.length}))||B((e="",t=b.Unavailable,s.tags.length>=1?(t=b.Tag,e=s.tags[0]):s.categories.length>=1?(t=b.Section,e=s.categories[0]):s.authors.length>=1&&(t=b.Author,e=s.authors[0]),{type:t,value:e})):h?B({type:b.Tag,value:s.tags[0]}):v?B({type:b.Section,value:s.categories[0]}):f?B({type:b.Author,value:s.authors[0]}):n(1),function(){k(!1),O([]),C(""),T(void 0)}}),[r,i,R,s]),0===s.authors.length&&0===s.categories.length&&0===s.tags.length&&d?(0,f.jsx)("div",{className:"wp-parsely-related-posts",children:(0,f.jsx)("div",{className:"related-posts-body",children:(0,x.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,f.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,f.jsx)("div",{className:"related-posts-description",children:(0,x.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,f.jsxs)("div",{className:"related-posts-body",children:[(0,f.jsxs)("div",{className:"related-posts-settings",children:[(0,f.jsx)(h.SelectControl,{size:"__unstable-large",onChange:function(e){var r;F(r=e,w)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Metric:r})}),P.trackEvent("related_posts_metric_changed",{metric:r}))},prefix:(0,f.jsx)(h.__experimentalInputControlPrefixWrapper,{children:(0,x.__)("Metric:","wp-parsely")}),value:i,children:Object.values(w).map((function(e){return(0,f.jsx)("option",{value:e,children:G(e)},e)}))}),(0,f.jsx)(h.SelectControl,{size:"__unstable-large",value:r,prefix:(0,f.jsxs)(h.__experimentalInputControlPrefixWrapper,{children:[(0,x.__)("Period:","wp-parsely")," "]}),onChange:function(e){return function(e){F(e,m)&&(n({RelatedPosts:Yn(Yn({},t.RelatedPosts),{Period:e})}),P.trackEvent("related_posts_period_changed",{period:e}))}(e)},children:Object.values(m).map((function(e){return(0,f.jsx)("option",{value:e,children:V(e)},e)}))})]}),(0,f.jsx)(Mn,{label:(0,x.__)("Filter by","wp-parsely"),filter:R,onFilterTypeChange:function(e){if(F(e,b)){var t="",n=e;b.Tag===n&&(t=s.tags[0]),b.Section===n&&(t=s.categories[0]),b.Author===n&&(t=s.authors[0]),""!==t&&(q(n,t),B({type:n,value:t}),P.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(q(R.type,e),B(Yn(Yn({},R),{value:e})))},postData:s}),(0,f.jsxs)("div",{className:"related-posts-wrapper",children:[(0,f.jsx)("div",{children:(0,f.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:b.Tag===R.type?(0,x.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ (0,x.__)("Top related posts with the “%1$s” tag in the %2$s.","wp-parsely"),R.value,V(r,!0)):b.Section===R.type?(0,x.sprintf)(/* translators: 1: section name, 2: period */ /* translators: 1: section name, 2: period */ (0,x.__)("Top related posts in the “%1$s” section in the %2$s.","wp-parsely"),R.value,V(r,!0)):b.Author===R.type?(0,x.sprintf)(/* translators: 1: author name, 2: period */ /* translators: 1: author name, 2: period */ (0,x.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),R.value,V(r,!0)):null!=L?L:""})}),j&&j.Message(),y&&(0,f.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,x.__)("Loading…","wp-parsely")}),!y&&!j&&0===A.length&&(0,f.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,x.__)("No related posts found.","wp-parsely")}),!y&&A.length>0&&(0,f.jsx)("div",{className:"related-posts-list",children:A.map((function(e){return(0,f.jsx)(zn,{metric:i,post:e,postContent:H},e.id)}))})]})]})]})},er=(0,f.jsx)(k.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(k.Path,{d:"M10.97 10.159a3.382 3.382 0 0 0-2.857.955l1.724 1.723-2.836 2.913L7 17h1.25l2.913-2.837 1.723 1.723a3.38 3.38 0 0 0 .606-.825c.33-.63.446-1.343.35-2.032L17 10.695 13.305 7l-2.334 3.159Z"})}),tr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"M18.3 11.7c-.6-.6-1.4-.9-2.3-.9H6.7l2.9-3.3-1.1-1-4.5 5L8.5 16l1-1-2.7-2.7H16c.5 0 .9.2 1.3.5 1 1 1 3.4 1 4.5v.3h1.5v-.2c0-1.5 0-4.3-1.5-5.7z"})}),nr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 5.5A2.25 2.25 0 0 0 9.878 7h4.244A2.251 2.251 0 0 0 12 5.5ZM12 4a3.751 3.751 0 0 0-3.675 3H5v1.5h1.27l.818 8.997a2.75 2.75 0 0 0 2.739 2.501h4.347a2.75 2.75 0 0 0 2.738-2.5L17.73 8.5H19V7h-3.325A3.751 3.751 0 0 0 12 4Zm4.224 4.5H7.776l.806 8.861a1.25 1.25 0 0 0 1.245 1.137h4.347a1.25 1.25 0 0 0 1.245-1.137l.805-8.861Z"})}),rr=(0,f.jsx)(k.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(k.Path,{d:"m21.5 9.1-6.6-6.6-4.2 5.6c-1.2-.1-2.4.1-3.6.7-.1 0-.1.1-.2.1-.5.3-.9.6-1.2.9l3.7 3.7-5.7 5.7v1.1h1.1l5.7-5.7 3.7 3.7c.4-.4.7-.8.9-1.2.1-.1.1-.2.2-.3.6-1.1.8-2.4.6-3.6l5.6-4.1zm-7.3 3.5.1.9c.1.9 0 1.8-.4 2.6l-6-6c.8-.4 1.7-.5 2.6-.4l.9.1L15 4.9 19.1 9l-4.9 3.6z"})}),ir=function(){return ir=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=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]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]0?(0,f.jsx)("span",{className:"parsely-write-titles-text",children:(0,_.createInterpolateElement)( // translators: %1$s is the tone, %2$s is the persona. // translators: %1$s is the tone, %2$s is the persona. -(0,x.__)("We've generated a few titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,f.jsx)("strong",{children:me(a)}),persona:(0,f.jsx)("strong",{children:de(u)})})}):(0,x.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,f.jsx)(pr,{title:k,type:Hn.PostTitle,isOriginal:!0}),00&&(0,f.jsx)(dr,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,f.jsx)(hr,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,f.jsx)(fr,{isLoading:g,onPersonaChange:function(e){N("Persona",e),p(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,f.jsx)("div",{className:"title-suggestions-generate",children:(0,f.jsxs)(h.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return mr(void 0,void 0,void 0,(function(){return wr(this,(function(e){switch(e.label){case 0:return o(void 0),!1!==g?[3,2]:(P.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=Hn.PostTitle,n=A,r=a,i=u,mr(void 0,void 0,void 0,(function(){var e,s,a;return wr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=gr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=l.sent(),[4,j(t,s)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),o(a),j(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,x.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,x.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,x.__)("Generate Titles","wp-parsely")]})})]})})},_r=function(){return _r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,f.jsx)("strong",{children:me(a)}),persona:(0,f.jsx)("strong",{children:de(u)})})}):(0,x.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,f.jsxs)(h.Button,{href:"https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/",target:"_blank",variant:"link",children:[(0,x.__)("Learn more about Parse.ly AI","wp-parsely"),(0,f.jsx)(le,{icon:Y,size:18,className:"parsely-external-link-icon"})]})]}),i&&(0,f.jsx)(h.Notice,{className:"wp-parsely-content-helper-error",onRemove:function(){return o(void 0)},status:"info",children:i.Message()}),void 0!==k&&(0,f.jsx)(pr,{title:k,type:Hn.PostTitle,isOriginal:!0}),00&&(0,f.jsx)(dr,{pinnedTitles:m,isOpen:!0}),y.length>0&&(0,f.jsx)(hr,{suggestions:y,isOpen:!0,isLoading:g})]}),(0,f.jsx)(fr,{isLoading:g,onPersonaChange:function(e){N("Persona",e),p(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),l(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,f.jsx)("div",{className:"title-suggestions-generate",children:(0,f.jsxs)(h.Button,{variant:"primary",isBusy:g,disabled:g||"custom"===a||"custom"===u,onClick:function(){return mr(void 0,void 0,void 0,(function(){return wr(this,(function(e){switch(e.label){case 0:return o(void 0),!1!==g?[3,2]:(P.trackEvent("title_suggestions_generate_pressed",{request_more:y.length>0,total_titles:y.length,total_pinned:y.filter((function(e){return e.isPinned})).length,tone:a,persona:u}),[4,(t=Hn.PostTitle,n=A,r=a,i=u,mr(void 0,void 0,void 0,(function(){var e,s,a;return wr(this,(function(l){switch(l.label){case 0:return[4,T(!0)];case 1:l.sent(),e=gr.getInstance(),l.label=2;case 2:return l.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=l.sent(),[4,j(t,s)];case 4:return l.sent(),[3,6];case 5:return a=l.sent(),o(a),j(t,[]),[3,6];case 6:return[4,T(!1)];case 7:return l.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[g&&(0,x.__)("Generating Titles…","wp-parsely"),!g&&w.length>0&&(0,x.__)("Generate More","wp-parsely"),!g&&0===w.length&&(0,x.__)("Generate Titles","wp-parsely")]})})]})})},_r=function(){return _r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n void; diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx index 9895d6b5b..a2cc88fc1 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/component-panel.tsx @@ -9,12 +9,11 @@ import { TextareaControl, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; -import { store as editorStore, PostTypeSupportCheck } from '@wordpress/editor'; +import { store as editorStore } from '@wordpress/editor'; import { useEffect, useState } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; import { external } from '@wordpress/icons'; import { count } from '@wordpress/wordcount'; -import { PluginDocumentSettingPanel } from '../../../@types/gutenberg/wrapper'; import { PersonaProp } from '../../common/components/persona-selector'; import { ToneProp } from '../../common/components/tone-selector'; @@ -31,10 +30,8 @@ import { LeafIcon } from '../../common/icons/leaf-icon'; import { SidebarSettings, ExcerptSuggestionsSettings as ExcerptSuggestionsSettingsType, - SettingsProvider, useSettings, } from '../../common/settings'; -import { getSettingsFromJson } from '../editor-sidebar'; import { ExcerptSuggestionsProvider } from './provider'; import { ExcerptSuggestionsSettings } from './component-panel-settings'; @@ -50,12 +47,21 @@ interface ExcerptData { oldExcerpt: string; } +type ExcerptSuggestionsPanelProps = { + isDocumentSettingPanel?: boolean; +}; + /** * The PostExcerptSuggestions component displays the excerpt textarea and the Parse.ly AI controls. * * @since 3.13.0 + * @since 3.17.0 Renamed from `PostExcerptSuggestions` and added the `isDocumentSettingPanel` prop. + * + * @param {ExcerptSuggestionsPanelProps} props The component's props. */ -const PostExcerptSuggestions = () => { +export const PostExcerptSuggestions = ( { + isDocumentSettingPanel = false, +}: Readonly ) => { const { settings, setSettings } = useSettings(); const [ error, setError ] = useState(); @@ -226,8 +232,26 @@ const PostExcerptSuggestions = () => {
; + const textareaLabel = isDocumentSettingPanel + ? __( 'Write an excerpt (optional)', 'wp-parsely' ) + : __( 'Excerpt', 'wp-parsely' ); + return (
+ { ! isDocumentSettingPanel && ( +
+ { __( 'Use Parse.ly AI to generate a concise, engaging excerpt for your post.', 'wp-parsely' ) } + +
+ ) }
{ isLoading && (
@@ -236,7 +260,7 @@ const PostExcerptSuggestions = () => { ) } { if ( ! excerptData.isUnderReview ) { @@ -260,22 +284,26 @@ const PostExcerptSuggestions = () => { help={ wordCountString ? wordCountString : null } />
- -
+ + { isDocumentSettingPanel && ( + + ) } + +
{ error && ( { ) } { excerptData.isUnderReview ? ( <> - { generateWithParselyHeader } + { isDocumentSettingPanel && generateWithParselyHeader }
) } - + + { isDocumentSettingPanel && ( + + ) }
); @@ -375,28 +407,3 @@ const LoadingAnimation = (): React.JSX.Element => { ); }; -/** - * The ExcerptPanel component verifies that the current post type supports excerpts, - * and then renders the PostExcerptSuggestions component. - * - * @since 3.13.0 - */ -export const ExcerptPanel = () => { - return ( - - - - - - - - ); -}; diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.scss b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.scss index 3233f857c..ba12ee00a 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.scss +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.scss @@ -11,8 +11,19 @@ margin-bottom: var(--grid-unit-10); } +.editor-post-excerpt .excerpt-suggestions-text { + display: flex; + padding: to_rem(6px) 0 var(--grid-unit-20) 0; + flex-direction: column; + align-items: flex-start; + gap: to_rem(10px); + align-self: stretch; +} + .wp-parsely-excerpt-generator { - margin-top: to_rem(20px); + &.is-doc-set-panel { + margin-top: to_rem(20px); + } // Suggestion settings. .excerpt-suggestions-settings { diff --git a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx index 5b323a364..d94443f02 100644 --- a/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx +++ b/src/content-helper/editor-sidebar/excerpt-suggestions/excerpt-suggestions.tsx @@ -2,19 +2,49 @@ * WordPress dependencies */ import { dispatch } from '@wordpress/data'; +import { PostTypeSupportCheck } from '@wordpress/editor'; import { addFilter, removeFilter } from '@wordpress/hooks'; +import { __ } from '@wordpress/i18n'; import { registerPlugin } from '@wordpress/plugins'; /** * Internal dependencies */ import { dispatchCoreEditPost } from '../../../@types/gutenberg/types'; +import { PluginDocumentSettingPanel } from '../../../@types/gutenberg/wrapper'; +import { SettingsProvider } from '../../common/settings'; import { getContentHelperPermissions } from '../../common/utils/permissions'; -import { ExcerptPanel } from './component-panel'; +import { getSettingsFromJson, PARSELY_SIDEBAR_PLUGIN_ID } from '../editor-sidebar'; import './excerpt-suggestions.scss'; +import { PostExcerptSuggestions } from './component-panel'; -// TODO: Get the plugin ID from the editor sidebar file. -const PARSELY_SIDEBAR_PLUGIN_ID = 'wp-parsely-block-editor-sidebar'; +/** + * The ExcerptDocumentSettingPanel component verifies that the current post type supports excerpts, + * and then renders the PostExcerptSuggestions component. + * + * @since 3.17.0 + */ +export const ExcerptDocumentSettingPanel = () => { + return ( + + + + + + + + ); +}; /** * The ExcerptSuggestions function registers the custom excerpt panel and removes @@ -51,7 +81,7 @@ const ExcerptSuggestions = ( settings: never, name: string ) => { // Register the custom excerpt panel. registerPlugin( 'wp-parsely-excerpt-suggestions', { render: () => ( - + ), } ); diff --git a/src/content-helper/editor-sidebar/smart-linking/component.tsx b/src/content-helper/editor-sidebar/smart-linking/component.tsx index 78d6616d6..9165d4dd9 100644 --- a/src/content-helper/editor-sidebar/smart-linking/component.tsx +++ b/src/content-helper/editor-sidebar/smart-linking/component.tsx @@ -679,19 +679,17 @@ export const SmartLinkingPanel = ( { { error.Message() } ) } - { ( isReviewDone && numAddedLinks > 0 ) && ( + { isReviewDone && numAddedLinks > 0 && ( setIsReviewDone( false ) } className="wp-parsely-smart-linking-suggested-links" > - { - sprintf( - /* translators: 1 - number of smart links generated */ - __( 'Successfully added %s smart links.', 'wp-parsely' ), - numAddedLinks > 0 ? numAddedLinks : suggestedLinks.length, - ) - } + { sprintf( + /* translators: 1 - number of smart links generated */ + __( 'Successfully added %s smart links.', 'wp-parsely' ), + numAddedLinks > 0 ? numAddedLinks : suggestedLinks.length, + ) } ) } { setNumAddedLinks( ( num ) => num + 1 ); - } } + } } onClose={ () => { setIsReviewDone( true ); setIsReviewModalOpen( false ); diff --git a/src/content-helper/editor-sidebar/tabs/sidebar-tools-tab.tsx b/src/content-helper/editor-sidebar/tabs/sidebar-tools-tab.tsx index 49fc1d38b..339bee8b3 100644 --- a/src/content-helper/editor-sidebar/tabs/sidebar-tools-tab.tsx +++ b/src/content-helper/editor-sidebar/tabs/sidebar-tools-tab.tsx @@ -2,6 +2,7 @@ * WordPress dependencies */ import { Panel, PanelBody } from '@wordpress/components'; +import { PostTypeSupportCheck } from '@wordpress/editor'; import { __ } from '@wordpress/i18n'; /** @@ -10,6 +11,7 @@ import { __ } from '@wordpress/i18n'; import { SidebarSettings, useSettings } from '../../common/settings'; import { ContentHelperPermissions } from '../../common/utils/permissions'; import { VerifyCredentials } from '../../common/verify-credentials'; +import { PostExcerptSuggestions } from '../excerpt-suggestions/component-panel'; import { RelatedPostsPanel } from '../related-posts/component'; import { SmartLinkingPanel, SmartLinkingPanelContext } from '../smart-linking/component'; import { TitleSuggestionsPanel } from '../title-suggestions/component'; @@ -59,6 +61,29 @@ export const SidebarToolsTab = ( } + { + permissions.ExcerptSuggestions && + + { + setSettings( { + ExcerptSuggestions: { + ...settings.ExcerptSuggestions, + Open: next, + }, + } ); + trackToggle( 'excerpt_suggestions', next ); + } } + > + + + + + + } + { permissions.SmartLinking &&