From 956251e330f5a1a84fd710851804c07f3572db16 Mon Sep 17 00:00:00 2001 From: Henrique Mouta Date: Thu, 6 Jun 2024 12:54:57 +0100 Subject: [PATCH] PCH Smart Linking: Implement Smart Links Reviewing step (#2507) * Add optional `$request` parameter to `is_available_to_current_user` * Lower phpstan type coverage param_type to 79.7 * Add Smart Linking models and bare endpoint * Start implementing Modal UI * Implement preview and UI elements * Finalize modal with apply and reject actions * Add Remove Link and Select in Editor buttons * Backend improvements * Improve functionality for existing smart links * Add max-height to the sidebar * Fix issue with the onClose callback of the modal * Sort smart links by block position and offset * Rebuild assets * Rebuild assets * Implement getting existing smart links to populate the modal * Improve modal sidebar scrolling when navigating the smart links * Implement retrieval of the post type for each smart link * Improve sorting and backfilling of existing smart links data * Better smart link detection and auto-fixing on save, link removal, and link changing. * Move isReviewModalOpen to the store to be global across the Smart Linking component * Add tooltip to the modal actions * Clean-up code and documentation * Implement the link selection functionality * UI & functionality tweaks to the Link Details component * Rebuild assets with the "finalized" UI & fix linting * Rebuild assets & fix tests * Fix some issues with link validation and saving * Address issue with sorting in some edge cases * Apply code review suggestions * Apply suggestions from code review Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> * Rebuild assets * class-smart-linking-endpoint.php: Improve comments * Fix regression with getBlockContent * Apply suggestions from code review Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> * Update src/Endpoints/class-base-endpoint.php Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> * Performance improvement per code review suggestion. * Improve comments in some PHP files * Smart Linking Provider: Improve comments * Apply whitespace and comment improvements * Apply whitespace and comment improvements * Apply comment improvements * Rebuild assets * Apply code review suggestions from @acicovic * Fix tests (hopefully) --------- Co-authored-by: Alex Cicovic <23142906+acicovic@users.noreply.github.com> --- build/admin-settings-rtl.css | 2 +- build/admin-settings.asset.php | 2 +- build/admin-settings.css | 2 +- build/content-helper/dashboard-widget-rtl.css | 2 +- .../content-helper/dashboard-widget.asset.php | 2 +- build/content-helper/dashboard-widget.css | 2 +- build/content-helper/editor-sidebar-rtl.css | 10 +- build/content-helper/editor-sidebar.asset.php | 2 +- build/content-helper/editor-sidebar.css | 10 +- build/content-helper/editor-sidebar.js | 40 +- .../content-helper/excerpt-generator-rtl.css | 2 +- .../excerpt-generator.asset.php | 2 +- build/content-helper/excerpt-generator.css | 2 +- jest.config.js | 5 + jest.setup.js | 2 + phpstan.neon | 2 +- src/@types/gutenberg/types.ts | 6 + src/Endpoints/class-base-endpoint.php | 38 +- .../class-smart-linking-endpoint.php | 271 ++++++++ ...ass-suggest-linked-reference-api-proxy.php | 8 +- .../class-base-endpoint-user-meta.php | 4 +- src/Models/class-base-model.php | 100 +++ src/Models/class-smart-link.php | 238 +++++++ .../class-analytics-post-detail-api.php | 5 +- src/RemoteAPI/class-analytics-posts-api.php | 5 +- .../class-referrers-post-detail-api.php | 5 +- src/RemoteAPI/class-related-api.php | 5 +- src/RemoteAPI/class-remote-api-cache.php | 7 +- src/RemoteAPI/class-validate-api.php | 5 +- .../class-content-suggestions-base-api.php | 6 +- .../class-link-suggestion.php | 48 -- .../class-suggest-linked-reference-api.php | 20 +- src/RemoteAPI/interface-remote-api.php | 5 +- src/content-helper/common/base-provider.tsx | 1 + src/content-helper/common/css/variables.scss | 12 +- src/content-helper/common/icons/ai-icon.tsx | 2 +- .../editor-sidebar/editor-sidebar.tsx | 7 +- .../smart-linking/component-block-overlay.tsx | 2 +- .../smart-linking/component-link-monitor.tsx | 186 ++++++ .../smart-linking/component.tsx | 465 ++++++-------- .../editor-sidebar/smart-linking/hooks.ts | 89 +++ .../editor-sidebar/smart-linking/provider.ts | 65 +- .../review-modal/component-modal.tsx | 462 +++++++++++++ .../review-modal/component-sidebar.tsx | 97 +++ .../review-modal/component-suggestion.tsx | 474 ++++++++++++++ .../smart-linking/smart-linking.scss | 207 +++++- .../editor-sidebar/smart-linking/store.ts | 235 ++++++- .../editor-sidebar/smart-linking/utils.ts | 608 +++++++++++++++++- .../Integration/BaseUserMetaEndpointTest.php | 20 + tests/Integration/ProxyEndpointTest.php | 2 +- .../SuggestLinkedReferenceAPITest.php | 3 +- .../js/content-helper/smart-linking.test.tsx | 23 + wp-parsely.php | 8 + 53 files changed, 3405 insertions(+), 428 deletions(-) create mode 100644 jest.setup.js create mode 100644 src/Endpoints/content-helper/class-smart-linking-endpoint.php create mode 100644 src/Models/class-base-model.php create mode 100644 src/Models/class-smart-link.php delete mode 100644 src/RemoteAPI/content-suggestions/class-link-suggestion.php create mode 100644 src/content-helper/editor-sidebar/smart-linking/component-link-monitor.tsx create mode 100644 src/content-helper/editor-sidebar/smart-linking/hooks.ts create mode 100644 src/content-helper/editor-sidebar/smart-linking/review-modal/component-modal.tsx create mode 100644 src/content-helper/editor-sidebar/smart-linking/review-modal/component-sidebar.tsx create mode 100644 src/content-helper/editor-sidebar/smart-linking/review-modal/component-suggestion.tsx create mode 100644 tests/js/content-helper/smart-linking.test.tsx diff --git a/build/admin-settings-rtl.css b/build/admin-settings-rtl.css index 8a59b2979..21a2880dd 100644 --- a/build/admin-settings-rtl.css +++ b/build/admin-settings-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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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}.settings_page_parsely{--padding-default:15px}.settings_page_parsely #track-post-types{max-width:550px;width:100%}.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.settings_page_parsely #track-post-types td{padding:0}.settings_page_parsely #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.settings_page_parsely #track-post-types thead th:nth-child(3){word-break:break-word}.settings_page_parsely fieldset:disabled *,.settings_page_parsely tr:has(fieldset:disabled) *{color:var(--gray-500);cursor:default}.settings_page_parsely .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.settings_page_parsely a.managed-option-badge{cursor:pointer!important}.settings_page_parsely a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{padding-right:10px;padding-left:10px}.settings_page_parsely #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} +#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}.settings_page_parsely{--padding-default:15px}.settings_page_parsely #track-post-types{max-width:550px;width:100%}.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.settings_page_parsely #track-post-types td{padding:0}.settings_page_parsely #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.settings_page_parsely #track-post-types thead th:nth-child(3){word-break:break-word}.settings_page_parsely fieldset:disabled *,.settings_page_parsely tr:has(fieldset:disabled) *{color:var(--gray-500);cursor:default}.settings_page_parsely .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.settings_page_parsely a.managed-option-badge{cursor:pointer!important}.settings_page_parsely a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{padding-right:10px;padding-left:10px}.settings_page_parsely #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} diff --git a/build/admin-settings.asset.php b/build/admin-settings.asset.php index 3e4513aea..91d66c680 100644 --- a/build/admin-settings.asset.php +++ b/build/admin-settings.asset.php @@ -1 +1 @@ - array(), 'version' => 'e15999c17e352b22474b'); + array(), 'version' => '20eafa29410328a029a2'); diff --git a/build/admin-settings.css b/build/admin-settings.css index 2ce0634eb..0fd7159f3 100644 --- a/build/admin-settings.css +++ b/build/admin-settings.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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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}.settings_page_parsely{--padding-default:15px}.settings_page_parsely #track-post-types{max-width:550px;width:100%}.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.settings_page_parsely #track-post-types td{padding:0}.settings_page_parsely #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.settings_page_parsely #track-post-types thead th:nth-child(3){word-break:break-word}.settings_page_parsely fieldset:disabled *,.settings_page_parsely tr:has(fieldset:disabled) *{color:var(--gray-500);cursor:default}.settings_page_parsely .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.settings_page_parsely a.managed-option-badge{cursor:pointer!important}.settings_page_parsely a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{padding-left:10px;padding-right:10px}.settings_page_parsely #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} +#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}.settings_page_parsely{--padding-default:15px}.settings_page_parsely #track-post-types{max-width:550px;width:100%}.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.settings_page_parsely #track-post-types td{padding:0}.settings_page_parsely #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.settings_page_parsely #track-post-types thead th:nth-child(3){word-break:break-word}.settings_page_parsely fieldset:disabled *,.settings_page_parsely tr:has(fieldset:disabled) *{color:var(--gray-500);cursor:default}.settings_page_parsely .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.settings_page_parsely a.managed-option-badge{cursor:pointer!important}.settings_page_parsely a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{padding-left:10px;padding-right:10px}.settings_page_parsely #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} diff --git a/build/content-helper/dashboard-widget-rtl.css b/build/content-helper/dashboard-widget-rtl.css index 1054e63a2..447c1c3cf 100644 --- a/build/content-helper/dashboard-widget-rtl.css +++ b/build/content-helper/dashboard-widget-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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-dashboard-widget{color:var(--base-text);font-family:var(--base-font)}#wp-parsely-dashboard-widget .parsely-spinner-wrapper{display:flex;justify-content:center;margin:11.875rem 0}#wp-parsely-dashboard-widget .parsely-spinner-wrapper svg{height:22px;width:22px}#wp-parsely-dashboard-widget .content-helper-error-message{margin-top:1.125rem}#wp-parsely-dashboard-widget p.content-helper-error-message-hint{color:var(--gray-700)}#wp-parsely-dashboard-widget .parsely-top-posts-filters{display:flex;justify-content:space-between;margin-bottom:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation{display:flex;justify-content:space-between;margin-top:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button{background:none;border:none;color:var(--blue-550);font-size:.75rem;font-weight:600;text-decoration:none}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:disabled{visibility:hidden}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:not([disabled]):hover{cursor:pointer}#wp-parsely-dashboard-widget .parsely-top-post-content{display:flex}#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:counter(item) "";counter-increment:item;padding-left:.5rem}@media only screen and (max-width:380px){#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:"";padding-left:0}}#wp-parsely-dashboard-widget .parsely-top-posts{list-style:none;margin:1rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post{margin-bottom:1rem}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail{height:46px;min-width:46px}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail img{height:100%;width:100%}#wp-parsely-dashboard-widget .parsely-top-post-data{border-top:1px solid var(--gray-300);flex-grow:1;margin-right:.5rem;padding-top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-title{color:var(--base-text);font-size:.875rem;margin-left:.4375rem}#wp-parsely-dashboard-widget a.parsely-top-post-title:hover{color:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-icon-link{position:relative;top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg{fill:#8d98a1;margin-left:.1875rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg:hover{fill:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-metadata{margin:.25rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span{color:var(--gray-500)}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span:not(:first-child){margin-right:.75rem}#wp-parsely-dashboard-widget .parsely-post-metric-data{float:left;font-family:var(--numeric-font);font-size:1.125rem;padding-right:.625rem} +#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-dashboard-widget{color:var(--base-text);font-family:var(--base-font)}#wp-parsely-dashboard-widget .parsely-spinner-wrapper{display:flex;justify-content:center;margin:11.875rem 0}#wp-parsely-dashboard-widget .parsely-spinner-wrapper svg{height:22px;width:22px}#wp-parsely-dashboard-widget .content-helper-error-message{margin-top:1.125rem}#wp-parsely-dashboard-widget p.content-helper-error-message-hint{color:var(--gray-700)}#wp-parsely-dashboard-widget .parsely-top-posts-filters{display:flex;justify-content:space-between;margin-bottom:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation{display:flex;justify-content:space-between;margin-top:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button{background:none;border:none;color:var(--blue-550);font-size:.75rem;font-weight:600;text-decoration:none}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:disabled{visibility:hidden}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:not([disabled]):hover{cursor:pointer}#wp-parsely-dashboard-widget .parsely-top-post-content{display:flex}#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:counter(item) "";counter-increment:item;padding-left:.5rem}@media only screen and (max-width:380px){#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:"";padding-left:0}}#wp-parsely-dashboard-widget .parsely-top-posts{list-style:none;margin:1rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post{margin-bottom:1rem}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail{height:46px;min-width:46px}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail img{height:100%;width:100%}#wp-parsely-dashboard-widget .parsely-top-post-data{border-top:1px solid var(--gray-300);flex-grow:1;margin-right:.5rem;padding-top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-title{color:var(--base-text);font-size:.875rem;margin-left:.4375rem}#wp-parsely-dashboard-widget a.parsely-top-post-title:hover{color:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-icon-link{position:relative;top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg{fill:#8d98a1;margin-left:.1875rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg:hover{fill:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-metadata{margin:.25rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span{color:var(--gray-500)}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span:not(:first-child){margin-right:.75rem}#wp-parsely-dashboard-widget .parsely-post-metric-data{float:left;font-family:var(--numeric-font);font-size:1.125rem;padding-right:.625rem} diff --git a/build/content-helper/dashboard-widget.asset.php b/build/content-helper/dashboard-widget.asset.php index 65368a141..670d941c1 100644 --- a/build/content-helper/dashboard-widget.asset.php +++ b/build/content-helper/dashboard-widget.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '930369a3015a8fbd0eee'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '2a085e2f1803cbb45764'); diff --git a/build/content-helper/dashboard-widget.css b/build/content-helper/dashboard-widget.css index 52838501e..d4ff79870 100644 --- a/build/content-helper/dashboard-widget.css +++ b/build/content-helper/dashboard-widget.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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-dashboard-widget{color:var(--base-text);font-family:var(--base-font)}#wp-parsely-dashboard-widget .parsely-spinner-wrapper{display:flex;justify-content:center;margin:11.875rem 0}#wp-parsely-dashboard-widget .parsely-spinner-wrapper svg{height:22px;width:22px}#wp-parsely-dashboard-widget .content-helper-error-message{margin-top:1.125rem}#wp-parsely-dashboard-widget p.content-helper-error-message-hint{color:var(--gray-700)}#wp-parsely-dashboard-widget .parsely-top-posts-filters{display:flex;justify-content:space-between;margin-bottom:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation{display:flex;justify-content:space-between;margin-top:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button{background:none;border:none;color:var(--blue-550);font-size:.75rem;font-weight:600;text-decoration:none}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:disabled{visibility:hidden}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:not([disabled]):hover{cursor:pointer}#wp-parsely-dashboard-widget .parsely-top-post-content{display:flex}#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:counter(item) "";counter-increment:item;padding-right:.5rem}@media only screen and (max-width:380px){#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:"";padding-right:0}}#wp-parsely-dashboard-widget .parsely-top-posts{list-style:none;margin:1rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post{margin-bottom:1rem}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail{height:46px;min-width:46px}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail img{height:100%;width:100%}#wp-parsely-dashboard-widget .parsely-top-post-data{border-top:1px solid var(--gray-300);flex-grow:1;margin-left:.5rem;padding-top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-title{color:var(--base-text);font-size:.875rem;margin-right:.4375rem}#wp-parsely-dashboard-widget a.parsely-top-post-title:hover{color:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-icon-link{position:relative;top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg{fill:#8d98a1;margin-right:.1875rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg:hover{fill:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-metadata{margin:.25rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span{color:var(--gray-500)}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span:not(:first-child){margin-left:.75rem}#wp-parsely-dashboard-widget .parsely-post-metric-data{float:right;font-family:var(--numeric-font);font-size:1.125rem;padding-left:.625rem} +#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-dashboard-widget{color:var(--base-text);font-family:var(--base-font)}#wp-parsely-dashboard-widget .parsely-spinner-wrapper{display:flex;justify-content:center;margin:11.875rem 0}#wp-parsely-dashboard-widget .parsely-spinner-wrapper svg{height:22px;width:22px}#wp-parsely-dashboard-widget .content-helper-error-message{margin-top:1.125rem}#wp-parsely-dashboard-widget p.content-helper-error-message-hint{color:var(--gray-700)}#wp-parsely-dashboard-widget .parsely-top-posts-filters{display:flex;justify-content:space-between;margin-bottom:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation{display:flex;justify-content:space-between;margin-top:.625rem}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button{background:none;border:none;color:var(--blue-550);font-size:.75rem;font-weight:600;text-decoration:none}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:disabled{visibility:hidden}#wp-parsely-dashboard-widget .parsely-top-posts-navigation button:not([disabled]):hover{cursor:pointer}#wp-parsely-dashboard-widget .parsely-top-post-content{display:flex}#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:counter(item) "";counter-increment:item;padding-right:.5rem}@media only screen and (max-width:380px){#wp-parsely-dashboard-widget .parsely-top-post-content:before{content:"";padding-right:0}}#wp-parsely-dashboard-widget .parsely-top-posts{list-style:none;margin:1rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post{margin-bottom:1rem}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail{height:46px;min-width:46px}#wp-parsely-dashboard-widget .parsely-top-post-thumbnail img{height:100%;width:100%}#wp-parsely-dashboard-widget .parsely-top-post-data{border-top:1px solid var(--gray-300);flex-grow:1;margin-left:.5rem;padding-top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-title{color:var(--base-text);font-size:.875rem;margin-right:.4375rem}#wp-parsely-dashboard-widget a.parsely-top-post-title:hover{color:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-icon-link{position:relative;top:.25rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg{fill:#8d98a1;margin-right:.1875rem}#wp-parsely-dashboard-widget .parsely-top-post-icon-link svg:hover{fill:var(--blue-550)}#wp-parsely-dashboard-widget .parsely-top-post-metadata{margin:.25rem 0 0}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span{color:var(--gray-500)}#wp-parsely-dashboard-widget .parsely-top-post-metadata>span:not(:first-child){margin-left:.75rem}#wp-parsely-dashboard-widget .parsely-post-metric-data{float:right;font-family:var(--numeric-font);font-size:1.125rem;padding-left:.625rem} diff --git a/build/content-helper/editor-sidebar-rtl.css b/build/content-helper/editor-sidebar-rtl.css index d0c845940..ef0fb5afd 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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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{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{align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .smart-linking-generate 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-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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-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{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 .smart-linking-review-sidebar{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);max-height:25rem;min-width:13.75rem;overflow-y:auto;padding:.1875rem}.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 .components-divider{border-color:#ccc;height:1px;width:28.25rem}.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{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);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} diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php index 65ca024d3..752d9a02a 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-edit-post', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url'), 'version' => 'c1e0b864d5664eb506af'); + array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-edit-post', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url'), 'version' => '4179c4d908321ffad715'); diff --git a/build/content-helper/editor-sidebar.css b/build/content-helper/editor-sidebar.css index d36bd5c93..53f76d0d3 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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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{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{align-self:stretch;display:flex;flex-direction:column;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-smart-linking .smart-linking-generate 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-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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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-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{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 .smart-linking-review-sidebar{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-20);max-height:25rem;min-width:13.75rem;overflow-y:auto;padding:.1875rem}.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 .components-divider{border-color:#ccc;height:1px;width:28.25rem}.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{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);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} diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js index e88c84447..4d8ebeafa 100644 --- a/build/content-helper/editor-sidebar.js +++ b/build/content-helper/editor-sidebar.js @@ -1,27 +1,27 @@ -!function(){"use strict";var e={20:function(e,t,n){var r=n(609),s=Symbol.for("react.element"),i=Symbol.for("react.fragment"),a=Object.prototype.hasOwnProperty,o=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,i={},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)a.call(t,r)&&!l.hasOwnProperty(r)&&(i[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===i[r]&&(i[r]=t[r]);return{$$typeof:s,type:e,key:c,ref:u,props:i,_owner:o.current}}t.Fragment=i,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 s=t[r];if(void 0!==s)return s.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.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 rn}});var e,t,r,s=n(848),i=window.wp.components,a=window.wp.data,o=window.wp.editPost,l=window.wp.element,c=window.wp.i18n,u=window.wp.primitives,p=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),d=window.wp.plugins,f=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,i=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,s,i,a={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return i={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function o(o){return function(l){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,o[0]&&(a=0)),a;)try{if(n=1,r&&(s=2&o[0]?r.return:o[0]?r.throw||((s=r.return)&&s.call(r),0):r.next)&&!(s=s.call(r,o[1])).done)return s;switch(r=0,s&&(o=[2&o[0],s.value]),o[0]){case 0:case 1:s=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,r=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!((s=(s=a.trys).length>0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]=1e4&&(clearInterval(i),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}(),h=(f.trackEvent,function(){return(0,s.jsx)(i.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,s.jsx)(i.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"})})}),g=function(e){var t=e.size,n=void 0===t?24:t,r=e.className,a=void 0===r?"wp-parsely-icon":r;return(0,s.jsxs)(i.SVG,{className:a,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)(i.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,s.jsx)(i.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,s.jsx)(i.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,s.jsx)(i.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"})]})},y=function(){return y=Object.assign||function(e){for(var t,n=1,r=arguments.length;nhere.',"wp-parsely"):i.code===A.ParselySuggestionsApiOpenAiError||i.code===A.ParselySuggestionsApiOpenAiUnavailable?i.message=(0,c.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):i.code===A.HttpRequestFailed&&i.message.includes("cURL error 28")?i.message=(0,c.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):i.code===A.ParselySuggestionsApiSchemaError?i.message=(0,c.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):i.code===A.ParselySuggestionsApiNoData?i.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"):i.code===A.ParselySuggestionsApiOpenAiSchema?i.message=(0,c.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):i.code===A.ParselySuggestionsApiAuthUnavailable&&(i.message=(0,c.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),i}return z(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[A.PluginCredentialsNotSetMessageDetected,A.PluginSettingsSiteIdNotSet,A.PluginSettingsApiSecretNotSet].includes(this.code)?I(e):(this.code===A.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!==A.ParselyApiForbidden&&this.code!==A.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===A.HttpRequestFailed&&(this.hint=this.Hint((0,c.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,s.jsx)(R,{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,c.__)("Hint:","wp-parsely")," ").concat(e,"

")},t}(Error);function $(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Z,q=function(e){var t=e.value,n=e.onChange,r=e.max,a=e.min,o=e.suffix,l=e.size,c=e.label,u=e.initialPosition,p=e.disabled,d=e.className;return(0,s.jsxs)("div",{className:"parsely-inputrange-control ".concat(d||""),children:[(0,s.jsx)(i.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:c}),(0,s.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,s.jsx)(i.__experimentalNumberControl,{disabled:p,value:t,suffix:(0,s.jsx)(i.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=l?l:"__unstable-large",min:a,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,s.jsx)(i.RangeControl,{disabled:p,value:t,showTooltip:!1,initialPosition:u,onChange:function(e){n(e)},withInputField:!1,min:a,max:r})]})]})},W=function(){return W=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0)){var e={maxLinksPerPost:p.SmartLinking.MaxLinks};U(e)}}),[U,p]);var ee=(0,a.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,s=t.getBlock,i=t.getBlocks,a=e("core/editor"),o=a.getEditedPostContent,l=a.getCurrentPostAttribute;return{allBlocks:i(),selectedBlock:n?s(n):r(),postContent:o(),postPermalink:l("link")}}),[n]),te=ee.allBlocks,ne=ee.selectedBlock,le=ee.postContent,ce=ee.postPermalink,ue=function(e){return ie(void 0,void 0,void 0,(function(){var t,n,r,s;return ae(this,(function(i){switch(i.label){case 0:t=[],i.label=1;case 1:return i.trys.push([1,4,,9]),[4,q((n=b||!ne)?Z.All:Z.Selected)];case 2:return i.sent(),a=ce.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],[4,re.getInstance().generateSmartLinks(ne&&!n?(0,V.getBlockContent)(ne):le,T,r)];case 3:return t=i.sent(),[3,9];case 4:if((s=i.sent()).code&&s.code===A.ParselyAborted)throw s.numRetries=3-e,s;return e>0&&s.retryFetch?(console.error(s),[4,Y(!0)]):[3,8];case 5:return i.sent(),[4,K()];case 6:return i.sent(),[4,ue(e-1)];case 7:return[2,i.sent()];case 8:throw s;case 9:return[4,B(t)];case 10:return i.sent(),[2,t]}var a}))}))},pe=function(e,t,n,r){var s=ce.replace(/^https?:\/\//,"").replace(/\/+$/,"");t=t.filter((function(e){return!e.href.includes(s)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(e.href)),!1)})),e.forEach((function(e){var s=!1;if(e.innerBlocks&&e.innerBlocks.length)pe(e.innerBlocks,t,n,r);else if(e.originalContent){var i=(0,V.getBlockContent)(e),a=(new DOMParser).parseFromString(i,"text/html").body.firstChild;a&&a instanceof HTMLElement&&(t.forEach((function(e){var t=function(e,t){for(var n,r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode:function(n){var r;if(!n.textContent||!n.textContent.includes(t))return NodeFilter.FILTER_REJECT;for(var s=n.parentNode;s&&s!==e;){if("A"===s.nodeName&&!(null===(r=s.textContent)||void 0===r?void 0:r.includes(t)))return NodeFilter.FILTER_REJECT;s=s.parentNode}return NodeFilter.FILTER_ACCEPT}}),s=[];n=r.nextNode();)s.push(n);return s}(a,e.text),r="".concat(e.text,"#").concat(e.offset);n[r]||(n[r]={encountered:0,linked:0}),t.forEach((function(t){var i;if(t.textContent){var a=n[r];if(a.linked>=1)return;for(var o=new RegExp($(e.text),"g"),l=void 0;null!==(l=o.exec(t.textContent));)if(a.encountered++,a.encountered===e.offset+1){var c=document.createElement("a");c.href=e.href,c.title=e.title,c.textContent=l[0];var u=document.createRange();if(u.setStart(t,l.index),u.setEnd(t,l.index+l[0].length),u.deleteContents(),u.insertNode(c),t.textContent&&l.index+l[0].length[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},ye=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),H.unlockPostSaving("wp-parsely-block-overlay")};return(0,s.jsx)("div",{className:"wp-parsely-smart-linking",children:(0,s.jsxs)(i.PanelRow,{className:t,children:[(0,s.jsxs)("div",{className:"smart-linking-text",children:[(0,c.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,s.jsxs)(i.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-smart-linking-beta",target:"_blank",variant:"link",children:[(0,c.__)("Learn more about Parse.ly AI","wp-parsely"),(0,s.jsx)(D,{icon:F,size:18,className:"parsely-external-link-icon"})]})]}),P&&(0,s.jsx)(i.Notice,{status:"info",onRemove:function(){return I(null)},className:"wp-parsely-content-helper-error",children:P.Message()}),null!==j&&(0,s.jsx)(i.Notice,{status:"success",onRemove:function(){return B(null)},className:"wp-parsely-smart-linking-suggested-links",children:(0,c.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ -(0,c.__)("Successfully added %s smart links.","wp-parsely"),y>0?y:j.length)}),(0,s.jsx)(J,{disabled:m,selectedBlock:null==ne?void 0:ne.clientId,onSettingChange:function(e,t){var n;h({SmartLinking:se(se({},p.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&W(t)}}),(0,s.jsx)("div",{className:"smart-linking-generate",children:(0,s.jsx)(i.Button,{onClick:function(){return ie(void 0,void 0,void 0,(function(){var e,t,n,r,s;return ae(this,(function(i){switch(i.label){case 0:return[4,R(!0)];case 1:return i.sent(),[4,B(null)];case 2:return i.sent(),[4,I(null)];case 3:return i.sent(),f.trackEvent("smart_linking_generate_pressed",{is_full_content:b,selected_block:null!==(s=null==ne?void 0:ne.name)&&void 0!==s?s:"none",context:o}),[4,fe(b?"all":null==ne?void 0:ne.clientId)];case 4:i.sent(),e=setTimeout((function(){var e;R(!1),f.trackEvent("smart_linking_generate_timeout",{is_full_content:b,selected_block:null!==(e=null==ne?void 0:ne.name)&&void 0!==e?e:"none",context:o}),he(b?"all":null==ne?void 0:ne.clientId)}),18e4),t=C,i.label=5;case 5:return i.trys.push([5,7,9,14]),[4,ue(3)];case 6:return function(e){var t;f.trackEvent("smart_linking_applied",{is_full_content:b||!ne,selected_block:null!==(t=null==ne?void 0:ne.name)&&void 0!==t?t:"none",links_count:e.length,context:o});var n={},r=[];pe(ne&&!b?[ne]:te,e,n,r),de(r);var s=Object.values(n).reduce((function(e,t){return e+t.linked}),0);v(s),w("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ -(0,c.sprintf)((0,c.__)("%s smart links successfully applied.","wp-parsely"),s),{type:"snackbar"})}(i.sent()),[3,14];case 7:return n=i.sent(),r=(0,c.__)("There was a problem applying smart links.","wp-parsely"),n.code&&n.code===A.ParselyAborted&&(r=(0,c.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ -(0,c.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),n.numRetries,(0,c._n)("attempt","attempts",n.numRetries,"wp-parsely")),n.message=r),[4,I(n)];case 8:return i.sent(),w("error",r,{type:"snackbar"}),[3,14];case 9:return[4,R(!1)];case 10:return i.sent(),[4,q(t)];case 11:return i.sent(),[4,Y(!1)];case 12:return i.sent(),[4,he(b?"all":null==ne?void 0:ne.clientId)];case 13:return i.sent(),clearTimeout(e),[7];case 14:return[2]}}))}))},variant:"primary",isBusy:m,disabled:m,children:E?(0,c.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,c.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),N,3):m?(0,c.__)("Adding Smart Links…","wp-parsely"):(0,c.__)("Add Smart Links","wp-parsely")})})]})})},ce=function(){return ce=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=c){var u=t;(s=r/c)%1>1/o&&(u=s>10?1:2),u=parseFloat(s.toFixed(2))===parseFloat(s.toFixed(0))?0:u,i=s.toFixed(u),a=l}o=c})),i+n+a}var xe=function(e){var n=e.data,r=e.isLoading,a=(0,l.useState)(t.Views),o=a[0],u=a[1],p=(0,l.useState)(!1),d=p[0],f=p[1];r||delete n.referrers.types.totals;var h=function(e){switch(e){case"social":return(0,c.__)("Social","wp-parsely");case"search":return(0,c.__)("Search","wp-parsely");case"other":return(0,c.__)("Other","wp-parsely");case"internal":return(0,c.__)("Internal","wp-parsely");case"direct":return(0,c.__)("Direct","wp-parsely")}return e},g=(0,c.sprintf)((0,c.__)("By %s","wp-parsely"),C(o)); -/* translators: %s: metric description */return(0,s.jsxs)(me,{title:(0,c.__)("Categories","wp-parsely"),level:3,subtitle:g,isOpen:d,onClick:function(){return f(!d)},children:[d&&(0,s.jsx)("div",{className:"panel-settings",children:(0,s.jsx)(i.SelectControl,{value:o,prefix:(0,c.__)("By: ","wp-parsely"),onChange:function(e){T(e,t)&&u(e)},children:Object.values(t).map((function(e){return(0,s.jsxs)("option",{value:e,disabled:"avg_engaged"===e,children:[C(e),"avg_engaged"===e&&(0,c.__)(" (coming soon)","wp-parsely")]},e)}))})}),r?(0,s.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,s.jsx)(i.Spinner,{})}):(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"multi-percentage-bar",children:Object.entries(n.referrers.types).map((function(e){var t=e[0],n=e[1],r=(0,c.sprintf)(/* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ /* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ -(0,c.__)("%1$s: %2$s%%","wp-parsely"),h(t),n.viewsPercentage);return(0,s.jsx)(i.Tooltip +!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),s=Symbol.for("react.fragment"),a=Object.prototype.hasOwnProperty,o=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)a.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:o.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 Gn}});var e,t,r,i=n(848),s=window.wp.components,a=window.wp.data,o=window.wp.domReady,l=n.n(o),c=window.wp.editPost,u=window.wp.element,p=window.wp.i18n,d=window.wp.primitives,f=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),h=window.wp.plugins,v=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,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return s={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function o(o){return function(l){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,o[0]&&(a=0)),a;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,r=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!((i=(i=a.trys).length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[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}(),g=(v.trackEvent,function(){return(0,i.jsx)(s.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,i.jsx)(s.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"})})}),y=function(e){var t=e.size,n=void 0===t?24:t,r=e.className,a=void 0===r?"wp-parsely-icon":r;return(0,i.jsxs)(s.SVG,{className:a,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,i.jsx)(s.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,i.jsx)(s.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,i.jsx)(s.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,i.jsx)(s.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"})]})},m=function(){return m=Object.assign||function(e){for(var t,n=1,r=arguments.length;nhere.',"wp-parsely"):s.code===N.ParselySuggestionsApiOpenAiError||s.code===N.ParselySuggestionsApiOpenAiUnavailable?s.message=(0,p.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):s.code===N.HttpRequestFailed&&s.message.includes("cURL error 28")?s.message=(0,p.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):s.code===N.ParselySuggestionsApiSchemaError?s.message=(0,p.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):s.code===N.ParselySuggestionsApiNoData?s.message=(0,p.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):s.code===N.ParselySuggestionsApiOpenAiSchema?s.message=(0,p.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):s.code===N.ParselySuggestionsApiAuthUnavailable&&(s.message=(0,p.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),s}return q(t,e),t.prototype.Message=function(e){return void 0===e&&(e=null),[N.PluginCredentialsNotSetMessageDetected,N.PluginSettingsSiteIdNotSet,N.PluginSettingsApiSecretNotSet].includes(this.code)?M(e):(this.code===N.FetchError&&(this.hint=this.Hint((0,p.__)("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!==N.ParselyApiForbidden&&this.code!==N.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,p.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===N.HttpRequestFailed&&(this.hint=this.Hint((0,p.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,i.jsx)(B,{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,p.__)("Hint:","wp-parsely")," ").concat(e,"

")},t}(Error);function $(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var W=function(e){var t=e.isDetectingEnabled,n=e.onLinkChange,r=e.onLinkRemove,i=e.onLinkAdd,s=e.debounceValue,o=void 0===s?500:s,l=(0,a.useSelect)((function(e){return{blocks:(0,e("core/block-editor").getBlocks)()}}),[]).blocks,c=(0,u.useRef)(l),p=(0,u.useRef)(t);return(0,u.useEffect)((function(){var e=(0,R.debounce)((function(){for(var t=[],s=0;s0)return r(e.innerBlocks,t[s].innerBlocks);if(JSON.stringify(e)!==JSON.stringify(t[s])){var a=t[s],o=i.parseFromString(e.attributes.content||"","text/html"),l=i.parseFromString((null==a?void 0:a.attributes.content)||"","text/html"),c=Array.from(o.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:a,addedLinks:p,removedLinks:d,changedLinks:f})}}}))};return r(e,t),n}(l,c.current);a.length>0&&(a.forEach((function(e){e.changedLinks.length>0&&n&&n(e),e.addedLinks.length>0&&i&&i(e),e.removedLinks.length>0&&r&&r(e)})),c.current=l)}),o);return e(t),function(){e.cancel()}}),[l,o,t,i,n,r]),null},K=function(e){var t=e.value,n=e.onChange,r=e.max,a=e.min,o=e.suffix,l=e.size,c=e.label,u=e.initialPosition,p=e.disabled,d=e.className;return(0,i.jsxs)("div",{className:"parsely-inputrange-control ".concat(d||""),children:[(0,i.jsx)(s.__experimentalHeading,{className:"parsely-inputrange-control__label",level:3,children:c}),(0,i.jsxs)("div",{className:"parsely-inputrange-control__controls",children:[(0,i.jsx)(s.__experimentalNumberControl,{disabled:p,value:t,suffix:(0,i.jsx)(s.__experimentalInputControlSuffixWrapper,{children:o}),size:null!=l?l:"__unstable-large",min:a,max:r,onChange:function(e){var t=parseInt(e,10);isNaN(t)||n(t)}}),(0,i.jsx)(s.RangeControl,{disabled:p,value:t,showTooltip:!1,initialPosition:u,onChange:function(e){n(e)},withInputField:!1,min:a,max:r})]})]})},Y=function(e,t,n,r){return new(n||(n=Promise))((function(i,s){function a(e){try{l(r.next(e))}catch(e){s(e)}}function o(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(a,o)}l((r=r.apply(e,t||[])).next())}))},Q=function(e,t){var n,r,i,s,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return s={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function o(o){return function(l){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,o[0]&&(a=0)),a;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,r=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!((i=(i=a.trys).length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]s.bottom)&&(r.scrollTop=i.offsetTop-r.offsetTop)}}}}),[t,n]);var l=(0,i.jsxs)("span",{className:"smart-linking-menu-label",children:[(0,p.__)("NEW","wp-parsely"),(0,i.jsx)(Se,{})]});return(0,i.jsx)("div",{className:"smart-linking-review-sidebar",ref:a,children:(0,i.jsxs)("div",{children:[(0,i.jsxs)("div",{className:"review-sidebar-header",children:[(0,p.__)("Outbound Smart Links","wp-parsely"),(0,i.jsx)("span",{children:null==n?void 0:n.length})]}),null==n?void 0:n.map((function(e,n){return(0,i.jsxs)(s.MenuItem,{ref:function(e){return 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(){r(e)},children:[(0,i.jsx)("span",{className:"smart-linking-menu-item",children:e.text}),!e.applied&&l]},e.uid)}))]})})},je=(0,i.jsxs)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:[(0,i.jsx)(d.Path,{d:"M15.5 7.5h-7V9h7V7.5Zm-7 3.5h7v1.5h-7V11Zm7 3.5h-7V16h7v-1.5Z"}),(0,i.jsx)(d.Path,{d:"M17 4H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2ZM7 5.5h10a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5H7a.5.5 0 0 1-.5-.5V6a.5.5 0 0 1 .5-.5Z"})]}),Te=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.Path,{d:"M20 11.2H6.8l3.7-3.7-1-1L3.9 12l5.6 5.5 1-1-3.7-3.7H20z"})}),Le=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.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"})}),Ee=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),Ce=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.Path,{d:"m14.5 6.5-1 1 3.7 3.7H4v1.6h13.2l-3.7 3.7 1 1 5.6-5.5z"})}),Ae=function(){return Ae=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&(o=a[0],(l=o.parentNode)&&(c=document.createTextNode(null!==(u=o.textContent)&&void 0!==u?u:""),l.replaceChild(c,o),z.updateBlockAttributes(n,{content:s.innerHTML}))),[4,P(t.uid)]):[2]):[2];case 1:return p.sent(),[2]}}))}))},T=function(){h(!1),g.filter((function(e){return!e.applied})).length>0?c(!0):k().then((function(){return t()}))},L=function(e){c(!1),e?(h(!1),k().then((function(){t()}))):h(!0)},E=function(){var e=g.indexOf(b)+1;g[e]&&_(g[e])},C=function(){var e=m().indexOf(b)-1;m()[e]&&_(m()[e])},A=function(){return Me(void 0,void 0,void 0,(function(){var e,t;return De(this,(function(n){switch(n.label){case 0:return b.match?(r(b),[4,(i=b.match.blockId,s=b,Me(void 0,void 0,void 0,(function(){var e,t;return De(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,a.select)("core/block-editor").getBlock(i))?(ee(t,s,e),s.applied=!0,[4,S(s)]):[2];case 1:return n.sent(),[2]}}))})))]):[2];case 1:return n.sent(),0===y().length?(T(),[2]):(e=g.indexOf(b),g[t=e+1]?_(g[t]):_(g[0]),[2])}var i,s}))}))},N=function(){return Me(void 0,void 0,void 0,(function(){var e,t;return De(this,(function(n){switch(n.label){case 0:return e=g.indexOf(b),g[t=e+1]?_(g[t]):g[0]?_(g[0]):T(),[4,P(b.uid)];case 1:return n.sent(),[2]}}))}))},O=function(){return Me(void 0,void 0,void 0,(function(){var e,t,n,r;return De(this,(function(i){switch(i.label){case 0:return b.match?(e=(0,a.select)("core/block-editor").getBlock(b.match.blockId))?(t=m(),n=t.indexOf(b),r=n-1,[4,j(e,b)]):[3,2]:[2];case 1:i.sent(),(t=m())[r]?_(t[r]):_(t[0]),i.label=2;case 2:return[2]}}))}))};return(0,i.jsxs)(i.Fragment,{children:[f&&(0,i.jsxs)(s.Modal,{title:(0,p.__)("Review Smart Links","wp-parsely"),className:"wp-parsely-smart-linking-review-modal",onRequestClose:T,shouldCloseOnClickOutside:!1,shouldCloseOnEsc:!1,children:[(0,i.jsx)(s.KeyboardShortcuts,{shortcuts:{left:C,right:E,up:C,down:E,a:function(){b&&!b.applied&&A()},r:function(){b&&(b.applied?O():N())}}}),(0,i.jsxs)("div",{className:"smart-linking-modal-body",children:[(0,i.jsx)(Pe,{links:g,activeLink:b,setSelectedLink:_}),(0,i.jsx)(Be,{link:b,hasNext:m().indexOf(b)0,onNext:E,onPrevious:C,onAccept:A,onReject:N,onRemove:O,onSelectInEditor:function(){if(b.match){var e=(0,a.select)("core/block-editor").getBlock(b.match.blockId);if(e){z.selectBlock(e.clientId);var t=document.querySelector('[data-block="'.concat(e.clientId,'"]'));if(t){var n=t.ownerDocument,r=t.querySelector('a[data-smartlink="'.concat(b.uid,'"]'));if(r){r.focus();var i=n.createRange();if(r.firstChild){i.setStart(r.firstChild,0),i.setEndAfter(r.firstChild);var s=n.getSelection();s&&(s.removeAllRanges(),s.addRange(i))}}}T()}}}})]})]}),l&&(0,i.jsxs)(s.Modal,{title:(0,p.__)("Review Smart Links","wp-parsely"),onRequestClose:function(){return L(!1)},className:"wp-parsely-smart-linking-close-dialog",children:[(0,p.__)("Are you sure you want to close? All un-accepted smart links will not be added.","wp-parsely"),(0,i.jsxs)("div",{className:"smart-linking-close-dialog-actions",children:[(0,i.jsx)(s.Button,{variant:"secondary",onClick:function(){return L(!1)},children:(0,p.__)("Go Back","wp-parsely")}),(0,i.jsx)(s.Button,{variant:"primary",onClick:function(){return L(!0)},children:(0,p.__)("Close","wp-parsely")})]})]})]})})),Fe=function(){return Fe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&_("success",/* translators: %d: number of smart links applied */ /* translators: %d: number of smart links applied */ +(0,p.sprintf)((0,p.__)("%s smart links successfully applied.","wp-parsely"),g),{type:"snackbar"}):y(0)}),[w]),(0,u.useEffect)((function(){if(!(Object.keys(O).length>0)){var e={maxLinksPerPost:c.SmartLinking.MaxLinks};ee(e)}}),[ee,c]);var me=(0,a.useSelect)((function(e){var t=e("core/block-editor"),r=t.getSelectedBlock,i=t.getBlock,s=t.getBlocks,a=e("core/editor"),o=a.getEditedPostContent,l=a.getCurrentPostAttribute;return{allBlocks:s(),selectedBlock:n?i(n):r(),postContent:o(),postPermalink:l("link")}}),[n]),we=me.allBlocks,be=me.selectedBlock,_e=me.postContent,xe=me.postPermalink,Se=function(e){return Ge(void 0,void 0,void 0,(function(){var t,n,r,i;return He(this,(function(s){switch(s.label){case 0:t=[],s.label=1;case 1:return s.trys.push([1,4,,9]),[4,te((n=T||!be)?le.All:le.Selected)];case 2:return s.sent(),a=xe.replace(/^https?:\/\//i,""),r=["http://"+a,"https://"+a],[4,ke.getInstance().generateSmartLinks(be&&!n?(0,F.getBlockContent)(be):_e,A,r)];case 3:return t=s.sent(),[3,9];case 4:if((i=s.sent()).code&&i.code===N.ParselyAborted)throw i.numRetries=3-e,i;return e>0&&i.retryFetch?(console.error(i),[4,se(!0)]):[3,8];case 5:return s.sent(),[4,ce()];case 6:return s.sent(),[4,Se(e-1)];case 7:return[2,s.sent()];case 8:throw i;case 9:return[2,t]}var a}))}))},Pe=function(){for(var e=[],t=0;t[type="button"]').forEach((function(e){e.setAttribute("disabled","disabled")}))},Le=function(){document.querySelectorAll('.edit-post-header__settings>[type="button"]').forEach((function(e){e.removeAttribute("disabled")})),U.unlockPostSaving("wp-parsely-block-overlay")};return(0,i.jsxs)("div",{className:"wp-parsely-smart-linking",children:[(0,i.jsx)(W,{isDetectingEnabled:!P,onLinkRemove:function(e){!function(e){Y(this,void 0,void 0,(function(){var t,n,r;return Q(this,(function(i){switch(i.label){case 0:return[4,ae((0,F.getBlockContent)(e),e.clientId)];case 1:return t=i.sent(),n=t.missingSmartLinks,r=t.didAnyFixes,n.forEach((function(e){(0,a.dispatch)(de).removeSmartLink(e.uid)})),[2,r]}}))}))}(e.block)}}),(0,i.jsxs)(s.PanelRow,{className:t,children:[(0,i.jsxs)("div",{className:"smart-linking-text",children:[(0,p.__)("Automatically insert links to your most relevant, top performing content.","wp-parsely"),(0,i.jsxs)(s.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-smart-linking-beta",target:"_blank",variant:"link",children:[(0,p.__)("Learn more about Parse.ly AI","wp-parsely"),(0,i.jsx)(G,{icon:H,size:18,className:"parsely-external-link-icon"})]})]}),E&&(0,i.jsx)(s.Notice,{status:"info",onRemove:function(){return $(null)},className:"wp-parsely-content-helper-error",children:E.Message()}),w&&g>0&&(0,i.jsx)(s.Notice,{status:"success",onRemove:function(){return b(!1)},className:"wp-parsely-smart-linking-suggested-links",children:(0,p.sprintf)(/* translators: 1 - number of smart links generated */ /* translators: 1 - number of smart links generated */ +(0,p.__)("Successfully added %s smart links.","wp-parsely"),g>0?g:C.length)}),(0,i.jsx)(he,{disabled:S,selectedBlock:null==be?void 0:be.clientId,onSettingChange:function(e,t){var n;f({SmartLinking:Fe(Fe({},c.SmartLinking),(n={},n[e]=t,n))}),"MaxLinks"===e&&ne(t)}}),(0,i.jsx)("div",{className:"smart-linking-generate",children:(0,i.jsx)(s.Button,{onClick:function(){return Ge(void 0,void 0,void 0,(function(){var e,t,n,r,i,s;return He(this,(function(a){switch(a.label){case 0:return[4,Z(!0)];case 1:return a.sent(),[4,ue()];case 2:return a.sent(),[4,$(null)];case 3:return a.sent(),b(!1),v.trackEvent("smart_linking_generate_pressed",{is_full_content:T,selected_block:null!==(s=null==be?void 0:be.name)&&void 0!==s?s:"none",context:o}),[4,Pe(T?"all":null==be?void 0:be.clientId)];case 4:a.sent(),e=setTimeout((function(){var e;Z(!1),v.trackEvent("smart_linking_generate_timeout",{is_full_content:T,selected_block:null!==(e=null==be?void 0:be.name)&&void 0!==e?e:"none",context:o}),je(T?"all":null==be?void 0:be.clientId)}),18e4),t=I,a.label=5;case 5:return a.trys.push([5,8,10,15]),[4,Se(3)];case 6:return n=a.sent(),[4,(l=n,Ge(void 0,void 0,void 0,(function(){var e;return He(this,(function(t){switch(t.label){case 0:return l=l.filter((function(e){return!D.some((function(t){return t.uid===e.uid&&t.applied}))})),e=xe.replace(/^https?:\/\//,"").replace(/\/+$/,""),l=l.filter((function(t){return!t.href.includes(e)||(console.warn("PCH Smart Linking: Skipping self-reference link: ".concat(t.href)),!1)})),l=(l=re(we,l,{}).filter((function(e){return e.match}))).filter((function(e){if(D.some((function(t){return t.text===e.text&&t.offset===e.offset})))return!1;if(!e.match)return!1;var t=e.match.blockLinkPosition,n=t+e.text.length;return!D.some((function(r){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,K(l)];case 1:return t.sent(),[2]}}))})))];case 7:return a.sent(),pe(!0),[3,15];case 8:return r=a.sent(),i=(0,p.__)("There was a problem generating smart links.","wp-parsely"),r.code&&r.code===N.ParselyAborted&&(i=(0,p.sprintf)(/* translators: %d: number of retry attempts, %s: attempt plural */ /* translators: %d: number of retry attempts, %s: attempt plural */ +(0,p.__)("The Smart Linking process was cancelled after %1$d %2$s.","wp-parsely"),r.numRetries,(0,p._n)("attempt","attempts",r.numRetries,"wp-parsely")),r.message=i),[4,$(r)];case 9:return a.sent(),_("error",i,{type:"snackbar"}),[3,15];case 10:return[4,Z(!1)];case 11:return a.sent(),[4,te(t)];case 12:return a.sent(),[4,se(!1)];case 13:return a.sent(),[4,je(T?"all":null==be?void 0:be.clientId)];case 14:return a.sent(),clearTimeout(e),[7];case 15:return[2]}var l}))}))},variant:"primary",isBusy:S,disabled:S,children:B?(0,p.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,p.__)("Retrying… Attempt %1$d of %2$d","wp-parsely"),M,3):S?(0,p.__)("Generating Smart Links…","wp-parsely"):(0,p.__)("Add Smart Links","wp-parsely")})}),V.length>0&&(0,i.jsx)("div",{className:"smart-linking-manage",children:(0,i.jsx)(s.Button,{onClick:function(){return Ge(void 0,void 0,void 0,(function(){var e;return He(this,(function(t){switch(t.label){case 0:return[4,oe()];case 1:return t.sent(),e=ie(),[4,K(e)];case 2:return t.sent(),pe(!0),[2]}}))}))},variant:"secondary",children:(0,p.__)("Review Smart Links","wp-parsely")})})]}),P&&(0,i.jsx)(Ve,{isOpen:P,onAppliedLink:function(){y((function(e){return e+1}))},onClose:function(){b(!0),pe(!1)}})]})},qe=function(){return qe=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=c){var u=t;(i=r/c)%1>1/o&&(u=i>10?1:2),u=parseFloat(i.toFixed(2))===parseFloat(i.toFixed(0))?0:u,s=i.toFixed(u),a=l}o=c})),s+n+a}var st=function(e){var n=e.data,r=e.isLoading,a=(0,u.useState)(t.Views),o=a[0],l=a[1],c=(0,u.useState)(!1),d=c[0],f=c[1];r||delete n.referrers.types.totals;var h=function(e){switch(e){case"social":return(0,p.__)("Social","wp-parsely");case"search":return(0,p.__)("Search","wp-parsely");case"other":return(0,p.__)("Other","wp-parsely");case"internal":return(0,p.__)("Internal","wp-parsely");case"direct":return(0,p.__)("Direct","wp-parsely")}return e},v=(0,p.sprintf)((0,p.__)("By %s","wp-parsely"),C(o)); +/* translators: %s: metric description */return(0,i.jsxs)(rt,{title:(0,p.__)("Categories","wp-parsely"),level:3,subtitle:v,isOpen:d,onClick:function(){return f(!d)},children:[d&&(0,i.jsx)("div",{className:"panel-settings",children:(0,i.jsx)(s.SelectControl,{value:o,prefix:(0,p.__)("By: ","wp-parsely"),onChange:function(e){L(e,t)&&l(e)},children:Object.values(t).map((function(e){return(0,i.jsxs)("option",{value:e,disabled:"avg_engaged"===e,children:[C(e),"avg_engaged"===e&&(0,p.__)(" (coming soon)","wp-parsely")]},e)}))})}),r?(0,i.jsx)("div",{className:"parsely-spinner-wrapper","data-testid":"parsely-spinner-wrapper",children:(0,i.jsx)(s.Spinner,{})}):(0,i.jsxs)("div",{children:[(0,i.jsx)("div",{className:"multi-percentage-bar",children:Object.entries(n.referrers.types).map((function(e){var t=e[0],n=e[1],r=(0,p.sprintf)(/* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ /* translators: 1: Referrer type, 2: Percentage value, %%: Escaped percent sign */ +(0,p.__)("%1$s: %2$s%%","wp-parsely"),h(t),n.viewsPercentage);return(0,i.jsx)(s.Tooltip /* translators: %s: percentage value */,{ /* translators: %s: percentage value */ -text:"".concat(h(t)," - ").concat((0,c.sprintf)((0,c.__)("%s%%","wp-parsely"),n.viewsPercentage)),delay:150,children:(0,s.jsx)("div",{"aria-label":r,className:"bar-fill "+t,style:{width:n.viewsPercentage+"%"}})},t)}))}),(0,s.jsx)("div",{className:"percentage-bar-labels",children:Object.entries(n.referrers.types).map((function(e){var t=e[0],n=e[1];return(0,s.jsxs)("div",{className:"single-label "+t,children:[(0,s.jsx)("div",{className:"label-color "+t}),(0,s.jsx)("div",{className:"label-text",children:h(t)}),(0,s.jsx)("div",{className:"label-value",children:be(n.views)})]},t)}))})]})]})},Pe=(0,s.jsx)(u.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,s.jsx)(u.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"})}),Se=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})}),je=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})}),Te=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.Path,{d:"M11 13h2v-2h-2v2zm-6 0h2v-2H5v2zm12-2v2h2v-2h-2z"})}),ke=function(){return ke=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]1?[2,Promise.reject(new U((0,c.sprintf)(/* translators: URL of the published post */ /* translators: URL of the published post */ -(0,c.__)("Multiple results were returned for the post %s by the Parse.ly API.","wp-parsely"),t),A.ParselyApiReturnedTooManyResults))]:[2,n[0]]}}))}))},t.prototype.fetchReferrerDataFromWpEndpoint=function(e,t,n){return De(this,void 0,void 0,(function(){return Fe(this,(function(r){switch(r.label){case 0:return[4,this.fetch({path:(0,ee.addQueryArgs)("/wp-parsely/v1/referrers/post/detail",Ve(Ve({},Be(e)),{itm_source:this.itmSource,total_views:n,url:t}))})];case 1:return[2,r.sent()]}}))}))},t}(te),He=function(){return He=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return n.sent(),[4,t(r-1)];case 2:return n.sent(),[3,4];case 3:d(e),o(!1),n.label=4;case 4:return[2]}}))}))})),[2]}))}))};return o(!0),t(1),function(){d(void 0)}}),[n]),(0,s.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,s.jsx)(me,{title:(0,c.__)("Performance Stats","wp-parsely"),icon:_e,dropdownChildren:function(e){var t=e.onClose;return(0,s.jsx)(We,{onClose:t})},children:(0,s.jsx)("div",{className:"panel-settings",children:(0,s.jsx)(i.SelectControl,{size:"__unstable-large",value:w.PerformanceStats.Period,prefix:(0,s.jsx)(i.__experimentalInputControlPrefixWrapper,{children:(0,c.__)("Period: ","wp-parsely")}),onChange:function(t){T(t,e)&&(_({PerformanceStats:He(He({},w.PerformanceStats),{Period:t})}),f.trackEvent("editor_sidebar_performance_period_changed",{period:t}))},children:Object.values(e).map((function(e){return(0,s.jsx)("option",{value:e,children:k(e)},e)}))})})}),p?p.Message():(0,s.jsxs)(s.Fragment,{children:[qe(w,"overview")&&(0,s.jsx)(Re,{data:g,isLoading:a}),qe(w,"categories")&&(0,s.jsx)(xe,{data:g,isLoading:a}),qe(w,"referrers")&&(0,s.jsx)(Ie,{data:g,isLoading:a})]}),window.wpParselyPostUrl&&(0,s.jsx)(i.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){f.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,c.__)("View this in Parse.ly","wp-parsely")})]})},Ke=function(e){var t=e.period;return(0,s.jsx)(i.Panel,{children:(0,s.jsx)(M,{children:(0,s.jsx)(Ye,{period:t})})})},Qe=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 s=0;for(r=Object.getOwnPropertySymbols(e);s=1&&(0,s.jsx)(i.__experimentalToggleGroupControlOption,{value:r.Tag,label:(0,c.__)("Tag","wp-parsely")}),a.categories.length>=1&&(0,s.jsx)(i.__experimentalToggleGroupControlOption,{value:r.Section,label:(0,c.__)("Section","wp-parsely")}),a.authors.length>=1&&(0,s.jsx)(i.__experimentalToggleGroupControlOption,{value:r.Author,label:(0,c.__)("Author","wp-parsely")})]})})},Je=function(e){var t=e.filter,n=e.label,a=e.postData,o=Qe(e,["filter","label","postData"]);return(0,s.jsx)("div",{className:"related-posts-filter-values",children:(0,s.jsx)(i.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return o.onFilterValueChange(e)},options:r.Tag===t.type?a.tags.map((function(e){return{value:e,label:e}})):r.Section===t.type?a.categories.map((function(e){return{value:e,label:e}})):r.Author===t.type?a.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},et=function(e){var t=e.filter,n=e.postData,i=e.label,a=Qe(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},l=function(){return r.Tag===t.type&&n.tags.length>1||r.Section===t.type&&n.categories.length>1||r.Author===t.type&&n.authors.length>1};return o()||l()?(0,s.jsxs)("div",{className:"related-posts-filter-settings",children:[o()&&(0,s.jsx)(Xe,{filter:t,label:i,onFilterTypeChange:a.onFilterTypeChange,postData:n}),l()&&(0,s.jsx)(Je,{filter:t,label:o()?void 0:i,onFilterValueChange:a.onFilterValueChange,postData:n})]}):null},tt=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})}),nt=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})});function rt(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,i=e.viewsIcon;return"views"===t?(0,s.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,s.jsx)("span",{className:"screen-reader-text",children:(0,c.__)("Number of Views","wp-parsely")}),i,be(n.views.toString())]}):"avg_engaged"===t?(0,s.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,s.jsx)("span",{className:"screen-reader-text",children:(0,c.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,s.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var st,it=function(){return(0,s.jsx)(i.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,s.jsx)(i.Rect,{width:"1",height:"40",fill:"#cccccc"})})},at=function(e){var t,n,r=e.metric,o=e.post,l=e.postContent,u=(0,a.useDispatch)("core/notices").createNotice,p=l&&(t=l,n=$(o.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,s.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,s.jsx)("div",{className:"related-post-title",children:(0,s.jsxs)("a",{href:o.url,target:"_blank",rel:"noreferrer",children:[(0,s.jsx)("span",{className:"screen-reader-text",children:(0,c.__)("View on website (opens new tab)","wp-parsely")}),o.title]})}),(0,s.jsx)("div",{className:"related-post-actions",children:(0,s.jsxs)("div",{className:"related-post-info",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"related-post-metric",children:(0,s.jsx)(rt,{metric:r,post:o,viewsIcon:(0,s.jsx)(D,{icon:Pe}),avgEngagedIcon:(0,s.jsx)(i.Dashicon,{icon:"clock",size:24})})}),p&&(0,s.jsx)("div",{className:"related-post-linked",children:(0,s.jsx)(i.Tooltip,{text:(0,c.__)("This post is linked in the content","wp-parsely"),children:(0,s.jsx)(D,{icon:tt,size:24})})})]}),(0,s.jsx)(it,{}),(0,s.jsxs)("div",{children:[(0,s.jsx)(i.Button,{icon:nt,iconSize:24,onClick:function(){navigator.clipboard.writeText(o.rawUrl).then((function(){u("success",(0,c.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,c.__)("Copy URL to clipboard","wp-parsely")}),(0,s.jsx)(i.Button,{icon:(0,s.jsx)(g,{}),iconSize:18,href:o.dashUrl,target:"_blank",label:(0,c.__)("View in Parse.ly","wp-parsely")})]})]})})]})},ot=window.wp.coreData,lt=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 __)}}(),ct=function(){return ct=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]1?[2,Promise.reject(new Z((0,p.sprintf)(/* translators: URL of the published post */ /* translators: URL of the published post */ +(0,p.__)("Multiple results were returned for the post %s by the Parse.ly API.","wp-parsely"),t),N.ParselyApiReturnedTooManyResults))]:[2,n[0]]}}))}))},t.prototype.fetchReferrerDataFromWpEndpoint=function(e,t,n){return xt(this,void 0,void 0,(function(){return kt(this,(function(r){switch(r.label){case 0:return[4,this.fetch({path:(0,me.addQueryArgs)("/wp-parsely/v1/referrers/post/detail",_t(_t({},wt(e)),{itm_source:this.itmSource,total_views:n,url:t}))})];case 1:return[2,r.sent()]}}))}))},t}(we),Pt=function(){return Pt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&e.retryFetch?[4,new Promise((function(e){return setTimeout(e,500)}))]:[3,3];case 1:return n.sent(),[4,t(r-1)];case 2:return n.sent(),[3,4];case 3:d(e),o(!1),n.label=4;case 4:return[2]}}))}))})),[2]}))}))};return o(!0),t(1),function(){d(void 0)}}),[n]),(0,i.jsxs)("div",{className:"wp-parsely-performance-panel",children:[(0,i.jsx)(rt,{title:(0,p.__)("Performance Stats","wp-parsely"),icon:nt,dropdownChildren:function(e){var t=e.onClose;return(0,i.jsx)(At,{onClose:t})},children:(0,i.jsx)("div",{className:"panel-settings",children:(0,i.jsx)(s.SelectControl,{size:"__unstable-large",value:m.PerformanceStats.Period,prefix:(0,i.jsx)(s.__experimentalInputControlPrefixWrapper,{children:(0,p.__)("Period: ","wp-parsely")}),onChange:function(t){L(t,e)&&(w({PerformanceStats:Pt(Pt({},m.PerformanceStats),{Period:t})}),v.trackEvent("editor_sidebar_performance_period_changed",{period:t}))},children:Object.values(e).map((function(e){return(0,i.jsx)("option",{value:e,children:E(e)},e)}))})})}),c?c.Message():(0,i.jsxs)(i.Fragment,{children:[Ct(m,"overview")&&(0,i.jsx)(yt,{data:h,isLoading:a}),Ct(m,"categories")&&(0,i.jsx)(st,{data:h,isLoading:a}),Ct(m,"referrers")&&(0,i.jsx)(mt,{data:h,isLoading:a})]}),window.wpParselyPostUrl&&(0,i.jsx)(s.Button,{className:"wp-parsely-view-post",variant:"primary",onClick:function(){v.trackEvent("editor_sidebar_view_post_pressed")},href:window.wpParselyPostUrl,rel:"noopener",target:"_blank",children:(0,p.__)("View this in Parse.ly","wp-parsely")})]})},Ot=function(e){var t=e.period;return(0,i.jsx)(s.Panel,{children:(0,i.jsx)(V,{children:(0,i.jsx)(Nt,{period:t})})})},Rt=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,i.jsx)(s.__experimentalToggleGroupControlOption,{value:r.Tag,label:(0,p.__)("Tag","wp-parsely")}),a.categories.length>=1&&(0,i.jsx)(s.__experimentalToggleGroupControlOption,{value:r.Section,label:(0,p.__)("Section","wp-parsely")}),a.authors.length>=1&&(0,i.jsx)(s.__experimentalToggleGroupControlOption,{value:r.Author,label:(0,p.__)("Author","wp-parsely")})]})})},Bt=function(e){var t=e.filter,n=e.label,a=e.postData,o=Rt(e,["filter","label","postData"]);return(0,i.jsx)("div",{className:"related-posts-filter-values",children:(0,i.jsx)(s.ComboboxControl,{__next40pxDefaultSize:!0,allowReset:!0,label:n,onChange:function(e){return o.onFilterValueChange(e)},options:r.Tag===t.type?a.tags.map((function(e){return{value:e,label:e}})):r.Section===t.type?a.categories.map((function(e){return{value:e,label:e}})):r.Author===t.type?a.authors.map((function(e){return{value:e,label:e}})):[],value:t.value})})},Mt=function(e){var t=e.filter,n=e.postData,s=e.label,a=Rt(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},l=function(){return r.Tag===t.type&&n.tags.length>1||r.Section===t.type&&n.categories.length>1||r.Author===t.type&&n.authors.length>1};return o()||l()?(0,i.jsxs)("div",{className:"related-posts-filter-settings",children:[o()&&(0,i.jsx)(It,{filter:t,label:s,onFilterTypeChange:a.onFilterTypeChange,postData:n}),l()&&(0,i.jsx)(Bt,{filter:t,label:o()?void 0:s,onFilterValueChange:a.onFilterValueChange,postData:n})]}):null},Dt=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.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"})}),Vt=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.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"})});function Ft(e){var t=e.metric,n=e.post,r=e.avgEngagedIcon,s=e.viewsIcon;return"views"===t?(0,i.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,i.jsx)("span",{className:"screen-reader-text",children:(0,p.__)("Number of Views","wp-parsely")}),s,it(n.views.toString())]}):"avg_engaged"===t?(0,i.jsxs)("span",{className:"parsely-post-metric-data",children:[(0,i.jsx)("span",{className:"screen-reader-text",children:(0,p.__)("Average Time","wp-parsely")}),r,n.avgEngaged]}):(0,i.jsx)("span",{className:"parsely-post-metric-data",children:"-"})}var Gt,Ht=function(){return(0,i.jsx)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"1",height:"40",viewBox:"0 0 1 40",fill:"none",children:(0,i.jsx)(s.Rect,{width:"1",height:"40",fill:"#cccccc"})})},zt=function(e){var t,n,r=e.metric,o=e.post,l=e.postContent,c=(0,a.useDispatch)("core/notices").createNotice,u=l&&(t=l,n=$(o.rawUrl),new RegExp("]*href=[\"'](http://|https://)?.*".concat(n,".*[\"'][^>]*>"),"i").test(t));return(0,i.jsxs)("div",{className:"related-post-single","data-testid":"related-post-single",children:[(0,i.jsx)("div",{className:"related-post-title",children:(0,i.jsxs)("a",{href:o.url,target:"_blank",rel:"noreferrer",children:[(0,i.jsx)("span",{className:"screen-reader-text",children:(0,p.__)("View on website (opens new tab)","wp-parsely")}),o.title]})}),(0,i.jsx)("div",{className:"related-post-actions",children:(0,i.jsxs)("div",{className:"related-post-info",children:[(0,i.jsxs)("div",{children:[(0,i.jsx)("div",{className:"related-post-metric",children:(0,i.jsx)(Ft,{metric:r,post:o,viewsIcon:(0,i.jsx)(G,{icon:at}),avgEngagedIcon:(0,i.jsx)(s.Dashicon,{icon:"clock",size:24})})}),u&&(0,i.jsx)("div",{className:"related-post-linked",children:(0,i.jsx)(s.Tooltip,{text:(0,p.__)("This post is linked in the content","wp-parsely"),children:(0,i.jsx)(G,{icon:Dt,size:24})})})]}),(0,i.jsx)(Ht,{}),(0,i.jsxs)("div",{children:[(0,i.jsx)(s.Button,{icon:Vt,iconSize:24,onClick:function(){navigator.clipboard.writeText(o.rawUrl).then((function(){c("success",(0,p.__)("URL copied to clipboard","wp-parsely"),{type:"snackbar"})}))},label:(0,p.__)("Copy URL to clipboard","wp-parsely")}),(0,i.jsx)(s.Button,{icon:(0,i.jsx)(y,{}),iconSize:18,href:o.dashUrl,target:"_blank",label:(0,p.__)("View in Parse.ly","wp-parsely")})]})]})})]})},Ut=window.wp.coreData,qt=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 __)}}(),Zt=function(){return Zt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&u.every(Number.isInteger)?null!==(n=o("taxonomy","category",{include:u,context:"view"}))&&void 0!==n?n:void 0:null,tags:a=Array.isArray(p)&&p.length>0&&p.every(Number.isInteger)?null!==(r=o("taxonomy","post_tag",{include:p,context:"view"}))&&void 0!==r?r:void 0:null,isReady:void 0!==s&&void 0!==i&&void 0!==a}}),[]);return{authors:e.authors,categories:e.categories,tags:e.tags,isReady:e.isReady}}(),w=v.authors,_=v.categories,m=v.tags,b=v.isReady;(0,l.useEffect)((function(){if(b){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})):[]};y({authors:e(w),categories:e(_),tags:e(m)})}}),[w,_,m,b]);var x=(0,l.useState)(!0),P=x[0],j=x[1],E=(0,l.useState)(),A=E[0],N=E[1],O=(0,l.useState)(),R=O[0],I=O[1],B=(0,l.useState)([]),M=B[0],V=B[1],D=(0,l.useState)({type:o.RelatedPosts.FilterBy,value:o.RelatedPosts.FilterValue}),F=D[0],G=D[1],H=(0,l.useState)(void 0),z=H[0],U=H[1],$=(0,L.useDebounce)(U,1e3);(0,a.useSelect)((function(e){if("undefined"==typeof jest){var t=e("core/editor").getEditedPostContent;$(t())}else $("Jest test is running")}),[$]);var Z=function(e,t){u({RelatedPosts:ft(ft({},o.RelatedPosts),{FilterBy:e,FilterValue:t})})};return(0,l.useEffect)((function(){var e,t,n=function(e){return ht(void 0,void 0,void 0,(function(){return gt(this,(function(t){return dt.getInstance().getRelatedPosts(p,d,F).then((function(e){V(e.posts),I(e.message),j(!1)})).catch((function(t){return ht(void 0,void 0,void 0,(function(){return gt(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:j(!1),N(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},s=r.Author===F.type,i=r.Tag===F.type,a=r.Section===F.type,o=r.Unavailable===F.type,l=0===g.authors.length,c=0===g.tags.length,u=0===g.categories.length,f=s&&!g.authors.includes(F.value),h=i&&!g.tags.includes(F.value),y=a&&!g.categories.includes(F.value);return j(!0),o||i&&c||a&&u||s&&l?Object.values(g).every((function(e){return 0===e.length}))||G((e="",t=r.Unavailable,g.tags.length>=1?(t=r.Tag,e=g.tags[0]):g.categories.length>=1?(t=r.Section,e=g.categories[0]):g.authors.length>=1&&(t=r.Author,e=g.authors[0]),{type:t,value:e})):h?G({type:r.Tag,value:g.tags[0]}):y?G({type:r.Section,value:g.categories[0]}):f?G({type:r.Author,value:g.authors[0]}):n(1),function(){j(!1),V([]),I(""),N(void 0)}}),[p,d,F,g]),0===g.authors.length&&0===g.categories.length&&0===g.tags.length&&b?(0,s.jsx)("div",{className:"wp-parsely-related-posts",children:(0,s.jsx)("div",{className:"related-posts-body",children:(0,c.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,s.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,s.jsx)("div",{className:"related-posts-description",children:(0,c.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,s.jsxs)("div",{className:"related-posts-body",children:[(0,s.jsxs)("div",{className:"related-posts-settings",children:[(0,s.jsx)(i.SelectControl,{size:"__unstable-large",onChange:function(e){var n;T(n=e,t)&&(u({RelatedPosts:ft(ft({},o.RelatedPosts),{Metric:n})}),f.trackEvent("related_posts_metric_changed",{metric:n}))},prefix:(0,s.jsx)(i.__experimentalInputControlPrefixWrapper,{children:(0,c.__)("Metric: ","wp-parsely")}),value:d,children:Object.values(t).map((function(e){return(0,s.jsx)("option",{value:e,children:C(e)},e)}))}),(0,s.jsx)(i.SelectControl,{size:"__unstable-large",value:p,prefix:(0,s.jsxs)(i.__experimentalInputControlPrefixWrapper,{children:[(0,c.__)("Period: ","wp-parsely")," "]}),onChange:function(t){return function(t){T(t,e)&&(u({RelatedPosts:ft(ft({},o.RelatedPosts),{Period:t})}),f.trackEvent("related_posts_period_changed",{period:t}))}(t)},children:Object.values(e).map((function(e){return(0,s.jsx)("option",{value:e,children:k(e)},e)}))})]}),(0,s.jsx)(et,{label:(0,c.__)("Filter by","wp-parsely"),filter:F,onFilterTypeChange:function(e){if(T(e,r)){var t="",n=e;r.Tag===n&&(t=g.tags[0]),r.Section===n&&(t=g.categories[0]),r.Author===n&&(t=g.authors[0]),""!==t&&(Z(n,t),G({type:n,value:t}),f.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(Z(F.type,e),G(ft(ft({},F),{value:e})))},postData:g}),(0,s.jsxs)("div",{className:"related-posts-wrapper",children:[(0,s.jsx)("div",{children:(0,s.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:r.Tag===F.type?(0,c.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ -(0,c.__)("Top related posts with the “%1$s” tag in the %2$s.","wp-parsely"),F.value,k(p,!0)):r.Section===F.type?(0,c.sprintf)(/* translators: 1: section name, 2: period */ /* translators: 1: section name, 2: period */ -(0,c.__)("Top related posts in the “%1$s” section in the %2$s.","wp-parsely"),F.value,k(p,!0)):r.Author===F.type?(0,c.sprintf)(/* translators: 1: author name, 2: period */ /* translators: 1: author name, 2: period */ -(0,c.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),F.value,k(p,!0)):null!=R?R:""})}),A&&A.Message(),P&&(0,s.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,c.__)("Loading…","wp-parsely")}),!P&&!A&&0===M.length&&(0,s.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,c.__)("No related posts found.","wp-parsely")}),!P&&M.length>0&&(0,s.jsx)("div",{className:"related-posts-list",children:M.map((function(e){return(0,s.jsx)(at,{metric:d,post:e,postContent:z},e.id)}))})]})]})]})},vt=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.Path,{d:"m19 7-3-3-8.5 8.5-1 4 4-1L19 7Zm-7 11.5H5V20h7v-1.5Z"})}),wt=function(){return(0,s.jsx)(i.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",children:(0,s.jsx)(i.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"})})},_t={journalist:{label:(0,c.__)("Journalist","wp-parsely")},editorialWriter:{label:(0,c.__)("Editorial Writer","wp-parsely")},investigativeReporter:{label:(0,c.__)("Investigative Reporter","wp-parsely")},techAnalyst:{label:(0,c.__)("Tech Analyst","wp-parsely")},businessAnalyst:{label:(0,c.__)("Business Analyst","wp-parsely")},culturalCommentator:{label:(0,c.__)("Cultural Commentator","wp-parsely")},scienceCorrespondent:{label:(0,c.__)("Science Correspondent","wp-parsely")},politicalAnalyst:{label:(0,c.__)("Political Analyst","wp-parsely")},healthWellnessAdvocate:{label:(0,c.__)("Health and Wellness Advocate","wp-parsely")},environmentalJournalist:{label:(0,c.__)("Environmental Journalist","wp-parsely")},custom:{label:(0,c.__)("Custom Persona","wp-parsely"),icon:vt}},mt=Object.keys(_t),bt=function(e){return"custom"===e||""===e?_t.custom.label:xt(e)?e:_t[e].label},xt=function(e){return!mt.includes(e)||"custom"===e},Pt=function(e){var t=e.value,n=e.onChange,r=(0,l.useState)(""),a=r[0],o=r[1],u=(0,L.useDebounce)(n,500);return(0,s.jsx)("div",{className:"parsely-persona-selector-custom",children:(0,s.jsx)(i.TextControl,{value:a||t,placeholder:(0,c.__)("Enter a custom persona…","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),u(e),o(e)}})})},St=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,c.__)("Select a persona…","wp-parsely"):n,a=e.label,o=void 0===a?(0,c.__)("Persona","wp-parsely"):a,l=e.onChange,u=e.onDropdownChange,p=e.disabled,d=void 0!==p&&p,f=e.allowCustom,h=void 0!==f&&f;return(0,s.jsxs)(i.Disabled,{isDisabled:d,children:[o&&(0,s.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,s.jsx)(i.DropdownMenu,{label:(0,c.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(d?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"parsely-persona-selector-label",children:xt(t)?_t.custom.label:r}),(0,s.jsx)(wt,{})]})},children:function(e){var n=e.onClose;return(0,s.jsx)(i.MenuGroup,{label:(0,c.__)("Persona","wp-parsely"),children:(0,s.jsx)(s.Fragment,{children:mt.map((function(e){if(!h&&"custom"===e)return null;var r=_t[e],a=e===t||xt(t)&&"custom"===e;return(0,s.jsxs)(i.MenuItem,{isSelected:a,className:a?"is-selected":"",role:"menuitemradio",onClick:function(){null==u||u(e),l(e),n(),"custom"===e&&setTimeout((function(){var e=document.querySelector(".parsely-persona-selector-custom input");e&&e.focus()}),0)},children:[r.icon&&(0,s.jsx)(D,{icon:r.icon}),r.label]},e)}))})})}}),h&&xt(t)&&(0,s.jsx)(Pt,{onChange:function(e){l(""!==e?e:"custom")},value:"custom"===t?"":t})]})},jt={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:vt}},Tt=Object.keys(jt),kt=function(e){return"custom"===e||""===e?jt.custom.label:Ct(e)?e:jt[e].label},Ct=function(e){return!Tt.includes(e)||"custom"===e},Et=function(e){var t=e.value,n=e.onChange,r=(0,l.useState)(""),a=r[0],o=r[1],u=(0,L.useDebounce)(n,500);return(0,s.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,s.jsx)(i.TextControl,{value:a||t,placeholder:(0,c.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),u(e),o(e)}})})},At=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,c.__)("Select a tone","wp-parsely"):n,a=e.label,o=void 0===a?(0,c.__)("Tone","wp-parsely"):a,l=e.onChange,u=e.onDropdownChange,p=e.disabled,d=void 0!==p&&p,f=e.allowCustom,h=void 0!==f&&f;return(0,s.jsxs)(i.Disabled,{isDisabled:d,children:[(0,s.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,s.jsx)(i.DropdownMenu,{label:(0,c.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(d?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"parsely-tone-selector-label",children:Ct(t)?jt.custom.label:r}),(0,s.jsx)(wt,{})]})},children:function(e){var n=e.onClose;return(0,s.jsx)(i.MenuGroup,{label:(0,c.__)("Select a tone","wp-parsely"),children:(0,s.jsx)(s.Fragment,{children:Tt.map((function(e){if(!h&&"custom"===e)return null;var r=jt[e],a=e===t||Ct(t)&&"custom"===e;return(0,s.jsxs)(i.MenuItem,{isSelected:a,className:a?"is-selected":"",role:"menuitemradio",onClick:function(){null==u||u(e),l(e),n(),"custom"===e&&setTimeout((function(){var e=document.querySelector(".parsely-tone-selector-custom input");e&&e.focus()}),0)},children:[r.icon&&(0,s.jsx)(D,{icon:r.icon}),r.label]},e)}))})})}}),h&&Ct(t)&&(0,s.jsx)(Et,{onChange:function(e){l(""!==e?e:"custom")},value:"custom"===t?"":t})]})},Nt=(0,s.jsx)(u.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,s.jsx)(u.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"})}),Lt=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})}),Ot=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})}),Rt=(0,s.jsx)(u.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,s.jsx)(u.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"})}),It=function(){return It=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0&&s[s.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]0?(0,s.jsx)("span",{className:"parsely-write-titles-text",children:(0,l.createInterpolateElement)( +message:(0,p.sprintf)((0,p.__)('by author "%1$s"',"wp-parsely"),n.value)};throw new Z((0,p.__)("No valid filter type has been specified.","wp-parsely"),N.CannotFormulateApiQuery)},t}(we),Yt=function(){return Yt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&u.every(Number.isInteger)?null!==(n=o("taxonomy","category",{include:u,context:"view"}))&&void 0!==n?n:void 0:null,tags:a=Array.isArray(p)&&p.length>0&&p.every(Number.isInteger)?null!==(r=o("taxonomy","post_tag",{include:p,context:"view"}))&&void 0!==r?r:void 0:null,isReady:void 0!==i&&void 0!==s&&void 0!==a}}),[]);return{authors:e.authors,categories:e.categories,tags:e.tags,isReady:e.isReady}}(),m=y.authors,w=y.categories,b=y.tags,_=y.isReady;(0,u.useEffect)((function(){if(_){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})):[]};g({authors:e(m),categories:e(w),tags:e(b)})}}),[m,w,b,_]);var x=(0,u.useState)(!0),k=x[0],S=x[1],P=(0,u.useState)(),T=P[0],A=P[1],N=(0,u.useState)(),O=N[0],I=N[1],B=(0,u.useState)([]),M=B[0],D=B[1],V=(0,u.useState)({type:o.RelatedPosts.FilterBy,value:o.RelatedPosts.FilterValue}),F=V[0],G=V[1],H=(0,u.useState)(void 0),z=H[0],U=H[1],q=(0,R.useDebounce)(U,1e3);(0,a.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,t){l({RelatedPosts:Yt(Yt({},o.RelatedPosts),{FilterBy:e,FilterValue:t})})};return(0,u.useEffect)((function(){var e,t,n=function(e){return Qt(void 0,void 0,void 0,(function(){return Xt(this,(function(t){return Kt.getInstance().getRelatedPosts(c,d,F).then((function(e){D(e.posts),I(e.message),S(!1)})).catch((function(t){return Qt(void 0,void 0,void 0,(function(){return Xt(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:S(!1),A(t),r.label=4;case 4:return[2]}}))}))})),[2]}))}))},i=r.Author===F.type,s=r.Tag===F.type,a=r.Section===F.type,o=r.Unavailable===F.type,l=0===h.authors.length,u=0===h.tags.length,p=0===h.categories.length,f=i&&!h.authors.includes(F.value),v=s&&!h.tags.includes(F.value),g=a&&!h.categories.includes(F.value);return S(!0),o||s&&u||a&&p||i&&l?Object.values(h).every((function(e){return 0===e.length}))||G((e="",t=r.Unavailable,h.tags.length>=1?(t=r.Tag,e=h.tags[0]):h.categories.length>=1?(t=r.Section,e=h.categories[0]):h.authors.length>=1&&(t=r.Author,e=h.authors[0]),{type:t,value:e})):v?G({type:r.Tag,value:h.tags[0]}):g?G({type:r.Section,value:h.categories[0]}):f?G({type:r.Author,value:h.authors[0]}):n(1),function(){S(!1),D([]),I(""),A(void 0)}}),[c,d,F,h]),0===h.authors.length&&0===h.categories.length&&0===h.tags.length&&_?(0,i.jsx)("div",{className:"wp-parsely-related-posts",children:(0,i.jsx)("div",{className:"related-posts-body",children:(0,p.__)("Error: No author, section, or tags could be found for this post.","wp-parsely")})}):(0,i.jsxs)("div",{className:"wp-parsely-related-posts",children:[(0,i.jsx)("div",{className:"related-posts-description",children:(0,p.__)("Find top-performing related posts based on a key metric.","wp-parsely")}),(0,i.jsxs)("div",{className:"related-posts-body",children:[(0,i.jsxs)("div",{className:"related-posts-settings",children:[(0,i.jsx)(s.SelectControl,{size:"__unstable-large",onChange:function(e){var n;L(n=e,t)&&(l({RelatedPosts:Yt(Yt({},o.RelatedPosts),{Metric:n})}),v.trackEvent("related_posts_metric_changed",{metric:n}))},prefix:(0,i.jsx)(s.__experimentalInputControlPrefixWrapper,{children:(0,p.__)("Metric: ","wp-parsely")}),value:d,children:Object.values(t).map((function(e){return(0,i.jsx)("option",{value:e,children:C(e)},e)}))}),(0,i.jsx)(s.SelectControl,{size:"__unstable-large",value:c,prefix:(0,i.jsxs)(s.__experimentalInputControlPrefixWrapper,{children:[(0,p.__)("Period: ","wp-parsely")," "]}),onChange:function(t){return function(t){L(t,e)&&(l({RelatedPosts:Yt(Yt({},o.RelatedPosts),{Period:t})}),v.trackEvent("related_posts_period_changed",{period:t}))}(t)},children:Object.values(e).map((function(e){return(0,i.jsx)("option",{value:e,children:E(e)},e)}))})]}),(0,i.jsx)(Mt,{label:(0,p.__)("Filter by","wp-parsely"),filter:F,onFilterTypeChange:function(e){if(L(e,r)){var t="",n=e;r.Tag===n&&(t=h.tags[0]),r.Section===n&&(t=h.categories[0]),r.Author===n&&(t=h.authors[0]),""!==t&&(Z(n,t),G({type:n,value:t}),v.trackEvent("related_posts_filter_type_changed",{filter_type:n}))}},onFilterValueChange:function(e){"string"==typeof e&&(Z(F.type,e),G(Yt(Yt({},F),{value:e})))},postData:h}),(0,i.jsxs)("div",{className:"related-posts-wrapper",children:[(0,i.jsx)("div",{children:(0,i.jsx)("p",{className:"related-posts-descr","data-testid":"parsely-related-posts-descr",children:r.Tag===F.type?(0,p.sprintf)(/* translators: 1: tag name, 2: period */ /* translators: 1: tag name, 2: period */ +(0,p.__)("Top related posts with the “%1$s” tag in the %2$s.","wp-parsely"),F.value,E(c,!0)):r.Section===F.type?(0,p.sprintf)(/* translators: 1: section name, 2: period */ /* translators: 1: section name, 2: period */ +(0,p.__)("Top related posts in the “%1$s” section in the %2$s.","wp-parsely"),F.value,E(c,!0)):r.Author===F.type?(0,p.sprintf)(/* translators: 1: author name, 2: period */ /* translators: 1: author name, 2: period */ +(0,p.__)("Top related posts by %1$s in the %2$s.","wp-parsely"),F.value,E(c,!0)):null!=O?O:""})}),T&&T.Message(),k&&(0,i.jsx)("div",{className:"related-posts-loading-message","data-testid":"parsely-related-posts-loading-message",children:(0,p.__)("Loading…","wp-parsely")}),!k&&!T&&0===M.length&&(0,i.jsx)("div",{className:"related-posts-empty","data-testid":"parsely-related-posts-empty",children:(0,p.__)("No related posts found.","wp-parsely")}),!k&&M.length>0&&(0,i.jsx)("div",{className:"related-posts-list",children:M.map((function(e){return(0,i.jsx)(zt,{metric:d,post:e,postContent:z},e.id)}))})]})]})]})},en=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.Path,{d:"m19 7-3-3-8.5 8.5-1 4 4-1L19 7Zm-7 11.5H5V20h7v-1.5Z"})}),tn=function(){return(0,i.jsx)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",children:(0,i.jsx)(s.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"})})},nn={journalist:{label:(0,p.__)("Journalist","wp-parsely")},editorialWriter:{label:(0,p.__)("Editorial Writer","wp-parsely")},investigativeReporter:{label:(0,p.__)("Investigative Reporter","wp-parsely")},techAnalyst:{label:(0,p.__)("Tech Analyst","wp-parsely")},businessAnalyst:{label:(0,p.__)("Business Analyst","wp-parsely")},culturalCommentator:{label:(0,p.__)("Cultural Commentator","wp-parsely")},scienceCorrespondent:{label:(0,p.__)("Science Correspondent","wp-parsely")},politicalAnalyst:{label:(0,p.__)("Political Analyst","wp-parsely")},healthWellnessAdvocate:{label:(0,p.__)("Health and Wellness Advocate","wp-parsely")},environmentalJournalist:{label:(0,p.__)("Environmental Journalist","wp-parsely")},custom:{label:(0,p.__)("Custom Persona","wp-parsely"),icon:en}},rn=Object.keys(nn),sn=function(e){return"custom"===e||""===e?nn.custom.label:an(e)?e:nn[e].label},an=function(e){return!rn.includes(e)||"custom"===e},on=function(e){var t=e.value,n=e.onChange,r=(0,u.useState)(""),a=r[0],o=r[1],l=(0,R.useDebounce)(n,500);return(0,i.jsx)("div",{className:"parsely-persona-selector-custom",children:(0,i.jsx)(s.TextControl,{value:a||t,placeholder:(0,p.__)("Enter a custom persona…","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),l(e),o(e)}})})},ln=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,p.__)("Select a persona…","wp-parsely"):n,a=e.label,o=void 0===a?(0,p.__)("Persona","wp-parsely"):a,l=e.onChange,c=e.onDropdownChange,u=e.disabled,d=void 0!==u&&u,f=e.allowCustom,h=void 0!==f&&f;return(0,i.jsxs)(s.Disabled,{isDisabled:d,children:[o&&(0,i.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,i.jsx)(s.DropdownMenu,{label:(0,p.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(d?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("div",{className:"parsely-persona-selector-label",children:an(t)?nn.custom.label:r}),(0,i.jsx)(tn,{})]})},children:function(e){var n=e.onClose;return(0,i.jsx)(s.MenuGroup,{label:(0,p.__)("Persona","wp-parsely"),children:(0,i.jsx)(i.Fragment,{children:rn.map((function(e){if(!h&&"custom"===e)return null;var r=nn[e],a=e===t||an(t)&&"custom"===e;return(0,i.jsxs)(s.MenuItem,{isSelected:a,className:a?"is-selected":"",role:"menuitemradio",onClick:function(){null==c||c(e),l(e),n(),"custom"===e&&setTimeout((function(){var e=document.querySelector(".parsely-persona-selector-custom input");e&&e.focus()}),0)},children:[r.icon&&(0,i.jsx)(G,{icon:r.icon}),r.label]},e)}))})})}}),h&&an(t)&&(0,i.jsx)(on,{onChange:function(e){l(""!==e?e:"custom")},value:"custom"===t?"":t})]})},cn={neutral:{label:(0,p.__)("Neutral","wp-parsely")},formal:{label:(0,p.__)("Formal","wp-parsely")},humorous:{label:(0,p.__)("Humorous","wp-parsely")},confident:{label:(0,p.__)("Confident","wp-parsely")},provocative:{label:(0,p.__)("Provocative","wp-parsely")},serious:{label:(0,p.__)("Serious","wp-parsely")},inspirational:{label:(0,p.__)("Inspirational","wp-parsely")},skeptical:{label:(0,p.__)("Skeptical","wp-parsely")},conversational:{label:(0,p.__)("Conversational","wp-parsely")},analytical:{label:(0,p.__)("Analytical","wp-parsely")},custom:{label:(0,p.__)("Custom Tone","wp-parsely"),icon:en}},un=Object.keys(cn),pn=function(e){return"custom"===e||""===e?cn.custom.label:dn(e)?e:cn[e].label},dn=function(e){return!un.includes(e)||"custom"===e},fn=function(e){var t=e.value,n=e.onChange,r=(0,u.useState)(""),a=r[0],o=r[1],l=(0,R.useDebounce)(n,500);return(0,i.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,i.jsx)(s.TextControl,{value:a||t,placeholder:(0,p.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void o("");e.length>32&&(e=e.slice(0,32)),l(e),o(e)}})})},hn=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,p.__)("Select a tone","wp-parsely"):n,a=e.label,o=void 0===a?(0,p.__)("Tone","wp-parsely"):a,l=e.onChange,c=e.onDropdownChange,u=e.disabled,d=void 0!==u&&u,f=e.allowCustom,h=void 0!==f&&f;return(0,i.jsxs)(s.Disabled,{isDisabled:d,children:[(0,i.jsx)("div",{className:"wp-parsely-dropdown-label",children:o}),(0,i.jsx)(s.DropdownMenu,{label:(0,p.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(d?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{children:(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("div",{className:"parsely-tone-selector-label",children:dn(t)?cn.custom.label:r}),(0,i.jsx)(tn,{})]})},children:function(e){var n=e.onClose;return(0,i.jsx)(s.MenuGroup,{label:(0,p.__)("Select a tone","wp-parsely"),children:(0,i.jsx)(i.Fragment,{children:un.map((function(e){if(!h&&"custom"===e)return null;var r=cn[e],a=e===t||dn(t)&&"custom"===e;return(0,i.jsxs)(s.MenuItem,{isSelected:a,className:a?"is-selected":"",role:"menuitemradio",onClick:function(){null==c||c(e),l(e),n(),"custom"===e&&setTimeout((function(){var e=document.querySelector(".parsely-tone-selector-custom input");e&&e.focus()}),0)},children:[r.icon&&(0,i.jsx)(G,{icon:r.icon}),r.label]},e)}))})})}}),h&&dn(t)&&(0,i.jsx)(fn,{onChange:function(e){l(""!==e?e:"custom")},value:"custom"===t?"":t})]})},vn=(0,i.jsx)(d.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(d.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,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.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"})}),yn=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.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"})}),mn=(0,i.jsx)(d.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(d.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"})}),wn=function(){return wn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0?(0,i.jsx)("span",{className:"parsely-write-titles-text",children:(0,u.createInterpolateElement)( // translators: %1$s is the tone, %2$s is the persona. // translators: %1$s is the tone, %2$s is the persona. -(0,c.__)("We've generated a few titles based on the content of your post, written as a .","wp-parsely"),{tone:(0,s.jsx)("strong",{children:kt(d)}),persona:(0,s.jsx)("strong",{children:bt(y)})})}):(0,c.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,s.jsxs)(i.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-title-suggestions-beta",target:"_blank",variant:"link",children:[(0,c.__)("Learn more about Parse.ly AI","wp-parsely"),(0,s.jsx)(D,{icon:F,size:18,className:"parsely-external-link-icon"})]})]}),o&&(0,s.jsx)(i.Notice,{status:"info",className:"wp-parsely-content-helper-error",children:o.Message()}),void 0!==j&&(0,s.jsx)(zt,{title:j,type:st.PostTitle,isOriginal:!0}),00&&(0,s.jsx)(Ut,{pinnedTitles:b,isOpen:!0}),m.length>0&&(0,s.jsx)(qt,{suggestions:m,isOpen:!0,isLoading:_})]}),(0,s.jsx)($t,{isLoading:_,onPersonaChange:function(e){L("Persona",e),v(e)},onSettingChange:L,onToneChange:function(e){L("Tone",e),h(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,s.jsx)("div",{className:"title-suggestions-generate",children:(0,s.jsxs)(i.Button,{variant:"primary",isBusy:_,disabled:_||"custom"===d||"custom"===y,onClick:function(){return Qt(void 0,void 0,void 0,(function(){return Xt(this,(function(e){switch(e.label){case 0:return u(void 0),!1!==_?[3,2]:(f.trackEvent("title_suggestions_generate_pressed",{request_more:m.length>0,total_titles:m.length,total_pinned:m.filter((function(e){return e.isPinned})).length,tone:d,persona:y}),[4,(t=st.PostTitle,n=O,r=d,s=y,Qt(void 0,void 0,void 0,(function(){var e,i,a;return Xt(this,(function(o){switch(o.label){case 0:return[4,C(!0)];case 1:o.sent(),e=Yt.getInstance(),o.label=2;case 2:return o.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,s)];case 3:return i=o.sent(),[4,k(t,i)];case 4:return o.sent(),[3,6];case 5:return a=o.sent(),u(a),k(t,[]),[3,6];case 6:return[4,C(!1)];case 7:return o.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,s}))}))},children:[_&&(0,c.__)("Generating Titles…","wp-parsely"),!_&&x.length>0&&(0,c.__)("Generate More","wp-parsely"),!_&&0===x.length&&(0,c.__)("Generate Titles","wp-parsely")]})})]})})},en=function(){return en=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,i.jsx)("strong",{children:pn(d)}),persona:(0,i.jsx)("strong",{children:sn(g)})})}):(0,p.__)("Use Parse.ly AI to generate a title for your post.","wp-parsely"),(0,i.jsxs)(s.Button,{href:"https://docs.parse.ly/plugin-content-helper/#h-title-suggestions-beta",target:"_blank",variant:"link",children:[(0,p.__)("Learn more about Parse.ly AI","wp-parsely"),(0,i.jsx)(G,{icon:H,size:18,className:"parsely-external-link-icon"})]})]}),o&&(0,i.jsx)(s.Notice,{status:"info",className:"wp-parsely-content-helper-error",children:o.Message()}),void 0!==S&&(0,i.jsx)(Ln,{title:S,type:Gt.PostTitle,isOriginal:!0}),00&&(0,i.jsx)(En,{pinnedTitles:_,isOpen:!0}),b.length>0&&(0,i.jsx)(An,{suggestions:b,isOpen:!0,isLoading:w})]}),(0,i.jsx)(Cn,{isLoading:w,onPersonaChange:function(e){N("Persona",e),y(e)},onSettingChange:N,onToneChange:function(e){N("Tone",e),f(e)},persona:t.TitleSuggestions.Persona,tone:t.TitleSuggestions.Tone}),(0,i.jsx)("div",{className:"title-suggestions-generate",children:(0,i.jsxs)(s.Button,{variant:"primary",isBusy:w,disabled:w||"custom"===d||"custom"===g,onClick:function(){return In(void 0,void 0,void 0,(function(){return Bn(this,(function(e){switch(e.label){case 0:return l(void 0),!1!==w?[3,2]:(v.trackEvent("title_suggestions_generate_pressed",{request_more:b.length>0,total_titles:b.length,total_pinned:b.filter((function(e){return e.isPinned})).length,tone:d,persona:g}),[4,(t=Gt.PostTitle,n=O,r=d,i=g,In(void 0,void 0,void 0,(function(){var e,s,a;return Bn(this,(function(o){switch(o.label){case 0:return[4,L(!0)];case 1:o.sent(),e=On.getInstance(),o.label=2;case 2:return o.trys.push([2,5,,6]),[4,e.generateTitles(n,3,r,i)];case 3:return s=o.sent(),[4,T(t,s)];case 4:return o.sent(),[3,6];case 5:return a=o.sent(),l(a),T(t,[]),[3,6];case 6:return[4,L(!1)];case 7:return o.sent(),[2]}}))})))]);case 1:e.sent(),e.label=2;case 2:return[2]}var t,n,r,i}))}))},children:[w&&(0,p.__)("Generating Titles…","wp-parsely"),!w&&x.length>0&&(0,p.__)("Generate More","wp-parsely"),!w&&0===x.length&&(0,p.__)("Generate Titles","wp-parsely")]})})]})})},Dn=function(){return Dn=Object.assign||function(e){for(var t,n=1,r=arguments.length;n array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-edit-post', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'ce7a57270255db9784f6'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-edit-post', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '1c19550f70ae7ceace8b'); diff --git a/build/content-helper/excerpt-generator.css b/build/content-helper/excerpt-generator.css index 8f0505aa7..039140a6b 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-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green:#59a744;--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;--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 .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} diff --git a/jest.config.js b/jest.config.js index d4b0472b2..76088444a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,4 +5,9 @@ module.exports = { ...baseConfig, silent: false, verbose: true, + globals: { TextEncoder, TextDecoder }, + setupFiles: [ './jest.setup.js' ], + transformIgnorePatterns: [ + 'node_modules/(?!(client-zip)/)', + ], }; diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 000000000..57b3912f0 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +global.TextDecoder = require( 'util' ).TextDecoder; diff --git a/phpstan.neon b/phpstan.neon index 88ed315e7..df46183de 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -15,7 +15,7 @@ parameters: - vendor/php-stubs/wordpress-tests-stubs/wordpress-tests-stubs.php type_coverage: return_type: 91 - param_type: 80 + param_type: 79.7 property_type: 0 # We can't use property types until PHP 7.4 becomes the plugin's minimum version. print_suggestions: false typeAliases: diff --git a/src/@types/gutenberg/types.ts b/src/@types/gutenberg/types.ts index 568bd68dd..a467a10d9 100644 --- a/src/@types/gutenberg/types.ts +++ b/src/@types/gutenberg/types.ts @@ -13,12 +13,18 @@ import { dispatch } from '@wordpress/data'; export interface GutenbergFunction { editPost( edits: Record ): void; getBlock( clientId: string ): BlockInstance | null; + getBlockParents( clientId: string ): string[]; getBlocks(): BlockInstance[]; getCurrentPostAttribute( attribute: string ): string; + getCurrentPostId(): number | undefined; getEditedPostAttribute( attribute: string ): string; getEditedPostContent(): string; getPermalink(): string | null; + getPermalink(): string | null; getSelectedBlock(): BlockInstance | null; + hasMetaBoxes(): boolean; + isAutosavingPost(): boolean; + isSavingPost(): boolean; lockPostSaving( lockName: string ): void; removeEditorPanel( panelName: string ): void; selectBlock( clientId: string, initialPosition?: number ): void; diff --git a/src/Endpoints/class-base-endpoint.php b/src/Endpoints/class-base-endpoint.php index 9fd161686..3e3c272e8 100644 --- a/src/Endpoints/class-base-endpoint.php +++ b/src/Endpoints/class-base-endpoint.php @@ -11,6 +11,7 @@ namespace Parsely\Endpoints; use Parsely\Parsely; +use WP_REST_Request; use function Parsely\Utils\convert_endpoint_to_filter_key; @@ -57,10 +58,12 @@ abstract class Base_Endpoint { * user. * * @since 3.14.0 Replaced `is_public_endpoint`, `user_capability` and `permission_callback()`. + * @since 3.16.0 Added the `$request` parameter. * + * @param WP_REST_Request|null $request The request object. * @return bool */ - abstract public function is_available_to_current_user(): bool; + abstract public function is_available_to_current_user( $request = null ): bool; /** * Constructor. @@ -156,4 +159,37 @@ public function register_endpoint( 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_' . 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/content-helper/class-smart-linking-endpoint.php b/src/Endpoints/content-helper/class-smart-linking-endpoint.php new file mode 100644 index 000000000..89ec10e21 --- /dev/null +++ b/src/Endpoints/content-helper/class-smart-linking-endpoint.php @@ -0,0 +1,271 @@ +get_param( 'post_id' ); + + if ( null !== $post_id ) { + // Check if the current user has edit capabilities for the post. + $can_edit = current_user_can( 'edit_post', $post_id ); + } else { + $can_edit = current_user_can( 'edit_posts' ); + } + + // 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 + ) + ); + + return $can_edit && $has_capability; + } + + /** + * Registers the endpoints. + * + * @since 3.16.0 + */ + public function run(): void { + $this->register_endpoint( + static::ENDPOINT . '/url-to-post-type', + 'url_to_post_type', + array( 'POST' ) + ); + + $this->register_endpoint_with_args( + static::ENDPOINT . '/(?P\d+)/add', + 'add_smart_link', + array( 'POST' ) + ); + } + + /** + * Converts a URL to a post type. + * + * @since 3.16.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response 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.', + ), + ), + 400 + ); + } + + $post_id = 0; + $cache = wp_cache_get( $url, 'wp_parsely_smart_link_url_to_postid' ); + + 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' ); + } + + $response = array( + 'data' => array( + 'post_id' => false, + 'post_type' => false, + ), + ); + + 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 request parameters. + * + * @since 3.16.0 + * + * @throws InvalidArgumentException If the request is invalid. + * + * @param WP_REST_Request $request The request object. + * @return bool True if the request is valid, false otherwise. + */ + private function validate_request( WP_REST_Request $request ): bool { + $post_id = $request->get_param( 'post_id' ); + + if ( ! is_numeric( $post_id ) ) { + throw new InvalidArgumentException( 'Invalid post ID' ); + } + + // Check if post exists. + $post = get_post( intval( $post_id ) ); + if ( null === $post ) { + throw new InvalidArgumentException( 'Invalid post ID' ); + } + + return true; + } + + /** + * Adds a smart link to a post. + * + * @since 3.16.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response The response object. + */ + public function add_smart_link( WP_REST_Request $request ): WP_REST_Response { + try { + $this->validate_request( $request ); + + $post_id = $request->get_param( 'post_id' ); + if ( is_numeric( $post_id ) ) { + $post_id = intval( $post_id ); + } else { + // Validate makes sure it's numeric, so this should never happen. + $post_id = 0; + } + + $json_body = $request->get_body(); + $body_data = json_decode( $json_body, true ); + + if ( ! is_array( $body_data ) || ! isset( $body_data['link'] ) ) { + return new WP_REST_Response( + array( + 'error' => array( + 'name' => 'invalid_request', + 'message' => 'Invalid request body.', + ), + ), + 400 + ); + } + + $encoded_data = wp_json_encode( $body_data['link'] ); + if ( false === $encoded_data ) { + return new WP_REST_Response( + array( + 'error' => array( + 'name' => 'invalid_request', + 'message' => 'Invalid request body.', + ), + ), + 400 + ); + } + + /** + * Smart link object. + * + * @var Smart_Link $smart_link The smart link object. + */ + $smart_link = Smart_Link::deserialize( $encoded_data ); + $smart_link->set_post_id( $post_id ); + + // Save the smart link to the post meta. + if ( ! $smart_link->save() ) { + return new WP_REST_Response( + array( + 'error' => array( + 'name' => 'add_smart_link_failed', + 'message' => 'Failed to add smart link.', + ), + ), + 500 + ); + } + + return new WP_REST_Response( + array( + 'data' => json_decode( $smart_link->serialize() ), + ), + 200 + ); + } catch ( \InvalidArgumentException $e ) { + return new WP_REST_Response( + array( + 'error' => array( + 'name' => 'invalid_request', + 'message' => $e->getMessage(), + ), + ), + 400 + ); + } + } +} 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 index a6b8d3cbe..444ee6306 100644 --- a/src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php +++ b/src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php @@ -143,8 +143,14 @@ public function get_items( WP_REST_Request $request ) { 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' => $response, + 'data' => $smart_links, ); } } diff --git a/src/Endpoints/user-meta/class-base-endpoint-user-meta.php b/src/Endpoints/user-meta/class-base-endpoint-user-meta.php index 119ba3341..72d1ca9e3 100644 --- a/src/Endpoints/user-meta/class-base-endpoint-user-meta.php +++ b/src/Endpoints/user-meta/class-base-endpoint-user-meta.php @@ -141,10 +141,12 @@ public function process_request( WP_REST_Request $request ): string { * 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(): bool { + public function is_available_to_current_user( $request = null ): bool { return current_user_can( 'edit_user', $this->current_user_id ); } diff --git a/src/Models/class-base-model.php b/src/Models/class-base-model.php new file mode 100644 index 000000000..4b8301b92 --- /dev/null +++ b/src/Models/class-base-model.php @@ -0,0 +1,100 @@ +uid = $this->generate_uid(); + } + + /** + * Returns the unique ID of the model. + * + * @since 3.16.0 + * + * @return string The unique ID of the model. + */ + public function get_uid(): string { + return $this->uid; + } + + /** + * Generates a unique ID for the model. + * + * @since 3.16.0 + * + * @return string The generated unique ID. + */ + abstract protected function generate_uid(): string; + + /** + * Serializes the model to a JSON string. + * + * @since 3.16.0 + * + * @return string The serialized model. + */ + public function serialize(): string { + $json = wp_json_encode( $this->to_array() ); + + if ( false === $json ) { + $json = '{}'; + } + + return $json; + } + + /** + * Converts the model to an array. + * + * @since 3.16.0 + * + * @return array The model as an array. + */ + abstract public function to_array(): array; + + /** + * Deserializes a JSON string to a model. + * + * @since 3.16.0 + * + * @param string $json The JSON string to deserialize. + * @return Base_Model The deserialized model. + */ + abstract public static function deserialize( string $json ): Base_Model; + + /** + * Saves the model to the database. + * + * @since 3.16.0 + * + * @return bool True if the model was saved successfully, false otherwise. + */ + abstract public function save(): bool; +} diff --git a/src/Models/class-smart-link.php b/src/Models/class-smart-link.php new file mode 100644 index 000000000..d55bf750f --- /dev/null +++ b/src/Models/class-smart-link.php @@ -0,0 +1,238 @@ +href = $href; + $this->title = $title; + $this->text = $text; + $this->offset = $offset; + $this->applied = false; + + $this->post_id = $this->get_post_id_by_url( $href ); + + if ( false === $this->post_id ) { + $this->post_type = 'external'; + } else { + $post_type = get_post_type( $this->post_id ); + if ( false !== $post_type ) { + $this->post_type = $post_type; + } else { + $this->post_type = 'external'; + } + } + + parent::__construct(); + } + + /** + * Gets the post ID by URL. + * + * @since 3.16.0 + * + * @param string $url The URL to get the post ID for. + * @return int|false The post ID of the URL, false if not found. + */ + private function get_post_id_by_url( string $url ) { + $cache = wp_cache_get( $url, 'wp_parsely_smart_link_url_to_postid' ); + if ( is_integer( $cache ) ) { + return $cache; + } + + if ( 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' ); + } + + if ( 0 === $post_id ) { + return false; + } + + return $post_id; + } + + /** + * Generates a unique ID for the suggested link. + * + * It takes the href, title, text, and offset properties and concatenates + * them to create a unique ID. This ID is hashed to ensure it is unique. + * + * @since 3.16.0 + * + * @return string The unique ID. + */ + protected function generate_uid(): string { + return md5( $this->href . $this->title . $this->text . $this->offset ); + } + + /** + * Serializes the model to a JSON string. + * + * @since 3.16.0 + * + * @return array The serialized model. + */ + public function to_array(): array { + return array( + 'uid' => $this->uid, + 'href' => $this->href, + 'title' => $this->title, + 'text' => $this->text, + 'offset' => $this->offset, + 'applied' => $this->applied, + 'post_type' => $this->post_type, + 'post_id' => $this->post_id, + ); + } + + /** + * Sets the post ID of the suggested link. + * + * @since 3.16.0 + * + * @param int $post_id The post ID of the suggested link. + */ + public function set_post_id( int $post_id ): void { + $this->post_id = $post_id; + } + + /** + * Deserializes a JSON string to a model. + * + * @since 3.16.0 + * + * @throws InvalidArgumentException If the JSON data is invalid. + * + * @param string $json The JSON string to deserialize. + * @return Base_Model The deserialized model. + */ + public static function deserialize( string $json ): Base_Model { + $data = json_decode( $json, true ); + + // Validate the JSON data. + if ( ! is_array( $data ) ) { + throw new InvalidArgumentException( 'Invalid JSON data' ); + } + + return new Smart_Link( $data['href'], $data['title'], $data['text'], $data['offset'] ); + } + + /** + * Saves the smart link to the post meta. + * + * @since 3.16.0 + * + * @return bool True if the smart link was saved successfully, false otherwise. + */ + public function save(): bool { + if ( false === $this->post_id ) { + return false; + } + + $post_meta_key = '_wp_parsely_smart_link_' . $this->uid; + $existing_meta = get_post_meta( $this->post_id, $post_meta_key, true ); + + if ( false !== $existing_meta ) { + update_post_meta( $this->post_id, $post_meta_key, $this->serialize() ); + return true; + } + + return add_post_meta( $this->post_id, $post_meta_key, $this->serialize(), true ) !== false; + } +} diff --git a/src/RemoteAPI/class-analytics-post-detail-api.php b/src/RemoteAPI/class-analytics-post-detail-api.php index a61049920..8d946f521 100644 --- a/src/RemoteAPI/class-analytics-post-detail-api.php +++ b/src/RemoteAPI/class-analytics-post-detail-api.php @@ -12,6 +12,7 @@ use Parsely\Endpoints\Base_Endpoint; use Parsely\Parsely; +use WP_REST_Request; /** * Class for Analytics Post Detail API (`/analytics/post/detail`). @@ -28,10 +29,12 @@ class Analytics_Post_Detail_API extends Base_Endpoint_Remote { * 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(): 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( diff --git a/src/RemoteAPI/class-analytics-posts-api.php b/src/RemoteAPI/class-analytics-posts-api.php index 12d62d587..9b70421cc 100644 --- a/src/RemoteAPI/class-analytics-posts-api.php +++ b/src/RemoteAPI/class-analytics-posts-api.php @@ -13,6 +13,7 @@ use Parsely\Endpoints\Base_Endpoint; use Parsely\Parsely; use WP_Error; +use WP_REST_Request; /** * Class for Analytics Posts API (`/analytics/posts`). @@ -65,10 +66,12 @@ class Analytics_Posts_API extends Base_Endpoint_Remote { * 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(): 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( diff --git a/src/RemoteAPI/class-referrers-post-detail-api.php b/src/RemoteAPI/class-referrers-post-detail-api.php index 51e91c9ec..45233630e 100644 --- a/src/RemoteAPI/class-referrers-post-detail-api.php +++ b/src/RemoteAPI/class-referrers-post-detail-api.php @@ -12,6 +12,7 @@ use Parsely\Endpoints\Base_Endpoint; use Parsely\Parsely; +use WP_REST_Request; /** * Class for Referrers Post Detail API (`/referrers/post/detail`). @@ -28,10 +29,12 @@ class Referrers_Post_Detail_API extends Base_Endpoint_Remote { * 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(): 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( diff --git a/src/RemoteAPI/class-related-api.php b/src/RemoteAPI/class-related-api.php index 93b47bba2..ea130bf02 100644 --- a/src/RemoteAPI/class-related-api.php +++ b/src/RemoteAPI/class-related-api.php @@ -11,6 +11,7 @@ namespace Parsely\RemoteAPI; use Parsely\Parsely; +use WP_REST_Request; /** * Class for Related API (`/related`). @@ -27,10 +28,12 @@ class Related_API extends Base_Endpoint_Remote { * 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(): bool { + public function is_available_to_current_user( $request = null ): bool { return true; } } diff --git a/src/RemoteAPI/class-remote-api-cache.php b/src/RemoteAPI/class-remote-api-cache.php index a37e67006..9b60c8a46 100644 --- a/src/RemoteAPI/class-remote-api-cache.php +++ b/src/RemoteAPI/class-remote-api-cache.php @@ -11,6 +11,7 @@ namespace Parsely\RemoteAPI; use WP_Error; +use WP_REST_Request; /** * Caching Decorator for remote API endpoints. @@ -79,10 +80,12 @@ public function get_items( array $query, bool $associative = false ) { * * @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(): bool { - return $this->remote_api->is_available_to_current_user(); + 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 index e7941cff3..9f5b6b3be 100644 --- a/src/RemoteAPI/class-validate-api.php +++ b/src/RemoteAPI/class-validate-api.php @@ -13,6 +13,7 @@ use Parsely\Endpoints\Base_Endpoint; use Parsely\Parsely; use WP_Error; +use WP_REST_Request; use function Parsely\Utils\convert_to_associative_array; @@ -33,10 +34,12 @@ class Validate_API extends Base_Endpoint_Remote { * 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(): 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( diff --git a/src/RemoteAPI/content-suggestions/class-content-suggestions-base-api.php b/src/RemoteAPI/content-suggestions/class-content-suggestions-base-api.php index 42f4d492a..3d2a1b050 100644 --- a/src/RemoteAPI/content-suggestions/class-content-suggestions-base-api.php +++ b/src/RemoteAPI/content-suggestions/class-content-suggestions-base-api.php @@ -15,6 +15,8 @@ use Parsely\RemoteAPI\Base_Endpoint_Remote; use UnexpectedValueException; use WP_Error; +use WP_REST_Request; + /** * Base API for all Parse.ly Content Suggestion API endpoints. @@ -50,10 +52,12 @@ abstract class Content_Suggestions_Base_API extends Base_Endpoint_Remote { * 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(): 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( diff --git a/src/RemoteAPI/content-suggestions/class-link-suggestion.php b/src/RemoteAPI/content-suggestions/class-link-suggestion.php deleted file mode 100644 index 1caa97d5a..000000000 --- a/src/RemoteAPI/content-suggestions/class-link-suggestion.php +++ /dev/null @@ -1,48 +0,0 @@ -result as $link ) { - $link_obj = new Link_Suggestion(); - $link_obj->href = esc_url( $link->canonical_url ); - $link_obj->title = esc_attr( $link->title ); - $link_obj->text = wp_kses_post( $link->text ); - $link_obj->offset = $link->offset; - $links[] = $link_obj; + $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-remote-api.php b/src/RemoteAPI/interface-remote-api.php index 45d42c4e6..88c4cf6a9 100644 --- a/src/RemoteAPI/interface-remote-api.php +++ b/src/RemoteAPI/interface-remote-api.php @@ -11,6 +11,7 @@ namespace Parsely\RemoteAPI; use WP_Error; +use WP_REST_Request; /** * Remote API Interface. @@ -31,8 +32,10 @@ public function get_items( array $query, bool $associative = false ); * 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(): bool; + public function is_available_to_current_user( $request = null ): bool; } diff --git a/src/content-helper/common/base-provider.tsx b/src/content-helper/common/base-provider.tsx index c0f71f805..77c5ffab7 100644 --- a/src/content-helper/common/base-provider.tsx +++ b/src/content-helper/common/base-provider.tsx @@ -17,6 +17,7 @@ import { ContentHelperError, ContentHelperErrorCode } from './content-helper-err */ export interface ContentHelperAPIResponse { error?: Error; + message?: string; data: T; } diff --git a/src/content-helper/common/css/variables.scss b/src/content-helper/common/css/variables.scss index a23d973c7..b9845252f 100644 --- a/src/content-helper/common/css/variables.scss +++ b/src/content-helper/common/css/variables.scss @@ -8,6 +8,9 @@ $base-unit-5: 0.25rem; // 4px. $base-unit-10: 0.5rem; // 8px. $base-unit-15: 0.75rem; // 12px. $base-unit-20: 1rem; // 16px. +$base-unit-25: 1.25rem; // 20px. +$base-unit-30: 1.5rem; // 24px. +$base-unit-40: 2rem; // 32px. /** * This is a subset of the CSS variables defined in the Parse.ly dashboard. It @@ -21,7 +24,10 @@ $base-unit-20: 1rem; // 16px. .editor-post-excerpt, .wp-parsely-popover, .wp-parsely-suggested-title-modal, +.wp-parsely-smart-linking-review-modal, +.wp-parsely-smart-linking-close-dialog, .wp-parsely-block-overlay, +.wp-parsely-preview-editor, .components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"], // Sidebar icon. #wp-parsely-dashboard-widget { @@ -30,7 +36,8 @@ $base-unit-20: 1rem; // 16px. --numeric-font: "ff-din-round-web", sans-serif; /** Category colors section - base scss. **/ - --parsely-green: hsl(107, 42%, 46%); + --parsely-green-components: 107, 42%, 46%; + --parsely-green: hsl(var(--parsely-green-components)); --parsely-green-10: hsla(98, 61%, 81%, 1); --parsely-green-65: hsla(109, 59%, 26%, 1); --gray-200: #f7f8f9; @@ -64,6 +71,9 @@ $base-unit-20: 1rem; // 16px. --grid-unit-10: #{$base-unit-10}; // 8px. --grid-unit-15: #{$base-unit-15}; // 12px. --grid-unit-20: #{$base-unit-20}; // 16px. + --grid-unit-25: #{$base-unit-25}; // 20px. + --grid-unit-30: #{$base-unit-30}; // 24px. + --grid-unit-40: #{$base-unit-40}; // 32px. /** Additional variables. **/ --font-size--smaller: 0.688rem; // 11px. diff --git a/src/content-helper/common/icons/ai-icon.tsx b/src/content-helper/common/icons/ai-icon.tsx index 403de3652..e05a66520 100644 --- a/src/content-helper/common/icons/ai-icon.tsx +++ b/src/content-helper/common/icons/ai-icon.tsx @@ -1,6 +1,6 @@ import { Path, SVG } from '@wordpress/components'; -export const AiIcon = ( { size = 24, className = 'wp-parsely-icon' }: { size?: number, className: string } ): JSX.Element => { +export const AiIcon = ( { size = 24, className = 'wp-parsely-icon' }: { size?: number, className?: string } ): JSX.Element => { return ( { + if ( initSmartLinking ) { + initSmartLinking(); + } +} ); diff --git a/src/content-helper/editor-sidebar/smart-linking/component-block-overlay.tsx b/src/content-helper/editor-sidebar/smart-linking/component-block-overlay.tsx index ab64e63d5..170f809b9 100644 --- a/src/content-helper/editor-sidebar/smart-linking/component-block-overlay.tsx +++ b/src/content-helper/editor-sidebar/smart-linking/component-block-overlay.tsx @@ -204,11 +204,11 @@ export const withBlockOverlay = createHigherOrderComponent( ( BlockEdit ) => { return ( <> + - ); }; diff --git a/src/content-helper/editor-sidebar/smart-linking/component-link-monitor.tsx b/src/content-helper/editor-sidebar/smart-linking/component-link-monitor.tsx new file mode 100644 index 000000000..71101cc0b --- /dev/null +++ b/src/content-helper/editor-sidebar/smart-linking/component-link-monitor.tsx @@ -0,0 +1,186 @@ +/** + * WordPress dependencies + */ +// eslint-disable-next-line import/named +import { BlockInstance } from '@wordpress/blocks'; +import { useEffect, useRef } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { debounce } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import { GutenbergFunction } from '../../../@types/gutenberg/types'; + +/** + * Defines the structure of a block change. + * + * @since 3.16.0 + */ +type BlockChange = { + block: BlockInstance; + prevBlock: BlockInstance; + addedLinks: HTMLAnchorElement[]; + removedLinks: HTMLAnchorElement[]; + changedLinks: HTMLAnchorElement[]; +}; + +/** + * Checks for changes in the blocks and calls the appropriate callback functions. + * + * The function compares the current blocks with the previous blocks and detects changes in the smart links. + * + * @since 3.16.0 + * + * @param {BlockInstance[]} currentBlocks The current blocks. + * @param {BlockInstance[]} previousBlocks The previous blocks. + * + * @return {BlockChange[]} The list of changes detected. + */ +const checkBlocks = ( + currentBlocks: BlockInstance[], + previousBlocks: BlockInstance[] +): BlockChange[] => { + const changesDetected: BlockChange[] = []; + + const traverseBlocks = ( blocks: BlockInstance[], prevBlocks: BlockInstance[] | undefined ) => { + const domParser = new DOMParser(); + + blocks.forEach( ( block, index ) => { + if ( ! prevBlocks || ! prevBlocks[ index ] ) { + return; + } + + // Check inner blocks recursively. + if ( block.innerBlocks.length > 0 ) { + return traverseBlocks( block.innerBlocks, prevBlocks[ index ].innerBlocks ); + } + + if ( JSON.stringify( block ) !== JSON.stringify( prevBlocks[ index ] ) ) { + const prevBlock = prevBlocks[ index ]; + + const blockDOM = domParser.parseFromString( block.attributes.content || '', 'text/html' ); + const prevBlockDOM = domParser.parseFromString( prevBlock?.attributes.content || '', 'text/html' ); + + // Get all smart links in the block and previous block. + const smartLinks = Array.from( blockDOM.querySelectorAll( 'a[data-smartlink]' ) ) as HTMLAnchorElement[]; + const prevSmartLinks = Array.from( prevBlockDOM.querySelectorAll( 'a[data-smartlink]' ) ) as HTMLAnchorElement[]; + + // Compare and make a list of added, removed, and changed smart links. + const addedLinks = smartLinks.filter( + ( link ) => ! prevSmartLinks.some( + ( prevLink ) => prevLink.dataset.smartlink === link.dataset.smartlink + ) + ); + const removedLinks = prevSmartLinks.filter( + ( prevLink ) => ! smartLinks.some( + ( link ) => link.dataset.smartlink === prevLink.dataset.smartlink + ) + ); + const changedLinks = smartLinks + .filter( ( link ) => { + const prevLink = prevSmartLinks + .find( ( _prevLink ) => _prevLink.dataset.smartlink === link.dataset.smartlink ); + return prevLink && ( prevLink.outerHTML !== link.outerHTML ); + } ); + + if ( addedLinks.length > 0 || removedLinks.length > 0 || changedLinks.length > 0 ) { + changesDetected.push( { block, prevBlock, addedLinks, removedLinks, changedLinks } ); + } + } + } ); + }; + + traverseBlocks( currentBlocks, previousBlocks ); + + return changesDetected; +}; + +/** + * Defines the callback function for the block change. + * + * @since 3.16.0 + */ +type onChangeCallback = ( change: BlockChange ) => void; + +/** + * The LinkMonitor component props. + * + * @since 3.16.0 + */ +type LinkMonitorProps = { + isDetectingEnabled: boolean; + onLinkChange?: onChangeCallback; + onLinkRemove?: onChangeCallback; + onLinkAdd?: onChangeCallback; + debounceValue?: number; +}; + +/** + * The LinkMonitor component. + * + * This component monitors the changes in the blocks and detects the changes in the smart links. + * + * @since 3.16.0 + * + * @param {LinkMonitorProps} props The component props. + */ +export const LinkMonitor = ( { + isDetectingEnabled, + onLinkChange, + onLinkRemove, + onLinkAdd, + debounceValue = 500, +}: LinkMonitorProps ) => { + const { blocks } = useSelect( + ( selectFn ) => { + const { getBlocks } = selectFn( 'core/block-editor' ) as GutenbergFunction; + return { + blocks: getBlocks(), + }; + }, + [] + ); + + const previousBlocks = useRef( blocks ); + const previousIsEnabledRef = useRef( isDetectingEnabled ); + + useEffect( () => { + const debouncedCheckBlocks = debounce( ( ...args ) => { + // If the detection is disabled or the previous detection was disabled, cancel the debounced function. + // We need to check for the previous detection because the debounced function might be called after the + // detection is disabled. + if ( ! args[ 0 ] || ! previousIsEnabledRef.current ) { + debouncedCheckBlocks.cancel(); + previousBlocks.current = blocks; // Update previous blocks reference. + previousIsEnabledRef.current = args[ 0 ] as boolean; + return; + } + + const changesDetected = checkBlocks( blocks, previousBlocks.current ); + if ( changesDetected.length > 0 ) { + changesDetected.forEach( ( changes ) => { + if ( changes.changedLinks.length > 0 && onLinkChange ) { + onLinkChange( changes ); + } + if ( changes.addedLinks.length > 0 && onLinkAdd ) { + onLinkAdd( changes ); + } + if ( changes.removedLinks.length > 0 && onLinkRemove ) { + onLinkRemove( changes ); + } + } ); + previousBlocks.current = blocks; // Update previous blocks reference. + } + }, debounceValue ); + + debouncedCheckBlocks( isDetectingEnabled ); + + // Clean up the debounced function on component unmount. + return () => { + debouncedCheckBlocks.cancel(); + }; + }, [ blocks, debounceValue, isDetectingEnabled, onLinkAdd, onLinkChange, onLinkRemove ] ); + + return null; +}; diff --git a/src/content-helper/editor-sidebar/smart-linking/component.tsx b/src/content-helper/editor-sidebar/smart-linking/component.tsx index 326a03851..16738923c 100644 --- a/src/content-helper/editor-sidebar/smart-linking/component.tsx +++ b/src/content-helper/editor-sidebar/smart-linking/component.tsx @@ -1,52 +1,35 @@ /** * WordPress dependencies */ +import { getBlockContent } from '@wordpress/blocks'; // eslint-disable-next-line import/named -import { BlockInstance, getBlockContent } from '@wordpress/blocks'; import { Button, Notice, PanelRow } from '@wordpress/components'; import { useDebounce } from '@wordpress/compose'; -import { select, useDispatch, useSelect } from '@wordpress/data'; -import { useEffect, useState } from '@wordpress/element'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { useEffect, useMemo, useState } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; -import { external, Icon } from '@wordpress/icons'; +import { Icon, external } from '@wordpress/icons'; /** * Internal dependencies */ -import { dispatchCoreBlockEditor, dispatchCoreEditor, GutenbergFunction } from '../../../@types/gutenberg/types'; +import { GutenbergFunction, dispatchCoreEditor } from '../../../@types/gutenberg/types'; import { Telemetry } from '../../../js/telemetry/telemetry'; import { ContentHelperErrorCode } from '../../common/content-helper-error'; import { SidebarSettings, SmartLinkingSettings, useSettings } from '../../common/settings'; import { generateProtocolVariants } from '../../common/utils/functions'; +import { LinkMonitor } from './component-link-monitor'; import { SmartLinkingSettings as SmartLinkingSettingsComponent } from './component-settings'; -import { LinkSuggestion, SmartLinkingProvider } from './provider'; +import { useSmartLinksValidation } from './hooks'; +import { SmartLink, SmartLinkingProvider } from './provider'; +import { SmartLinkingReviewModal } from './review-modal/component-modal'; import { ApplyToOptions, SmartLinkingSettingsProps, SmartLinkingStore } from './store'; -import { escapeRegExp, findTextNodesNotInAnchor } from './utils'; - -/** - * Represents the counts of occurrences and applications of links within text content. - * - * - `encountered`: The number of times a specific link text is encountered in the content. - * - `linked`: The number of times a link has been successfully applied for a specific link text. - * - * @since 3.14.1 - */ -type LinkOccurrenceCounts = { - [key: string]: { - encountered: number; - linked: number; - }; -}; - -/** - * Represents an update to a block's content. - * - * @since 3.14.3 - */ -type BlockUpdate = { - clientId: string; - newContent: string; -}; +import { + calculateSmartLinkingMatches, + getAllSmartLinksInPost, + validateAndFixSmartLinksInBlock, + validateAndFixSmartLinksInPost, +} from './utils'; /** * Defines the props structure for SmartLinkingPanel. @@ -92,9 +75,14 @@ export const SmartLinkingPanel = ( { context = SmartLinkingPanelContext.Unknown, }: Readonly ): JSX.Element => { const { settings, setSettings } = useSettings(); + + // Saving hooks. + useSmartLinksValidation(); + const setSettingsDebounced = useDebounce( setSettings, 500 ); const [ numAddedLinks, setNumAddedLinks ] = useState( 0 ); + const [ isReviewDone, setIsReviewDone ] = useState( false ); const { createNotice } = useDispatch( 'core/notices' ); @@ -104,7 +92,9 @@ export const SmartLinkingPanel = ( { * @since 3.14.0 */ const { + ready, loading, + reviewModalIsOpen, isFullContent, overlayBlocks, error, @@ -114,22 +104,27 @@ export const SmartLinkingPanel = ( { applyTo, retrying, retryAttempt, + smartLinks, } = useSelect( ( selectFn ) => { const { + isReady, isLoading, + isReviewModalOpen, getOverlayBlocks, getSuggestedLinks, getError, - // eslint-disable-next-line @typescript-eslint/no-shadow - isFullContent, + isFullContent, // eslint-disable-line @typescript-eslint/no-shadow getMaxLinks, getSmartLinkingSettings, getApplyTo, isRetrying, getRetryAttempt, + getSmartLinks, } = selectFn( SmartLinkingStore ); return { + ready: isReady(), loading: isLoading(), + reviewModalIsOpen: isReviewModalOpen(), error: getError(), maxLinks: getMaxLinks(), isFullContent: isFullContent(), @@ -139,18 +134,29 @@ export const SmartLinkingPanel = ( { applyTo: getApplyTo(), retrying: isRetrying(), retryAttempt: getRetryAttempt(), + smartLinks: getSmartLinks(), }; }, [] ); + /** + * The filtered list of smart links that have been applied. + * + * This list is memoized to prevent unnecessary re-renders. + * + * @since 3.16.0 + */ + const appliedLinks = useMemo( () => smartLinks.filter( ( link ) => link.applied ), [ smartLinks ] ); + /** * Loads the Smart Linking store actions. * * @since 3.14.0 */ const { + setIsReady, setLoading, setError, - setSuggestedLinks, + addSmartLinks, addOverlayBlock, removeOverlayBlock, setSmartLinkingSettings, @@ -158,8 +164,45 @@ export const SmartLinkingPanel = ( { setMaxLinks, setIsRetrying, incrementRetryAttempt, + purgeSmartLinksSuggestions, + setIsReviewModalOpen, } = useDispatch( SmartLinkingStore ); + /** + * Handles the initialization of the Smart Linking existing links. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( ! ready ) { + const existingSmartLinks = getAllSmartLinksInPost(); + addSmartLinks( existingSmartLinks ).then( () => { + setIsReady( true ); + } ); + } + }, [ addSmartLinks, ready, setIsReady ] ); + + /** + * Handles the ending of the review process. + * Shows a success notice if the review is done and there are added links. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( ! isReviewDone ) { + setNumAddedLinks( 0 ); + } else if ( numAddedLinks > 0 ) { + createNotice( + 'success', + /* translators: %d: number of smart links applied */ + sprintf( __( '%s smart links successfully applied.', 'wp-parsely' ), numAddedLinks ), + { + type: 'snackbar', + }, + ); + } + }, [ isReviewDone ] ); // eslint-disable-line react-hooks/exhaustive-deps + /** * Handles the change of a setting. * @@ -233,16 +276,85 @@ export const SmartLinkingPanel = ( { [ selectedBlockClientId ], ); + /** + * Processes the smart links generated by the Smart Linking provider. + * + * The processing step are: + * - Exclude the links that have been applied already. + * - Strip the protocol and trailing slashes from the post permalink. + * - Filter out self-referencing links. + * - Calculate the smart links matches for each block. + * - Update the stored smart links with the new matches. + * + * @since 3.16.0 + * + * @param {SmartLink[]} links The smart links to process. + */ + const processSmartLinks = async ( links: SmartLink[] ) => { + // Exclude the links that have been applied already. + links = links.filter( + ( link ) => ! smartLinks.some( ( sl ) => sl.uid === link.uid && sl.applied ) + ); + + // Strip the protocol and trailing slashes from the post permalink. + const strippedPermalink = postPermalink + .replace( /^https?:\/\//, '' ).replace( /\/+$/, '' ); + + // Filter out self-referencing links. + links = links.filter( ( link ) => { + if ( link.href.includes( strippedPermalink ) ) { + // eslint-disable-next-line no-console + console.warn( `PCH Smart Linking: Skipping self-reference link: ${ link.href }` ); + return false; + } + return true; + } ); + + // Calculate the smart links matches for each block. + links = calculateSmartLinkingMatches( allBlocks, links, {} ) + // Filter out links without a match. + .filter( ( link ) => link.match ); + + // Filter out links without match and smart links being inserted inside another smart link. + links = links.filter( ( link ) => { + // If the link text and offset are the same, we want to keep the link, so it can replace the old smart link. + if ( smartLinks.some( ( sl ) => sl.text === link.text && sl.offset === link.offset ) ) { + // TODO: Flag smart link as updated, for now we just remove the old one. + return false; + } + + if ( ! link.match ) { + return false; + } + const linkStart = link.match.blockLinkPosition; + const linkEnd = linkStart + link.text.length; + + return ! smartLinks.some( ( sl ) => { + if ( link.match!.blockId !== sl.match!.blockId ) { + return false; + } + const slStart = sl.match!.blockLinkPosition; + const slEnd = slStart + sl.text.length; + + return ( linkStart >= slStart && linkEnd <= slEnd ); + } ); + } ); + + // Update the link suggestions with the new matches. + await addSmartLinks( links ); + }; + /** * Generates smart links for the selected block or the entire post content. * * @since 3.14.0 - * @since 3.15.0 Renamed from `generateSmartLinks` to `generateAndApplySmartLinks`. */ - const generateAndApplySmartLinks = () => async (): Promise => { + const generateSmartLinks = async () => { await setLoading( true ); - await setSuggestedLinks( null ); + await purgeSmartLinksSuggestions(); await setError( null ); + setIsReviewDone( false ); + Telemetry.trackEvent( 'smart_linking_generate_pressed', { is_full_content: isFullContent, selected_block: selectedBlock?.name ?? 'none', @@ -268,9 +380,10 @@ export const SmartLinkingPanel = ( { const previousApplyTo = applyTo; try { const generatedLinks = await generateSmartLinksWithRetry( MAX_NUMBER_OF_RETRIES ); - applySmartLinks( generatedLinks ); + await processSmartLinks( generatedLinks ); + setIsReviewModalOpen( true ); } catch ( e: any ) { // eslint-disable-line @typescript-eslint/no-explicit-any - let snackBarMessage = __( 'There was a problem applying smart links.', 'wp-parsely' ); + let snackBarMessage = __( 'There was a problem generating smart links.', 'wp-parsely' ); // Handle the case where the operation was aborted by the user. if ( e.code && e.code === ContentHelperErrorCode.ParselyAborted ) { @@ -304,10 +417,10 @@ export const SmartLinkingPanel = ( { * * @param {number} retries The number of retries remaining. * - * @return {Promise} The generated smart links. + * @return {Promise} The generated smart links. */ - const generateSmartLinksWithRetry = async ( retries: number ): Promise => { - let generatedLinks: LinkSuggestion[] = []; + const generateSmartLinksWithRetry = async ( retries: number ): Promise => { + let generatedLinks: SmartLink[] = []; try { const generatingFullContent = isFullContent || ! selectedBlock; await setApplyTo( generatingFullContent ? ApplyToOptions.All : ApplyToOptions.Selected ); @@ -339,220 +452,9 @@ export const SmartLinkingPanel = ( { throw err; } - await setSuggestedLinks( generatedLinks ); return generatedLinks; }; - /** - * Applies the smart links to the selected block or the entire post content. - * - * @since 3.14.0 - * @since 3.14.1 Moved applyLinksToBlocks to a separate function. - * - * @param {LinkSuggestion[]} links The smart links to apply. - */ - const applySmartLinks = ( links: LinkSuggestion[] ): void => { - Telemetry.trackEvent( 'smart_linking_applied', { - is_full_content: isFullContent || ! selectedBlock, - selected_block: selectedBlock?.name ?? 'none', - links_count: links.length, - context, - } ); - - let blocks; - if ( selectedBlock && ! isFullContent ) { - blocks = [ selectedBlock ]; - } else { - blocks = allBlocks; - } - - // An object to keep track of the number of times each link text has been found across all blocks. - const occurrenceCounts: LinkOccurrenceCounts = {}; - const updatedBlocks: BlockUpdate[] = []; - - // Apply the smart links to the content. - applyLinksToBlocks( blocks, links, occurrenceCounts, updatedBlocks ); - - // Update the content of each block. - updateBlocksContent( updatedBlocks ); - - const numberOfUpdatedLinks = Object.values( occurrenceCounts ).reduce( ( acc, occurrenceCount ) => { - return acc + occurrenceCount.linked; - }, 0 ); - - setNumAddedLinks( numberOfUpdatedLinks ); - - createNotice( - 'success', - /* translators: %d: number of smart links applied */ - sprintf( __( '%s smart links successfully applied.', 'wp-parsely' ), numberOfUpdatedLinks ), - { - type: 'snackbar', - }, - ); - }; - - /** - * Iterates through blocks of content to apply smart link suggestions. - * - * This function parses the content of each block, looking for text nodes that match the provided link suggestions. - * When a match is found, it creates an anchor element (``) around the matching text with the specified href and - * title from the link suggestion. - * It carefully avoids inserting links within existing anchor elements and handles various inline HTML elements gracefully. - * - * @since 3.14.1 - * - * @param {BlockInstance[]} blocks The blocks of content where links should be applied. - * @param {LinkSuggestion[]} links An array of link suggestions to apply to the content. - * @param {LinkOccurrenceCounts} occurrenceCounts An object to keep track of the number of times each link text has - * been applied across all blocks. - * @param {BlockUpdate[]} updatedBlocks An array of updated blocks with the new content. - * This array is modified in place and will contain the updated blocks - * after the function has been called. - */ - const applyLinksToBlocks = ( - blocks: Readonly[], - links: LinkSuggestion[], - occurrenceCounts: LinkOccurrenceCounts, - updatedBlocks: BlockUpdate[], - ): void => { - // Check if any of the links being applied is a self-reference, and remove it if it is. - const strippedPermalink = postPermalink - .replace( /^https?:\/\//, '' ) // Remove HTTP(S). - .replace( /\/+$/, '' ); // Remove trailing slash. - links = links.filter( ( link ) => { - if ( link.href.includes( strippedPermalink ) ) { - // eslint-disable-next-line no-console - console.warn( `PCH Smart Linking: Skipping self-reference link: ${ link.href }` ); - return false; - } - return true; - } ); - - blocks.forEach( ( block ) => { - let blockUpdated = false; - // Recursively apply links to any inner blocks. - if ( block.innerBlocks && block.innerBlocks.length ) { - applyLinksToBlocks( block.innerBlocks, links, occurrenceCounts, updatedBlocks ); - return; - } - - if ( ! block.originalContent ) { - return; - } - - const blockContent: string = getBlockContent( block ); - const doc = new DOMParser().parseFromString( blockContent, 'text/html' ); - - const contentElement = doc.body.firstChild; - if ( contentElement && contentElement instanceof HTMLElement ) { - links.forEach( ( link ) => { - const textNodes = findTextNodesNotInAnchor( contentElement, link.text ); - const occurrenceKey = `${ link.text }#${ link.offset }`; - - if ( ! occurrenceCounts[ occurrenceKey ] ) { - occurrenceCounts[ occurrenceKey ] = { encountered: 0, linked: 0 }; - } - - textNodes.forEach( ( node ) => { - if ( node.textContent ) { - const occurrenceCount = occurrenceCounts[ occurrenceKey ]; - if ( occurrenceCount.linked >= 1 ) { - // The link has already been applied, skip this occurrence. - return; - } - - const regex = new RegExp( escapeRegExp( link.text ), 'g' ); - let match; - while ( ( match = regex.exec( node.textContent ) ) !== null ) { - // Increment the encountered count every time the text is found. - occurrenceCount.encountered++; - - // Check if the link is in the correct position (offset) to be applied. - if ( occurrenceCount.encountered === link.offset + 1 ) { - // Create a new anchor element for the link. - const anchor = document.createElement( 'a' ); - anchor.href = link.href; - anchor.title = link.title; - anchor.textContent = match[ 0 ]; - - // Replace the matched text with the new anchor element. - const range = document.createRange(); - range.setStart( node, match.index ); - range.setEnd( node, match.index + match[ 0 ].length ); - range.deleteContents(); - range.insertNode( anchor ); - - // Adjust the text node if there's text remaining after the link. - if ( - node.textContent && - match.index + match[ 0 ].length < node.textContent.length - ) { - const remainingText = document.createTextNode( - node.textContent.slice( match.index + match[ 0 ].length ) - ); - node.parentNode?.insertBefore( remainingText, anchor.nextSibling ); - } - - // Increment the linked count only when a link is applied. - occurrenceCount.linked++; - - // Flag the block as updated. - blockUpdated = true; - } - } - } - } ); - } ); - - // Save the updated content if the block was updated. - if ( blockUpdated ) { - updatedBlocks.push( { - clientId: block.clientId, - newContent: contentElement.innerHTML, - } ); - } - } - } ); - }; - - /** - * Updates the content of a block with the modified HTML. - * - * This function updates the originalContent attribute of the block with the modified HTML. - * It also recursively updates the content of any inner blocks. - * - * @since 3.14.1 - * @since 3.14.3 Rename the function from updateBlockContent to updateBlocksContent. - * - * @param {BlockUpdate[]} blockUpdates An array of block updates. - */ - const updateBlocksContent = ( blockUpdates: BlockUpdate[] ) => { - const { getBlock } = select( 'core/block-editor' ); - const updatedBlocks: { [clientId: string]: object } = {}; - - // Prepare the updated blocks object. - blockUpdates.forEach( ( blockUpdate ) => { - const block = getBlock( blockUpdate.clientId ); - - if ( ! block ) { - return; - } - - updatedBlocks[ block.clientId ] = { - content: blockUpdate.newContent, - }; - } ); - - // Update the blocks attributes. - dispatchCoreBlockEditor.updateBlockAttributes( - Object.keys( updatedBlocks ), - updatedBlocks, - // @ts-ignore - The uniqueByBlock parameter is not available in the type definition. - true, - ); - }; - /** * Applies the overlay to the selected block or the entire post content. * @@ -577,17 +479,6 @@ export const SmartLinkingPanel = ( { const removeOverlay = async ( clientId: string = 'all' ): Promise => { await removeOverlayBlock( clientId ); - // Select a block after removing the overlay, only if we're using the block inspector. - if ( context === SmartLinkingPanelContext.BlockInspector ) { - if ( 'all' !== clientId && ! isFullContent ) { - dispatchCoreBlockEditor.selectBlock( clientId ); - } else { - const firstBlock = select( 'core/block-editor' ).getBlockOrder()[ 0 ]; - // Select the first block in the post. - dispatchCoreBlockEditor.selectBlock( firstBlock ); - } - } - // If there are no more overlay blocks, enable save. if ( overlayBlocks.length === 0 ) { enableSave(); @@ -643,13 +534,20 @@ export const SmartLinkingPanel = ( { ); } if ( loading ) { - return __( 'Adding Smart Links…', 'wp-parsely' ); + return __( 'Generating Smart Links…', 'wp-parsely' ); } return __( 'Add Smart Links', 'wp-parsely' ); }; return (
+ { + // When a link is removed, validate and fix any smart-link that got the data-smartlink attribute removed. + validateAndFixSmartLinksInBlock( changes.block ); + } } + />
{ __( @@ -674,10 +572,10 @@ export const SmartLinkingPanel = ( { { error.Message() } ) } - { suggestedLinks !== null && ( + { ( isReviewDone && numAddedLinks > 0 ) && ( setSuggestedLinks( null ) } + onRemove={ () => setIsReviewDone( false ) } className="wp-parsely-smart-linking-suggested-links" > { @@ -696,7 +594,7 @@ export const SmartLinkingPanel = ( { />
+ { appliedLinks.length > 0 && ( +
+ +
+ ) } + + { reviewModalIsOpen && ( + { + setNumAddedLinks( ( num ) => num + 1 ); + } } + onClose={ () => { + setIsReviewDone( true ); + setIsReviewModalOpen( false ); + } } + /> + ) }
); }; diff --git a/src/content-helper/editor-sidebar/smart-linking/hooks.ts b/src/content-helper/editor-sidebar/smart-linking/hooks.ts new file mode 100644 index 000000000..9bb1c6b09 --- /dev/null +++ b/src/content-helper/editor-sidebar/smart-linking/hooks.ts @@ -0,0 +1,89 @@ +/** + * WordPress dependencies + */ +import { useRef, useState, useEffect } from '@wordpress/element'; +import { dispatch, useSelect } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import { GutenbergFunction } from '../../../@types/gutenberg/types'; +import { validateAndFixSmartLinksInPost } from './utils'; + +/** + * Handles the smart links validation process, which will validate the smart links before saving the post. + * + * This hook is used to validate the smart links before saving the post. It will validate the smart links before + * saving the post, and then save the post after the smart links have been validated. This is necessary because + * the validation process may change the post content, and those changes are not reflected in the post saving process. + * + * This is a fallback for the validation step in the LinkMonitor component. If for some reason the validation step + * is not triggered, this hook will fix the smart links before saving the post. + * + * @since 3.16.0 + * + * @return {boolean} Whether the post is saved. + */ +export const useSmartLinksValidation = (): boolean => { + const [ isPostSaved, setIsPostSaved ] = useState( false ); + const [ didAnyFixes, setDidAnyFixes ] = useState( false ); + const isPostSavingInProgress = useRef( false ); + const hasValidatedLinks = useRef( false ); + + const { isSavingPost, isAutosavingPost } = useSelect( ( selectFn ) => { + const coreEditorSelect = selectFn( 'core/editor' ) as GutenbergFunction; + return { + isSavingPost: coreEditorSelect.isSavingPost(), + isAutosavingPost: coreEditorSelect.isAutosavingPost(), + }; + }, [] ); + + /** + * Handles the before save action, which will validate the smart links before saving the post. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( isSavingPost && ! hasValidatedLinks.current ) { + ( async () => { + const validationFixed = await validateAndFixSmartLinksInPost(); + setDidAnyFixes( validationFixed ); + hasValidatedLinks.current = true; + } )(); + } + }, [ isSavingPost ] ); + + /** + * Handles the post saving state tracking. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( ( isSavingPost || isAutosavingPost ) && ! isPostSavingInProgress.current ) { + setIsPostSaved( false ); + isPostSavingInProgress.current = true; + } else if ( ! ( isSavingPost || isAutosavingPost ) && isPostSavingInProgress.current ) { + setIsPostSaved( true ); + isPostSavingInProgress.current = false; + } + }, [ isSavingPost, isAutosavingPost ] ); + + /** + * Handles the post saving action, which will save the post after the smart links have been validated. + * This is necessary because the validation process may change the post content, and those changes are not + * reflected in the post saving process. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( isPostSaved && hasValidatedLinks.current && didAnyFixes ) { + ( async () => { + await dispatch( editorStore ).savePost(); + hasValidatedLinks.current = false; + } )(); + } + }, [ didAnyFixes, isPostSaved ] ); + + return isPostSaved; +}; diff --git a/src/content-helper/editor-sidebar/smart-linking/provider.ts b/src/content-helper/editor-sidebar/smart-linking/provider.ts index 867ac14bb..e1e7faf81 100644 --- a/src/content-helper/editor-sidebar/smart-linking/provider.ts +++ b/src/content-helper/editor-sidebar/smart-linking/provider.ts @@ -14,17 +14,36 @@ import { DEFAULT_MAX_LINKS } from './smart-linking'; * `content-suggestions/suggest-linked-reference` endpoint. * * @since 3.14.0 + * @since 3.16.0 Added the `applied`, `match`, `post_id`, and `post_type` properties. */ -export type LinkSuggestion = { +export type SmartLink = { + uid: string; href: string; text: string; title: string; offset: number; + applied: boolean; + match?: SmartLinkMatch; + post_id?: number|false; + post_type?: string; }; /** - * Returns data from the `content-suggestions/suggest-linked-reference` WordPress REST API - * endpoint. + * Structure of a link suggestion match, that is filled in by the + * processing of the smart links. + * + * @since 3.16.0 + */ +export type SmartLinkMatch = { + blockId: string; + blockPosition: number; + blockOffset: number; + blockLinkPosition: number; +} + +/** + * Returns data from the `content-suggestions/suggest-linked-reference` + * WordPress REST API endpoint. * * @since 3.14.0 */ @@ -57,14 +76,14 @@ export class SmartLinkingProvider extends BaseProvider { * @param {number} maxLinksPerPost The maximum number of links to return. * @param {string[]} urlExclusionList A list of URLs to exclude from the suggestions. * - * @return {Promise} The resulting list of links. + * @return {Promise} The resulting list of links. */ public async generateSmartLinks( content: string, maxLinksPerPost: number = DEFAULT_MAX_LINKS, urlExclusionList: string[] = [], - ): Promise { - const response = await this.fetch( { + ): Promise { + const response = await this.fetch( { method: 'POST', path: addQueryArgs( '/wp-parsely/v1/content-suggestions/suggest-linked-reference', { max_links: maxLinksPerPost, @@ -77,4 +96,38 @@ export class SmartLinkingProvider extends BaseProvider { return response ?? []; } + + public async addSmartLink( postID: number, linkSuggestion: SmartLink ) { + // /wp-parsely/v1/smart-linking/[post-id]/add + const response = await this.fetch( { + method: 'POST', + path: `/wp-parsely/v1/smart-linking/${ postID }/add`, + data: { + link: linkSuggestion, + }, + } ); + + return response; + } + + /** + * Get the post type of post by its URL. + * + * @since 3.16.0 + * + * @param {string} url The URL of the post. + * + * @return {Promise} The post type of the post. + */ + public async getPostTypeByURL( url: string ): Promise { + const response = await this.fetch<{ post_type: string }>( { + method: 'POST', + path: '/wp-parsely/v1/smart-linking/url-to-post-type', + data: { + url, + }, + } ); + + return response.post_type; + } } diff --git a/src/content-helper/editor-sidebar/smart-linking/review-modal/component-modal.tsx b/src/content-helper/editor-sidebar/smart-linking/review-modal/component-modal.tsx new file mode 100644 index 000000000..bcbcea2ba --- /dev/null +++ b/src/content-helper/editor-sidebar/smart-linking/review-modal/component-modal.tsx @@ -0,0 +1,462 @@ +/** + * WordPress dependencies + */ +// eslint-disable-next-line import/named +import { BlockInstance, getBlockContent } from '@wordpress/blocks'; +import { Button, KeyboardShortcuts, Modal } from '@wordpress/components'; +import { select, useDispatch, useSelect } from '@wordpress/data'; +import { memo, useEffect, useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { dispatchCoreBlockEditor } from '../../../../@types/gutenberg/types'; +import { SmartLink } from '../provider'; +import { SmartLinkingStore } from '../store'; +import { applyNodeToBlock } from '../utils'; +import { ReviewModalSidebar } from './component-sidebar'; +import { ReviewSuggestion } from './component-suggestion'; + +/** + * The props for the SmartLinkingReviewModal component. + * + * @since 3.16.0 + */ +export type SmartLinkingReviewModalProps = { + onClose: () => void, + isOpen: boolean, + onAppliedLink: ( link: SmartLink ) => void, +}; + +/** + * The SmartLinkingReviewModal component displays a modal to review and apply smart links. + * + * @since 3.16.0 + * + * @param {SmartLinkingReviewModalProps} props The component props. + */ +const SmartLinkingReviewModalComponent = ( { + onClose, + isOpen, + onAppliedLink, +}: SmartLinkingReviewModalProps ): JSX.Element => { + const [ showCloseDialog, setShowCloseDialog ] = useState( false ); + const [ isModalOpen, setIsModalOpen ] = useState( isOpen ); + + /** + * Loads the Smart Linking store selectors. + * + * @since 3.16.0 + */ + const { + smartLinks, + suggestedLinks, + getSmartLinks, + } = useSelect( ( selectFn ) => { + // eslint-disable-next-line @typescript-eslint/no-shadow + const { getSmartLinks, getSuggestedLinks } = selectFn( SmartLinkingStore ); + return { + smartLinks: getSmartLinks(), + getSmartLinks, + suggestedLinks: getSuggestedLinks, + }; + }, [] ); + + const [ selectedLink, setSelectedLink ] = useState( smartLinks[ 0 ] ); + + /** + * Loads the Smart Linking store actions. + * + * @since 3.16.0 + */ + const { + purgeSmartLinksSuggestions, + updateSmartLink, + removeSmartLink, + } = useDispatch( SmartLinkingStore ); + + /** + * Sets the selected link when the suggested links change. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( isModalOpen && smartLinks.length === 0 ) { + onClose(); + } + }, [ isModalOpen, onClose, smartLinks ] ); + + const showConfirmCloseDialog = () => setShowCloseDialog( true ); + const hideConfirmCloseDialog = () => setShowCloseDialog( false ); + + /** + * Updates the modal state when the `isOpen` prop changes. + * + * @since 3.16.0 + */ + useEffect( () => { + setIsModalOpen( isOpen ); + }, [ isOpen ] ); + + /** + * Applies the link to the block. + * + * @since 3.16.0 + * + * @param {string} blockId The block instance to apply the link to. + * @param {SmartLink} linkSuggestion The link suggestion to apply. + */ + const applyLinkToBlock = async ( blockId: string, linkSuggestion: SmartLink ) => { + const anchor = document.createElement( 'a' ); + anchor.href = linkSuggestion.href; + anchor.title = linkSuggestion.title; + // Add data-smartlink attribute to the anchor tag. + anchor.setAttribute( 'data-smartlink', linkSuggestion.uid ); + + const block = select( 'core/block-editor' ).getBlock( blockId ); + if ( ! block ) { + return; + } + + // Apply and updates the block content. + applyNodeToBlock( block, linkSuggestion, anchor ); + + // Update the smart link in the store. + linkSuggestion.applied = true; + await updateSmartLink( linkSuggestion ); + }; + + /** + * Removes a Smart Link from a block, using the unique identifier. + * + * @since 3.16.0 + * + * @param {BlockInstance} block The block instance to remove the link from. + * @param {SmartLink} linkSuggestion The link suggestion to remove. + */ + const removeLinkFromBlock = async ( block: BlockInstance, linkSuggestion: SmartLink ) => { + const blockId = block.clientId; + if ( ! block ) { + return; + } + + const blockContent: string = getBlockContent( block ); + const doc = new DOMParser().parseFromString( blockContent, 'text/html' ); + const contentElement = doc.body.firstChild as HTMLElement; + + if ( ! contentElement ) { + return; + } + + // Select anchors by 'data-smartlink' attribute matching the UID. + const anchors = Array.from( + contentElement.querySelectorAll( `a[data-smartlink="${ linkSuggestion.uid }"]` ), + ); + + // Check if we found the anchor with the specified UID. + if ( anchors.length > 0 ) { + const anchorToRemove = anchors[ 0 ]; + const parentNode = anchorToRemove.parentNode; + if ( parentNode ) { + // Replace the anchor with its text content. + const textNode = document.createTextNode( anchorToRemove.textContent ?? '' ); + parentNode.replaceChild( textNode, anchorToRemove ); + + // Update the block content. + dispatchCoreBlockEditor.updateBlockAttributes( blockId, { content: contentElement.innerHTML } ); + } + } + + // Remove the link from the store. + await removeSmartLink( linkSuggestion.uid ); + }; + + /** + * Handles the closing of the modal. + * + * If there are any pending links, a confirmation dialog is shown. + * When the modal is closed, any pending suggestions are purged. + * + * @since 3.16.0 + */ + const onCloseHandler = () => { + // Hide the modal. + setIsModalOpen( false ); + + const pendingLinks = smartLinks.filter( ( link ) => ! link.applied ); + if ( pendingLinks.length > 0 ) { + showConfirmCloseDialog(); + return; + } + + // Purge any remaining suggestions. + purgeSmartLinksSuggestions().then( () => onClose() ); + }; + + /** + * Handles the closing of the closing confirmation dialog. + * + * If the user confirms the closing, the modal is closed. + * + * @since 3.16.0 + * + * @param {boolean} shouldClose Whether the modal should be closed. + */ + const onCloseConfirmCloseDialog = ( shouldClose: boolean ) => { + hideConfirmCloseDialog(); + if ( shouldClose ) { + setIsModalOpen( false ); + purgeSmartLinksSuggestions().then( () => { + onClose(); + } ); + } else { + setIsModalOpen( true ); + } + }; + + /** + * Handles the selection of the next smart link. + * + * @since 3.16.0 + */ + const handleNext = () => { + const currentIndex = smartLinks.indexOf( selectedLink ); + const nextIndex = currentIndex + 1; + + if ( ! smartLinks[ nextIndex ] ) { + return; + } + + setSelectedLink( smartLinks[ nextIndex ] ); + }; + + /** + * Handles the selection of the previous smart link. + * + * @since 3.16.0 + */ + const handlePrevious = () => { + const currentIndex = getSmartLinks().indexOf( selectedLink ); + const previousIndex = currentIndex - 1; + + if ( ! getSmartLinks()[ previousIndex ] ) { + return; + } + + setSelectedLink( getSmartLinks()[ previousIndex ] ); + }; + + /** + * Handles the acceptance of a smart link. + * + * @since 3.16.0 + */ + const onAcceptHandler = async () => { + if ( ! selectedLink.match ) { + return; + } + + onAppliedLink( selectedLink ); + await applyLinkToBlock( selectedLink.match.blockId, selectedLink ); + + // If there are no more suggested links, close the modal. + if ( suggestedLinks().length === 0 ) { + onCloseHandler(); + return; + } + + const currentIndex = smartLinks.indexOf( selectedLink ); + const nextIndex = currentIndex + 1; + + // If there is a next link, select it, otherwise select the first link. + if ( smartLinks[ nextIndex ] ) { + setSelectedLink( smartLinks[ nextIndex ] ); + } else { + setSelectedLink( smartLinks[ 0 ] ); + } + }; + + /** + * Handles the rejection of a smart link. + * + * @since 3.16.0 + */ + const onRejectHandler = async () => { + // Change to the next link. + const currentIndex = smartLinks.indexOf( selectedLink ); + const nextIndex = currentIndex + 1; + + // Check if it exists. If not, try to go for the first one on the array. + // If there isn't any, close the modal. + if ( ! smartLinks[ nextIndex ] ) { + if ( smartLinks[ 0 ] ) { + setSelectedLink( smartLinks[ 0 ] ); + } else { + onCloseHandler(); + } + } else { + setSelectedLink( smartLinks[ nextIndex ] ); + } + + await removeSmartLink( selectedLink.uid ); + }; + + /** + * Handles the removal of a smart link. + * + * @since 3.16.0 + */ + const onRemoveHandler = async () => { + if ( ! selectedLink.match ) { + return; + } + + const block = select( 'core/block-editor' ).getBlock( selectedLink.match.blockId ); + if ( block ) { + let currentSmartLinks = getSmartLinks(); + + // Get the selected link index, and set the selected link as the previous one, or the first one if no previous. + const currentIndex = currentSmartLinks.indexOf( selectedLink ); + const previousIndex = currentIndex - 1; + + await removeLinkFromBlock( block, selectedLink ); + + currentSmartLinks = getSmartLinks(); + if ( currentSmartLinks[ previousIndex ] ) { + setSelectedLink( currentSmartLinks[ previousIndex ] ); + } else { + setSelectedLink( currentSmartLinks[ 0 ] ); + } + } + }; + + /** + * Selects the link into the block editor. + * + * @since 3.16.0 + */ + const onSelectedInEditorHandler = () => { + if ( ! selectedLink.match ) { + return; + } + + const block = select( 'core/block-editor' ).getBlock( selectedLink.match.blockId ); + if ( block ) { + // Select the block in the editor. + dispatchCoreBlockEditor.selectBlock( block.clientId ); + + // Find the link element within the block. + const blockContent = document.querySelector( `[data-block="${ block.clientId }"]` ); + if ( blockContent ) { + const ownerDocument = blockContent.ownerDocument; + const linkElement = blockContent.querySelector( `a[data-smartlink="${ selectedLink.uid }"]` ) as HTMLElement; + if ( linkElement ) { + // Set focus to the link element. + linkElement.focus(); + + // Select the link. + const range = ownerDocument.createRange(); + if ( linkElement.firstChild ) { + range.setStart( linkElement.firstChild, 0 ); // Start at the beginning of the link text + range.setEndAfter( linkElement.firstChild ); + const sel = ownerDocument.getSelection(); + if ( sel ) { + sel.removeAllRanges(); + sel.addRange( range ); + } + } + } + } + + // Close the modal. + onCloseHandler(); + } + }; + + return ( + <> + { isModalOpen && ( + + { + if ( selectedLink && ! selectedLink.applied ) { + onAcceptHandler(); + } + }, + r: () => { + if ( ! selectedLink ) { + return; + } + if ( selectedLink.applied ) { + onRemoveHandler(); + } else { + onRejectHandler(); + } + }, + } } /> +
+ + 0 } + onNext={ handleNext } + onPrevious={ handlePrevious } + onAccept={ onAcceptHandler } + onReject={ onRejectHandler } + onRemove={ onRemoveHandler } + onSelectInEditor={ onSelectedInEditorHandler } + /> +
+
+ ) } + + { showCloseDialog && ( + onCloseConfirmCloseDialog( false ) } + className="wp-parsely-smart-linking-close-dialog" + > + { __( 'Are you sure you want to close? All un-accepted smart links will not be added.', 'wp-parsely' ) } +
+ + +
+
+ ) } + + + ); +}; + +/** + * The SmartLinkingReviewModal component, memoized for performance. + * + * @since 3.16.0 + */ +export const SmartLinkingReviewModal = memo( SmartLinkingReviewModalComponent ); diff --git a/src/content-helper/editor-sidebar/smart-linking/review-modal/component-sidebar.tsx b/src/content-helper/editor-sidebar/smart-linking/review-modal/component-sidebar.tsx new file mode 100644 index 000000000..d38e53dcc --- /dev/null +++ b/src/content-helper/editor-sidebar/smart-linking/review-modal/component-sidebar.tsx @@ -0,0 +1,97 @@ +/** + * WordPress dependencies + */ +import { MenuItem } from '@wordpress/components'; +import { useEffect, useRef } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { AiIcon } from '../../../common/icons/ai-icon'; +import { SmartLink } from '../provider'; + +type ReviewModalSidebarProps = { + activeLink: SmartLink | null, + links: SmartLink[] | null, + setSelectedLink: ( link: SmartLink ) => void, +}; + +/** + * Sidebar component for the review modal. + * + * @since 3.16.0 + * + * @param {ReviewModalSidebarProps} props The component props. + */ +export const ReviewModalSidebar = ( { + activeLink, + links, + setSelectedLink, +}: ReviewModalSidebarProps ): JSX.Element => { + const sidebarRef = useRef( null ); + const itemRefs = useRef<( HTMLButtonElement | null )[]>( [] ); + + /** + * Handles the scroll of the sidebar to the active link. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( activeLink ) { + const activeIndex = links?.findIndex( ( link ) => link.uid === activeLink.uid ); + if ( activeIndex !== undefined && activeIndex !== -1 && sidebarRef.current && itemRefs.current[ activeIndex ] ) { + const sidebar = sidebarRef.current; + const activeItem = itemRefs.current[ activeIndex ]; + + if ( activeItem ) { + if ( activeIndex === 0 ) { + sidebar.scrollTop = 0; + return; + } + const sidebarRect = sidebar.getBoundingClientRect(); + const activeItemRect = activeItem.getBoundingClientRect(); + + // Check if the active item is out of view. + if ( activeItemRect.top < sidebarRect.top || activeItemRect.bottom > sidebarRect.bottom ) { + // Scroll only if the active item is out of view. + sidebar.scrollTop = activeItem.offsetTop - sidebar.offsetTop; + } + } + } + } + }, [ activeLink, links ] ); + + const label = ( + + { __( 'NEW', 'wp-parsely' ) } + + + ); + + return ( +
+
+
+ { __( 'Outbound Smart Links', 'wp-parsely' ) } + { links?.length } +
+ { links?.map( ( link, index ) => ( + itemRefs.current[ index ] = el } + className={ activeLink?.uid === link.uid ? 'is-selected' : '' } + role="menuitemradio" + isSelected={ activeLink?.uid === link.uid } + onClick={ () => { + setSelectedLink( link ); + } } + > + { link.text } + { ! link.applied && label } + + ) ) } +
+
+ ); +}; diff --git a/src/content-helper/editor-sidebar/smart-linking/review-modal/component-suggestion.tsx b/src/content-helper/editor-sidebar/smart-linking/review-modal/component-suggestion.tsx new file mode 100644 index 000000000..a48bf8c44 --- /dev/null +++ b/src/content-helper/editor-sidebar/smart-linking/review-modal/component-suggestion.tsx @@ -0,0 +1,474 @@ +/** + * WordPress dependencies + */ +// eslint-disable-next-line import/named +import { BlockInstance, cloneBlock, getBlockContent, getBlockType } from '@wordpress/blocks'; +import { + Button, + Disabled, + __experimentalDivider as Divider, + MenuItem, + Tooltip, +} from '@wordpress/components'; +import { select as selectFn, useDispatch, useSelect } from '@wordpress/data'; +import { useEffect, useMemo, useRef, useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { Icon, arrowLeft, arrowRight, check, closeSmall, page } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { BlockEditorProvider, BlockList } from '@wordpress/block-editor'; +import { GutenbergFunction } from '../../../../@types/gutenberg/types'; +import { SmartLink, SmartLinkingProvider } from '../provider'; +import { SmartLinkingStore } from '../store'; +import { applyNodeToBlock, trimURLForDisplay } from '../utils'; + +/** + * The props for the SuggestionBreadcrumb component. + * + * @since 3.16.0 + */ +type SuggestionBreadcrumbProps = { + link: SmartLink, +}; + +/** + * Displays the breadcrumb for the suggestion. + * + * It shows the parent blocks of the block where the link is found. + * + * @since 3.16.0 + * + * @param {SuggestionBreadcrumbProps} props The component props. + */ +const SuggestionBreadcrumb = ( { link }: SuggestionBreadcrumbProps ): JSX.Element => { + const blockId = link.match?.blockId; + + // Fetch block details and parent IDs using the blockId. + const { block, parents } = useSelect( + ( select ) => { + const { getBlock, getBlockParents } = select( 'core/block-editor' ) as GutenbergFunction; + + if ( ! blockId ) { + return { block: undefined, parents: [] }; + } + + return { + block: getBlock( blockId ), + parents: getBlockParents( blockId ) + .map( ( id ) => getBlock( id ) ) + .filter( ( currBlock ): currBlock is BlockInstance => currBlock !== undefined ), + }; + }, + [ blockId ], + ); + + if ( ! block ) { + return <>; + } + + return ( +
+ { parents.map( ( parent: BlockInstance, index: number ) => ( + + + { getBlockType( parent.name )?.title } + +  /  + + ) ) } + + { getBlockType( block.name )?.title } + { block.attributes?.metadata?.name && ( + { block.attributes.metadata.name } + ) } + +
+ ); +}; + +/** + * The props for the Styles component. + * + * @since 3.16.0 + */ +type StylesProps = { + styles: { + css?: string, + assets?: string, + __unstableType?: string, + }[], +}; + +/** + * The Styles component, which renders the editor styles for the block preview. + * + * This component replaces the body selector with the block editor selector. + * + * @since 3.16.0 + * + * @param {StylesProps} props The component props. + */ +const Styles = ( { styles }: StylesProps ): JSX.Element => { + // Get only the theme and user styles. + const filteredStyles = styles + .filter( ( style ) => { + return ( + style.__unstableType === 'theme' || + style.__unstableType === 'user' + ) && style.css; + } ); + + // Returns the styles, but replaces the body selector with the block editor selector. + return ( + <> + { filteredStyles.map( ( style, index ) => ( + + ) ) } + + ); +}; + +/** + * The props for the BlockPreview component. + * + * @since 3.16.0 + */ +type BlockPreviewProps = { + block: BlockInstance, + link: SmartLink, +} + +/** + * The BlockPreview component, which renders the block preview for the + * suggestion. + * + * @since 3.16.0 + * + * @param {BlockPreviewProps} props The component props. + */ +const BlockPreview = ( { block, link }: BlockPreviewProps ) => { + /** + * Clones the block to prevent editing the original block. + * The memoized block is used to prevent unnecessary re-renders. + * + * It updates when the block or link changes. + * + * @since 3.16.0 + */ + // eslint-disable-next-line react-hooks/exhaustive-deps + const clonedBlock = useMemo( () => cloneBlock( block ), [ block, link ] ); + + /** + * Runs when the block is rendered in the DOM. + * + * It will set the block element to be non-editable and highlight the link + * in the block. + * + * @since 3.16.0 + */ + useEffect( () => { + const blockPreviewElement = document.querySelector( '.wp-parsely-preview-editor' ); + + if ( ! blockPreviewElement ) { + return; + } + + /** + * Highlights the link in the block. + * + * @since 3.16.0 + * + * @param {BlockInstance} blockInstance The block instance to highlight the link in. + * @param {SmartLink} linkSuggestion The link suggestion to highlight. + */ + const highlightLinkInBlock = ( blockInstance: BlockInstance, linkSuggestion: SmartLink ) => { + // If the link is not applied, add a highlight with a new mark element. + if ( ! link.applied ) { + const mark = document.createElement( 'mark' ); + mark.className = 'smart-linking-highlight'; + blockInstance.attributes.content = applyNodeToBlock( blockInstance, linkSuggestion, mark ); + return; + } + + // Otherwise, if the link is applied, add a highlight class to the + // link element with the link UID. + const blockContent: string = getBlockContent( blockInstance ); + + const doc = new DOMParser().parseFromString( blockContent, 'text/html' ); + const contentElement = doc.body.firstChild as HTMLElement; + if ( ! contentElement ) { + return; + } + + const anchor = contentElement.querySelector( + `a[data-smartlink="${ linkSuggestion.uid }"]` + ); + if ( anchor ) { + anchor.classList.add( 'smart-linking-highlight' ); + } + + blockInstance.attributes.content = contentElement.innerHTML; + }; + + highlightLinkInBlock( clonedBlock, link ); + + const observer = new MutationObserver( ( mutations: MutationRecord[] ) => { + mutations.forEach( ( mutation: MutationRecord ) => { + if ( mutation.type === 'childList' ) { + // Temporarily disconnect observer to prevent observing our own changes. + observer.disconnect(); + + mutation.addedNodes.forEach( ( node ) => { + if ( node instanceof HTMLElement ) { + const blockElement = document.querySelector( + `.wp-parsely-preview-editor [data-block="${ clonedBlock.clientId }"]` + ); + + if ( blockElement ) { + // Disable editing on the block element. + blockElement.setAttribute( 'contenteditable', 'false' ); + } + } + } ); + + // Reconnect observer after changes. + observer.observe( document.body, { childList: true, subtree: true } ); + } + } ); + } ); + + observer.observe( blockPreviewElement, { + childList: true, + subtree: true, + } ); + + return () => observer.disconnect(); + }, [ clonedBlock, link ] ); + + if ( ! block ) { + return <>; + } + + const settings = selectFn( 'core/block-editor' ).getSettings(); + + return ( + + + + + + + ); +}; + +/** + * The LinkDetails component, which renders the details of the link suggestion. + * + * @since 3.16.0 + * + * @param {{link: SmartLink}} props The component props. + */ +const LinkDetails = ( { link }: { link: SmartLink } ): JSX.Element => { + // Get the post type by the permalink. + const [ displayUrl, setDisplayUrl ] = useState( link.href ); + const [ postType, setPostType ] = useState( link.post_type ); + const linkRef = useRef( null ); + + const { + updateSmartLink, + } = useDispatch( SmartLinkingStore ); + + /** + * Fetches the post type by the permalink using the SmartLinkingProvider. + * + * If the post type is not found, it will default to 'External'. + * + * @since 3.16.0 + */ + useEffect( () => { + if ( ! link.post_type ) { + setPostType( __( 'External', 'wp-parsely' ) ); + SmartLinkingProvider.getInstance().getPostTypeByURL( link.href ).then( ( type ) => { + if ( type ) { + setPostType( type ); + } + link.post_type = type ?? 'external'; + updateSmartLink( link ); + } ); + } else { + setPostType( link.post_type ); + } + }, [ link, updateSmartLink ] ); + + /** + * Trims the URL for display based on the container width. + * + * @since 3.16.0 + */ + useEffect( () => { + const calculateTrimSize = () => { + if ( linkRef.current ) { + const containerWidth = linkRef.current.offsetWidth; + const averageCharWidth = 8; // Estimate or adjust based on actual character width. + const maxLength = Math.floor( containerWidth / averageCharWidth ); + setDisplayUrl( trimURLForDisplay( link.href, maxLength ) ); + } + }; + + calculateTrimSize(); + + window.addEventListener( 'resize', calculateTrimSize ); + return () => { + window.removeEventListener( 'resize', calculateTrimSize ); + }; + }, [ link ] ); + + return ( + + { link.title } + + ); +}; + +/** + * The props for the ReviewSuggestion component. + * + * @since 3.16.0 + */ +type ReviewSuggestionProps = { + link: SmartLink, + onNext: () => void, + onPrevious: () => void, + onAccept: () => void, + onReject: () => void, + onRemove: () => void, + onSelectInEditor: () => void, + hasPrevious: boolean, + hasNext: boolean, +}; + +/** + * The ReviewSuggestion component, which renders the review suggestion UI. + * + * @since 3.16.0 + * + * @param {ReviewSuggestionProps} props The component props. + */ +export const ReviewSuggestion = ( { + link, + onNext, + onPrevious, + onAccept, + onReject, + onRemove, + onSelectInEditor, + hasPrevious, + hasNext, +}: ReviewSuggestionProps ): JSX.Element => { + if ( ! link?.match ) { + return <>{ __( 'This Smart Link does not have any matches in the current content.', 'wp-parsely' ) }; + } + + const blockId = link.match.blockId; + // Get the block. + const block = selectFn( 'core/block-editor' ).getBlock( blockId ); + const isApplied = link.applied; + + if ( ! block ) { + return <>{ __( 'No block is selected.', 'wp-parsely' ) }; + } + + return ( +
+ +
+ +
+ + +
+ + + +
+ { ! isApplied && ( + <> + + + + + + + + ) } + { isApplied && ( + <> + + + + + + ) } +
+ + + +
+
+ ); +}; diff --git a/src/content-helper/editor-sidebar/smart-linking/smart-linking.scss b/src/content-helper/editor-sidebar/smart-linking/smart-linking.scss index da495fe6f..29666dbaf 100644 --- a/src/content-helper/editor-sidebar/smart-linking/smart-linking.scss +++ b/src/content-helper/editor-sidebar/smart-linking/smart-linking.scss @@ -161,7 +161,8 @@ } - .smart-linking-generate { + .smart-linking-generate, + .smart-linking-manage { display: flex; padding: to_rem(6px) 0 var(--grid-unit-20) 0; flex-direction: column; @@ -185,3 +186,207 @@ margin-top: calc(var(--grid-unit-10) * -1); } } + +.wp-parsely-smart-linking-review-modal { + display: flex; + width: to_rem(766px); + flex-direction: column; + align-items: flex-start; + + .smart-linking-modal-body { + display: flex; + flex-direction: row; + gap: var(--grid-unit-30); + align-self: stretch; + } + + .wp-parsely-link-suggestion-link-details { + text-align: left; + height: auto; + margin-bottom: var(--grid-unit-20); + + .components-menu-item__item { + display: inline-block; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + .smart-linking-review-sidebar { + display: flex; + min-width: to_rem(220px); + max-height: to_rem(400px); + overflow-y: auto; + padding: to_rem(3px); + flex-direction: column; + align-items: flex-start; + gap: var(--grid-unit-20); + align-self: stretch; + + .review-sidebar-header { + margin-bottom: var(--grid-unit-15); + display: flex; + align-items: center; + gap: to_rem(6px); + align-self: stretch; + color: var(--sidebar-black); + font-size: to_rem(11px); + font-style: normal; + font-weight: 600; + line-height: var(--grid-unit-20); + text-transform: uppercase; + + > span { + color: var(--Gutenberg-Gray-700, #757575); + } + } + + .components-button.components-menu-item__button { + width: to_rem(220px); + display: flex; + align-items: center; + justify-content: space-between; + + &:focus { + outline: none; + box-shadow: none; + } + + .smart-linking-menu-label { + display: flex; + align-items: center; + white-space: nowrap; + padding-left: var(--grid-unit-10); + color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); + } + + &.is-selected { + background-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); + color: #fff; + + .smart-linking-menu-label { + color: #fff; + } + } + + .components-menu-item__item { + width: 100%; + padding-right: 0; + } + + .smart-linking-menu-item { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + display: inline; + text-align: left; + flex-grow: 1; + } + } + } + + .smart-linking-review-suggestion { + max-width: to_rem(452px); + display: flex; + flex-direction: column; + align-items: flex-start; + gap: to_rem(16px); + flex: 1; + align-self: stretch; + + .review-suggestions-breadcrumbs { + font-size: to_rem(12px); + + .breadcrumbs-parent-separator { + margin: 0 var(--grid-unit-5); + } + + .breadcrumbs-parent-block { + color: var(--Gutenberg-Gray-700, #757575); + } + + .breadcrumbs-current-block { + color: var(--sidebar-black); + + .breadcrumbs-current-block-name { + margin-left: var(--grid-unit-10); + } + } + } + + .components-divider { + width: to_rem(452px); + height: 1px; + border-color: #ccc; + } + + .review-controls { + display: flex; + width: to_rem(452px); + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; + margin: 0 var(--grid-unit-20); + user-select: none; + + .reviews-controls-middle { + display: flex; + justify-content: center; + align-items: center; + gap: var(--grid-unit-20); + flex: 1 0 0; + } + + .wp-parsely-review-suggestion-previous, + .wp-parsely-review-suggestion-next { + color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); + } + + .wp-parsely-review-suggestion-reject { + border-radius: 2px; + box-shadow: inset 0 0 0 1px var(--Gutenberg-Alert-Red, #cc1818); + background: var(--Gutenberg-White, #fff); + color: var(--Gutenberg-Alert-Red, #cc1818); + } + } + } +} + +.wp-parsely-smart-linking-close-dialog { + display: flex; + width: to_rem(384px); + flex-direction: column; + align-items: flex-start; + + .smart-linking-close-dialog-actions { + display: flex; + padding-top: var(--grid-unit-30); + justify-content: flex-end; + align-items: center; + gap: var(--grid-unit-15); + align-self: stretch; + } +} + +.wp-parsely-preview-editor { + + &.editor-styles-wrapper { + padding-bottom: 0; + font-size: var(--font-size--medium); + } + + p[role="document"] { + margin: 0; + } + + .smart-linking-highlight { + border-radius: 2px; + background: hsla(var(--parsely-green-components), 0.5); + mix-blend-mode: multiply; + text-decoration-line: underline; + color: var(--sidebar-black); + } +} diff --git a/src/content-helper/editor-sidebar/smart-linking/store.ts b/src/content-helper/editor-sidebar/smart-linking/store.ts index 07db39bfb..0f8c5adc4 100644 --- a/src/content-helper/editor-sidebar/smart-linking/store.ts +++ b/src/content-helper/editor-sidebar/smart-linking/store.ts @@ -2,13 +2,14 @@ * WordPress dependencies */ import { createReduxStore, register } from '@wordpress/data'; -import { ContentHelperError } from '../../common/content-helper-error'; -import { DEFAULT_MAX_LINKS } from './smart-linking'; /** * Internal dependencies */ -import { LinkSuggestion } from './provider'; +import { ContentHelperError } from '../../common/content-helper-error'; +import { DEFAULT_MAX_LINKS } from './smart-linking'; +import { SmartLink } from './provider'; +import { sortSmartLinks } from './utils'; /** * Defines the props structure for SmartLinkingSettings. @@ -35,20 +36,31 @@ export enum ApplyToOptions { * @since 3.14.0 */ type SmartLinkingState = { + isReady: boolean; isLoading: boolean; applyTo: ApplyToOptions|null; fullContent: boolean; error: ContentHelperError | null; settings: SmartLinkingSettingsProps; - suggestedLinks: LinkSuggestion[] | null; + smartLinks: SmartLink[]; overlayBlocks: string[]; wasAlreadyClicked: boolean; isRetrying: boolean; retryAttempt: number; + isReviewModalOpen: boolean; }; -/********** Actions ********** / +/********** Actions **********/ +/** + * Interface for the SetIsReadyAction. + * + * @since 3.16.0 + */ +interface SetIsReadyAction { + type: 'SET_IS_READY'; + isReady: boolean; +} /** * Interface for the SetLoadingAction. * @@ -119,16 +131,6 @@ interface SetSettingsAction { settings: SmartLinkingSettingsProps; } -/** - * Interface for the SetSuggestedLinksAction. - * - * @since 3.14.0 - */ -interface SetSuggestedLinksAction { - type: 'SET_SUGGESTED_LINKS'; - suggestedLinks: LinkSuggestion[] | null; -} - /** * Interface for the SetWasAlreadyClickedAction. * @@ -159,6 +161,55 @@ interface SetIsRetryingAction { isRetrying: boolean; } +/** + * Interface for the SetSmartLinksAction. + * + * @since 3.16.0 + */ +interface SetSmartLinksAction { + type: 'SET_SMART_LINKS'; + smartLinks: SmartLink[]; +} + +/** + * Interface for the AddSmartLinkAction. + * + * @since 3.16.0 + */ +interface AddSmartLinkAction { + type: 'ADD_SMART_LINK'; + smartLink: SmartLink; +} + +/** + * Interface for the AddSmartLinksAction. + * + * @since 3.16.0 + */ +interface AddSmartLinksAction { + type: 'ADD_SMART_LINKS'; + smartLinks: SmartLink[]; +} + +/** + * Interface for the RemoveSmartLinkAction. + * + * @since 3.16.0 + */ +interface RemoveSmartLinkAction { + type: 'REMOVE_SMART_LINK'; + uid: string; +} + +/** + * Interface for the PurgeSmartLinksSuggestionsAction. + * + * @since 3.16.0 + */ +interface PurgeSmartLinksSuggestionsAction { + type: 'PURGE_SMART_LINKS_SUGGESTIONS'; +} + /** * Interface for the IncrementRetryAttemptAction. * @@ -168,21 +219,34 @@ interface IncrementRetryAttemptAction { type: 'INCREMENT_RETRY_ATTEMPT'; } -type ActionTypes = SetLoadingAction | SetOverlayBlocksAction | SetSettingsAction | +/** + * Interface for the SetIsReviewModalOpenAction. + * + * @since 3.16.0 + */ +interface SetIsReviewModalOpenAction { + type: 'SET_IS_REVIEW_MODAL_OPEN'; + isReviewModalOpen: boolean; +} + +type ActionTypes = SetIsReadyAction | SetLoadingAction | SetOverlayBlocksAction | SetSettingsAction | AddOverlayBlockAction | RemoveOverlayBlockAction |SetFullContentAction | - SetSuggestedLinksAction | SetErrorAction| SetWasAlreadyClickedAction | SetApplyToAction | - IncrementRetryAttemptAction | SetIsRetryingAction; + SetErrorAction| SetWasAlreadyClickedAction | SetApplyToAction | IncrementRetryAttemptAction | + SetIsRetryingAction | SetSmartLinksAction | AddSmartLinkAction | AddSmartLinksAction | RemoveSmartLinkAction | + PurgeSmartLinksSuggestionsAction | SetIsReviewModalOpenAction; const defaultState: SmartLinkingState = { + isReady: false, isLoading: false, applyTo: null, fullContent: false, - suggestedLinks: null, + smartLinks: [], error: null, settings: { }, overlayBlocks: [], wasAlreadyClicked: false, isRetrying: false, + isReviewModalOpen: false, retryAttempt: 0, }; @@ -195,6 +259,11 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { initialState: defaultState, reducer( state: SmartLinkingState = defaultState, action: ActionTypes ): SmartLinkingState { switch ( action.type ) { + case 'SET_IS_READY': + return { + ...state, + isReady: action.isReady, + }; case 'SET_LOADING': return { ...state, @@ -240,11 +309,6 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { ...action.settings, }, }; - case 'SET_SUGGESTED_LINKS': - return { - ...state, - suggestedLinks: action.suggestedLinks, - }; case 'SET_WAS_ALREADY_CLICKED': return { ...state, @@ -266,11 +330,70 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { ...state, retryAttempt: state.retryAttempt + 1, }; + case 'SET_SMART_LINKS': + return { + ...state, + smartLinks: sortSmartLinks( action.smartLinks ), + }; + case 'ADD_SMART_LINK': + // If the UID is already there, just update it, otherwise add it. + const existingIndex = state.smartLinks.findIndex( ( link ) => link.uid === action.smartLink.uid ); + if ( existingIndex !== -1 ) { + const newSmartLinks = [ ...state.smartLinks ]; + newSmartLinks[ existingIndex ] = action.smartLink; + return { + ...state, + smartLinks: sortSmartLinks( newSmartLinks ), + }; + } + return { + ...state, + smartLinks: sortSmartLinks( [ ...state.smartLinks, action.smartLink ] ), + }; + case 'ADD_SMART_LINKS': + // If the UID is already there, just update it, otherwise add it. + const newSmartLinks = [ ...state.smartLinks ]; + action.smartLinks.forEach( ( link ) => { + // eslint-disable-next-line @typescript-eslint/no-shadow + const existingIndex = state.smartLinks.findIndex( ( l ) => l.uid === link.uid ); + if ( existingIndex !== -1 ) { + newSmartLinks[ existingIndex ] = { ...newSmartLinks[ existingIndex ], ...link }; + } else { + newSmartLinks.push( link ); + } + } ); + return { + ...state, + smartLinks: sortSmartLinks( newSmartLinks ), + }; + case 'REMOVE_SMART_LINK': + return { + ...state, + smartLinks: + sortSmartLinks( state.smartLinks.filter( ( link ) => link.uid !== action.uid ) ), + }; + case 'PURGE_SMART_LINKS_SUGGESTIONS': + return { + ...state, + smartLinks: + sortSmartLinks( state.smartLinks.filter( ( link ) => link.applied ) ), + }; + case 'SET_IS_REVIEW_MODAL_OPEN': + return { + ...state, + isReviewModalOpen: action.isReviewModalOpen, + }; default: return state; } }, actions: { + setIsReady( isReady: boolean ): SetIsReadyAction { + return { + type: 'SET_IS_READY', + isReady, + }; + }, setLoading( isLoading: boolean ): SetLoadingAction { return { type: 'SET_LOADING', @@ -321,12 +444,6 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { }, }; }, - setSuggestedLinks( suggestedLinks: LinkSuggestion[] | null ): SetSuggestedLinksAction { - return { - type: 'SET_SUGGESTED_LINKS', - suggestedLinks, - }; - }, setAlreadyClicked( wasAlreadyClicked: boolean ): SetWasAlreadyClickedAction { return { type: 'SET_WAS_ALREADY_CLICKED', @@ -350,14 +467,62 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { type: 'INCREMENT_RETRY_ATTEMPT', }; }, + setSmartLinks( smartLinks: SmartLink[] ): SetSmartLinksAction { + return { + type: 'SET_SMART_LINKS', + smartLinks, + }; + }, + addSmartLink( smartLink: SmartLink ): AddSmartLinkAction { + return { + type: 'ADD_SMART_LINK', + smartLink, + }; + }, + updateSmartLink( smartLink: SmartLink ): AddSmartLinkAction { + // Alias of addSmartLink. + return { + type: 'ADD_SMART_LINK', + smartLink, + }; + }, + addSmartLinks( smartLinks: SmartLink[] ): AddSmartLinksAction { + return { + type: 'ADD_SMART_LINKS', + smartLinks, + }; + }, + removeSmartLink( uid: string ): RemoveSmartLinkAction { + return { + type: 'REMOVE_SMART_LINK', + uid, + }; + }, + purgeSmartLinksSuggestions(): PurgeSmartLinksSuggestionsAction { + return { + type: 'PURGE_SMART_LINKS_SUGGESTIONS', + }; + }, + setIsReviewModalOpen( isReviewModalOpen: boolean ): SetIsReviewModalOpenAction { + return { + type: 'SET_IS_REVIEW_MODAL_OPEN', + isReviewModalOpen, + }; + }, }, selectors: { + isReady( state: SmartLinkingState ): boolean { + return state.isReady; + }, isLoading( state: SmartLinkingState ): boolean { return state.isLoading; }, isFullContent( state: SmartLinkingState ): boolean { return state.fullContent; }, + isReviewModalOpen( state: SmartLinkingState ): boolean { + return state.isReviewModalOpen; + }, getApplyTo( state: SmartLinkingState ): ApplyToOptions|null { return state.applyTo; }, @@ -373,8 +538,8 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { getMaxLinks( state: SmartLinkingState ): number { return state.settings.maxLinksPerPost ?? DEFAULT_MAX_LINKS; }, - getSuggestedLinks( state: SmartLinkingState ): LinkSuggestion[] | null { - return state.suggestedLinks; + getSuggestedLinks( state: SmartLinkingState ): SmartLink[] { + return state.smartLinks.filter( ( link ) => ! link.applied ); }, wasAlreadyClicked( state: SmartLinkingState ): boolean { return state.wasAlreadyClicked; @@ -385,6 +550,12 @@ export const SmartLinkingStore = createReduxStore( 'wp-parsely/smart-linking', { getRetryAttempt( state: SmartLinkingState ): number { return state.retryAttempt; }, + hasUnappliedLinks( state: SmartLinkingState ): boolean { + return state.smartLinks.some( ( link ) => ! link.applied ); + }, + getSmartLinks( state: SmartLinkingState ): SmartLink[] { + return state.smartLinks; + }, }, } ); diff --git a/src/content-helper/editor-sidebar/smart-linking/utils.ts b/src/content-helper/editor-sidebar/smart-linking/utils.ts index 130249d19..1f4dd3136 100644 --- a/src/content-helper/editor-sidebar/smart-linking/utils.ts +++ b/src/content-helper/editor-sidebar/smart-linking/utils.ts @@ -1,13 +1,29 @@ +/** + * WordPress dependencies + */ +// eslint-disable-next-line import/named +import { BlockInstance, getBlockContent } from '@wordpress/blocks'; +import { dispatch, select } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { dispatchCoreBlockEditor } from '../../../@types/gutenberg/types'; +import { escapeRegExp } from '../../common/utils/functions'; +import { SmartLink } from './provider'; +import { SmartLinkingStore } from './store'; export { escapeRegExp } from '../../common/utils/functions'; /** - * Finds all text nodes in an element that contain a given search text and are not within an anchor tag. + * Finds all text nodes in an element that contain a given search text and are + * not within an anchor tag. + * * This is useful for finding text nodes that should be linked. * * @since 3.14.1 * - * @param {HTMLElement} element - The element to search within. - * @param {string} searchText - The text to search for. + * @param {HTMLElement} element The element to search within. + * @param {string} searchText The text to search for. * * @return {Node[]} The text nodes that match the search text and are not within an anchor tag. */ @@ -35,3 +51,589 @@ export function findTextNodesNotInAnchor( element: HTMLElement, searchText: stri } return textNodes; } + +/** + * Checks if a smart link is present in a text node. + * + * @since 3.16.0 + * + * @param {Text} textNode The text node to check. + * @param {string} smartLinkUID The smart link UID to check for. + * + * @return {boolean} Whether the smart link is present in the text node. + */ +function isLinkAtNode( textNode: Text, smartLinkUID: string ): boolean { + let parentNode: Node | null = textNode; + while ( parentNode && ! ( parentNode instanceof HTMLAnchorElement ) ) { + parentNode = parentNode.parentNode; + } + return parentNode instanceof HTMLAnchorElement && parentNode.dataset.smartlink === smartLinkUID; +} + +/** + * Checks if a node is inside a similar node to a reference node. + * + * @since 3.16.0 + * + * @param {Node} node The node to check. + * @param {HTMLElement} referenceNode The reference node to compare against. + * + * @return {boolean} Whether the node is inside a similar node to the reference node. + */ +function isInsideSimilarNode( node: Node, referenceNode: HTMLElement ): boolean { + let currentNode = node.parentNode; + while ( currentNode ) { + // Check by nodeName or any specific attribute. + if ( currentNode.nodeName === referenceNode.nodeName ) { + return true; + } + currentNode = currentNode.parentNode; + } + return false; +} + +/** + * Finds all text nodes in an element that contain a given search text. + * + * @since 3.16.0 + * + * @param {Node} element The element to search within. + * @param {string} searchText The text to search for. + * + * @return {Node[]} The text nodes that match the search text and are not within a similar node. + */ +function findTextNodes( element: Node, searchText: string ): Node[] { + const textNodes: Node[] = []; + const walker = document.createTreeWalker( element, NodeFilter.SHOW_TEXT, null ); + + while ( walker.nextNode() ) { + const node = walker.currentNode; + if ( node.textContent && node.textContent.includes( searchText ) ) { + textNodes.push( node ); + } + } + + return textNodes; +} + +/** + * Applies an HTML node to a block's content, replacing the text of the link + * with the HTML node. + * + * This is useful for applying a link to a block's content. + * + * @since 3.16.0 + * + * @param {BlockInstance} block The block instance to apply the link to. + * @param {SmartLink} link The link suggestion to apply. + * @param {HTMLElement} htmlNode The HTML node to apply to the block. + * + * @return {string|undefined} The updated block content, or `undefined` if the block content could not be updated. + */ +export function applyNodeToBlock( + block: BlockInstance, + link: SmartLink, + htmlNode: HTMLElement +): string|undefined { + const blockContent: string = getBlockContent( block ); + + const doc = new DOMParser().parseFromString( blockContent, 'text/html' ); + const contentElement = doc.body.firstChild as HTMLElement; + + if ( ! contentElement ) { + return; + } + + const textNodes = findTextNodes( contentElement, link.text ); + + let occurrenceCount = 0; + let hasAddedNode = false; + + textNodes.forEach( ( node ) => { + if ( ! node.textContent || hasAddedNode ) { + return; + } + + if ( isInsideSimilarNode( node, htmlNode ) ) { + // Check if the node content contains the link text, and if so + // increase the occurrence count. + if ( node.textContent?.includes( link.text ) ) { + occurrenceCount++; + } + return; + } + + const regex = new RegExp( escapeRegExp( link.text ), 'g' ); + let match; + while ( ( match = regex.exec( node.textContent ) ) !== null ) { + if ( occurrenceCount === link.match?.blockOffset ) { + const anchor: HTMLElement = htmlNode.cloneNode( true ) as HTMLElement; + anchor.textContent = match[ 0 ]; + + const range = document.createRange(); + range.setStart( node, match.index ); + range.setEnd( node, match.index + match[ 0 ].length ); + range.deleteContents(); + range.insertNode( anchor ); + + if ( node.textContent && match.index + match[ 0 ].length < node.textContent.length ) { + const remainingText = document.createTextNode( + node.textContent.slice( match.index + match[ 0 ].length ) + ); + node.parentNode?.insertBefore( remainingText, anchor.nextSibling ); + } + + hasAddedNode = true; + + return; + } + occurrenceCount++; + } + } ); + + // Update the block content with the new content. + dispatchCoreBlockEditor.updateBlockAttributes( block.clientId, { content: contentElement.innerHTML } ); + return contentElement.innerHTML; +} + +/** + * Sorts smart links based on their block position and link position within the + * block. + * + * The applied links are sorted after the not applied links. + * + * @since 3.16.0 + * + * @param {SmartLink[]} smartLinks The smart links to sort. + * + * @return {SmartLink[]} The sorted smart links. + */ +export function sortSmartLinks( smartLinks: SmartLink[] ): SmartLink[] { + // Break-down in two buckets: applied and not applied. + const appliedLinks = smartLinks.filter( ( link ) => link.applied ); + const notAppliedLinks = smartLinks.filter( ( link ) => ! link.applied ); + + const sortByBlockPosition = ( a: SmartLink, b: SmartLink ) => { + if ( a.match!.blockPosition === b.match!.blockPosition ) { + return a.match!.blockLinkPosition - b.match!.blockLinkPosition; + } + return a.match!.blockPosition - b.match!.blockPosition; + }; + + appliedLinks.sort( sortByBlockPosition ); + notAppliedLinks.sort( sortByBlockPosition ); + + return [ ...notAppliedLinks, ...appliedLinks ]; +} + +/** + * Recursively collect all blocks into a flat array. + * + * @since 3.16.0 + * + * @param {BlockInstance[]} blocks The blocks to flatten. + * @param {BlockInstance[]} flatList The flat list of blocks. + * + * @return {BlockInstance[]} The flat list of blocks. + */ +function flattenBlocks( blocks: BlockInstance[], flatList: BlockInstance[] = [] ): BlockInstance[] { + blocks.forEach( ( block ) => { + if ( block.innerBlocks.length ) { + return flattenBlocks( block.innerBlocks, flatList ); + } + flatList.push( block ); + } ); + return flatList; +} + +/** + * Represents the counts of occurrences and applications of links within text + * content. + * + * - `encountered`: The number of times a specific link text is encountered in + * the content. + * - `linked`: The number of times a link has been successfully applied for a + * specific link text. + * + * @since 3.14.1 + * @since 3.16.0 Moved from `content-helper/editor-sidebar/smart-linking/component.tsx`. + */ +type LinkOccurrenceCounts = { + [key: string]: { + encountered: number; + linked: number; + }; +}; + +/** + * Iterates through blocks of content to calculate the correct block and offset + * for each link suggestion. + * + * This function processes each block's content to identify and handle text + * nodes that match provided link suggestions. It avoids inserting links within + * existing anchor and respects the specified offset for each link to determine + * the correct block. + * + * Note: The function is recursive for blocks containing inner blocks, ensuring + * all nested content is processed. + * + * @since 3.16.0 + * + * @param {Readonly[]} blocks The blocks of content where links should be applied. + * @param {SmartLink[]} links An array of link suggestions to apply to the content. + * @param {LinkOccurrenceCounts} occurrenceCounts An object to keep track of the number of times each link + * text has been encountered and applied across all blocks. + * @param {number} currentIndex The current index of the block being processed. + * + * @return {SmartLink[]} The array of link suggestions that have been successfully applied to the content. + */ +export function calculateSmartLinkingMatches( + blocks: Readonly[], + links: SmartLink[], + occurrenceCounts: LinkOccurrenceCounts = {}, + currentIndex: number = 0 +): SmartLink[] { + blocks.forEach( ( block, index ) => { + const currentBlockIndex = currentIndex + index; + + if ( block.innerBlocks?.length ) { + calculateSmartLinkingMatches( block.innerBlocks, links, occurrenceCounts, currentBlockIndex ); + return; + } + + if ( ! block.originalContent ) { + return; + } + + const blockContent: string = getBlockContent( block ); + const doc = new DOMParser().parseFromString( blockContent, 'text/html' ); + const contentElement = doc.body.firstChild; + + if ( ! ( contentElement instanceof HTMLElement ) ) { + return; + } + + const fullContentPlain = contentElement.textContent; + + links.forEach( ( link ) => { + const textNodes = findTextNodesNotInAnchor( contentElement, link.text ); + const occurrenceKey = `${ link.text }#${ link.offset }`; + occurrenceCounts[ occurrenceKey ] = occurrenceCounts[ occurrenceKey ] || { encountered: 0, linked: 0 }; + + let cumulativeTextLength = 0; + let blockOffsetCounter = 0; + + textNodes.forEach( ( node ) => { + const regex = new RegExp( escapeRegExp( link.text ), 'g' ); + let match; + const nodeText = node.textContent ?? ''; + const startPosition = fullContentPlain?.indexOf( nodeText, cumulativeTextLength ) ?? 0; + + while ( ( match = regex.exec( nodeText ) ) !== null ) { + const occurrenceCount = occurrenceCounts[ occurrenceKey ]; + occurrenceCount.encountered++; + blockOffsetCounter++; + + if ( occurrenceCount.encountered - 1 === link.offset && occurrenceCount.linked < 1 ) { + occurrenceCount.linked++; + link.match = { + blockId: block.clientId, + blockOffset: blockOffsetCounter - 1, + blockPosition: currentBlockIndex, + blockLinkPosition: startPosition + match.index, + }; + } + } + + cumulativeTextLength += nodeText.length; + } ); + } ); + } ); + + return links; +} + +/** + * Gets all smart links in the post content. + * + * This function parses the post content to find all the smart links in the post + * content. Each smart link is identified by the `data-smartlink` attribute in + * the anchor tag. + * + * After finding all the smart links, it calculates the correct block and offset + * for each link suggestion. + * + * @since 3.16.0 + * + * @return {SmartLink[]} The smart links in the post content. + */ +export function getAllSmartLinksInPost(): SmartLink[] { + const blocks = flattenBlocks( select( 'core/block-editor' ).getBlocks() ); + const postContent = select( 'core/editor' ).getEditedPostContent(); + const parser = new DOMParser(); + const doc = parser.parseFromString( postContent, 'text/html' ); + const allLinks = Array.from( doc.querySelectorAll( 'a[data-smartlink]' ) as NodeListOf ); + const smartLinks: SmartLink[] = []; + + allLinks.forEach( ( link ) => { + const uid = link.getAttribute( 'data-smartlink' ) ?? ''; + const href = link.href; + const text = link.textContent ?? ''; + const title = link.title; + + // Find the block this link belongs to. + const block = blocks.find( + ( blockInstance ) => getBlockContent( blockInstance ).includes( uid ) + ); + + if ( ! block ) { + return; + } + + const blockIndex = blocks.indexOf( block ); + + const smartLink: SmartLink = { + uid, + href, + text, + title, + applied: true, + offset: getLinkOffset( link, doc ), + match: { + blockId: block?.clientId ?? '', + blockPosition: blockIndex, + blockOffset: -1, // Will be calculated later. + blockLinkPosition: -1, // Will be calculated later. + }, + }; + + smartLinks.push( smartLink ); + } ); + + return calculateSmartLinkingMatches( blocks, smartLinks ); +} + +/** + * Gets the offset of a link in the post content. + * + * This function calculates the offset of a link in the post content by counting + * the number of times the link text is encountered before the link in the post + * content. + * + * @since 3.16.0 + * + * @param {HTMLAnchorElement} link The link to calculate the offset for. + * @param {Document} document The document to search the link in. + * + * @return {number} The offset of the link in the post content. + */ +function getLinkOffset( link: HTMLAnchorElement, document: Document ): number { + const smartLinkUID = link.dataset.smartlink; + const linkText = link.textContent?.trim(); + + if ( ! smartLinkUID ) { + return -1; + } + if ( ! linkText ) { + return -1; + } + + let occurrence = 0; + + const treeWalker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT ); + while ( treeWalker.nextNode() ) { + const textNode = treeWalker.currentNode as Text; + const nodeValue = textNode.nodeValue ?? ''; + let pos = nodeValue.indexOf( linkText ); + + while ( pos !== -1 ) { + if ( isLinkAtNode( textNode, smartLinkUID ) ) { + return occurrence; + } + + // Move to next occurrence of linkText in the current text node. + pos = nodeValue.indexOf( linkText, pos + linkText.length ); + occurrence++; + } + } + + return -1; +} + +/** + * Represents the return type of the `validateAndFixSmartLinks` function. + * + * @since 3.16.0 + */ +type ValidateAndFixSmartLinksReturnType = { + missingSmartLinks: SmartLink[], + didAnyFixes: boolean +}; + +/** + * Validates and fixes smart links in a specific content. + * + * This function checks if the smart links in the store are still present in the + * post content. If a smart link is not found in the post content, it tries to + * find a link that matches the text, title and href of the smart link. And if + * the link is found, it restores the missing fields from the link + * (data-smartlink and title). + * + * @since 3.16.0 + * + * @param {string} content The post content to validate and fix smart links. + * @param {string|false} blockId The block ID to filter the smart links by. + * + * @return {ValidateAndFixSmartLinksReturnType} The missing smart links and whether any fixes were made. + */ +export async function validateAndFixSmartLinks( + content: string, + blockId: string|false = false +): Promise { + // Get the post content and all the smart links from the store. + let smartLinks = select( SmartLinkingStore ).getSmartLinks(); + + // If a blockId is provided, filter out all the smart links that don't belong to the block. + if ( blockId ) { + smartLinks = smartLinks.filter( ( smartLink ) => smartLink.match?.blockId === blockId ); + } + + // Create a DOM from the post content. + const parser = new DOMParser(); + const doc = parser.parseFromString( content, 'text/html' ); + + const missingSmartLinks: SmartLink[] = []; + + // Check for each smart link UID in the post content. + smartLinks.forEach( ( smartLink ) => { + // Search for the link with the UID in the post content. + const link = doc.querySelector( `a[data-smartlink="${ smartLink.uid }"]` ); + + // If the link is not found, add it to the missing smart links array. + if ( ! link ) { + missingSmartLinks.push( smartLink ); + } + } ); + + // Flag to check if any fixes were made. + let didAnyFixes = false; + + // For each missing smart link, try to find a link that matches the text, title and href. + for ( let i = 0; i < missingSmartLinks.length; i++ ) { + const missingSmartLink = missingSmartLinks[ i ]; + if ( ! missingSmartLink.match?.blockId ) { + continue; + } + + // Get the block that contains the smart link. + const block = select( 'core/block-editor' ).getBlock( missingSmartLink.match?.blockId ); + + if ( ! block ) { + continue; + } + + const blockContent: string = getBlockContent( block ); + const blockDoc = new DOMParser().parseFromString( blockContent, 'text/html' ); + + const link = Array.from( blockDoc.querySelectorAll( 'a' ) ).find( ( a ) => { + return a.textContent === missingSmartLink.text && + a.href === missingSmartLink.href && + ! a.hasAttribute( 'data-smartlink' ); + } ); + + if ( ! link ) { + continue; + } + + // If the link is found, remove it from the missing smart links array. + missingSmartLinks.splice( i--, 1 ); + + // Restore the missing fields from the link (data-smartlink and title). + link.setAttribute( 'data-smartlink', missingSmartLink.uid ); + link.title = missingSmartLink.title; + + // Update the block content with the new content. + const paragraph = blockDoc.body.firstChild as HTMLElement; + dispatchCoreBlockEditor.updateBlockAttributes( + block.clientId, { content: paragraph.innerHTML } + ); + didAnyFixes = true; + } + + return { missingSmartLinks, didAnyFixes }; +} + +/** + * Validates and fixes smart links in the post content. + * + * @since 3.16.0 + * + * @return {boolean} Whether any fixes were made. + */ +export async function validateAndFixSmartLinksInPost(): Promise { + const postContent = select( 'core/editor' ).getEditedPostContent(); + const { missingSmartLinks, didAnyFixes } = await validateAndFixSmartLinks( postContent ); + + // Remove any missing smart links that are not in the store. + missingSmartLinks.forEach( ( missingLink ) => { + dispatch( SmartLinkingStore ).removeSmartLink( missingLink.uid ); + } ); + + return didAnyFixes; +} + +/** + * Validates and fixes smart links in a block content. + * + * @since 3.16.0 + * + * @param {BlockInstance} block The block instance to validate and fix smart links. + * + * @return {boolean} Whether any fixes were made. + */ +export async function validateAndFixSmartLinksInBlock( block: BlockInstance ): Promise { + const blockContent: string = getBlockContent( block ); + const { missingSmartLinks, didAnyFixes } = await validateAndFixSmartLinks( blockContent, block.clientId ); + + // Remove any missing smart links that are not in the store. + missingSmartLinks.forEach( ( missingLink ) => { + dispatch( SmartLinkingStore ).removeSmartLink( missingLink.uid ); + } ); + + return didAnyFixes; +} + +/** + * Trims a URL for display, ensuring it fits within the specified maximum length. + * + * @since 3.16.0 + * + * @param {string} url The URL to trim. + * @param {number} maxLength The maximum length of the URL. + * + * @return {string} The trimmed URL. + */ +export function trimURLForDisplay( url: string, maxLength: number ): string { + // Remove protocol (http, https) and www. + const strippedUrl = url.replace( /(^\w+:|^)\/\//, '' ).replace( /^www\./, '' ); + + // If no maxLength is specified or the URL length is already less than + // maxLength, return the stripped URL. + if ( ! maxLength || strippedUrl.length <= maxLength ) { + return strippedUrl; + } + + // Get the domain name and path from the URL + const domain = strippedUrl.split( '/' )[ 0 ]; + const path = strippedUrl.substring( domain.length ); + + // Update the maxLength to account for the domain name, plus a slash. + maxLength -= domain.length; + + // Calculate part lengths for trimming. + const partLength = Math.floor( ( maxLength - 3 ) / 2 ); + const start = path.substring( 0, partLength ); + const end = path.substring( path.length - partLength ); + + return `${ domain }${ start }...${ end }`; +} diff --git a/tests/Integration/BaseUserMetaEndpointTest.php b/tests/Integration/BaseUserMetaEndpointTest.php index befd671e8..a32e32cc3 100644 --- a/tests/Integration/BaseUserMetaEndpointTest.php +++ b/tests/Integration/BaseUserMetaEndpointTest.php @@ -145,4 +145,24 @@ protected function send_put_request( string $data ): string { 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/ProxyEndpointTest.php b/tests/Integration/ProxyEndpointTest.php index 81a923b67..030871970 100644 --- a/tests/Integration/ProxyEndpointTest.php +++ b/tests/Integration/ProxyEndpointTest.php @@ -38,7 +38,7 @@ abstract class ProxyEndpointTest extends TestCase { * * @var callable $rest_api_init_proxy */ - private $rest_api_init_proxy; + protected $rest_api_init_proxy; /** * Route of the WP REST endpoint. diff --git a/tests/Integration/RemoteAPI/content-suggestions/SuggestLinkedReferenceAPITest.php b/tests/Integration/RemoteAPI/content-suggestions/SuggestLinkedReferenceAPITest.php index 49d3b4c84..21d2d3c8d 100644 --- a/tests/Integration/RemoteAPI/content-suggestions/SuggestLinkedReferenceAPITest.php +++ b/tests/Integration/RemoteAPI/content-suggestions/SuggestLinkedReferenceAPITest.php @@ -10,6 +10,7 @@ namespace Parsely\Tests\Integration\RemoteAPI\ContentSuggestions; +use Parsely\Models\Smart_Link; use Parsely\Parsely; use Parsely\RemoteAPI\ContentSuggestions\Suggest_Linked_Reference_API; @@ -153,7 +154,7 @@ public function test_get_links(): void { // instance. foreach ( $suggested_links as $suggested_link ) { self::assertIsObject( $suggested_link ); - self::assertInstanceOf( 'Parsely\RemoteAPI\ContentSuggestions\Link_Suggestion', $suggested_link ); + self::assertInstanceOf( Smart_Link::class, $suggested_link ); } // Remove mock. diff --git a/tests/js/content-helper/smart-linking.test.tsx b/tests/js/content-helper/smart-linking.test.tsx new file mode 100644 index 000000000..664892a77 --- /dev/null +++ b/tests/js/content-helper/smart-linking.test.tsx @@ -0,0 +1,23 @@ +import { trimURLForDisplay } from '../../../src/content-helper/editor-sidebar/smart-linking/utils'; + +describe( 'trimURLForDisplay', () => { + it( 'should remove protocol and www', () => { + expect( trimURLForDisplay( 'https://www.example.com', 20 ) ).toBe( 'example.com' ); + } ); + + it( 'should keep the domain in long URLs correctly', () => { + expect( trimURLForDisplay( 'https://www.example.com/long-url-path', 20 ) ).toBe( 'example.com/lo...ath' ); + expect( trimURLForDisplay( 'https://www.example.com/long-url-path', 20 ) ).toContain( 'example.com' ); + } ); + it( 'should trim long URLs correctly', () => { + expect( trimURLForDisplay( 'https://www.example.com/it-a-very-long-url-path', 30 ) ).toBe( 'example.com/it-a-ve...url-path' ); + } ); + it( 'should return the full URL if it is shorter than maxLength', () => { + expect( trimURLForDisplay( 'https://example.com', 50 ) ).toBe( 'example.com' ); + } ); + + it( 'should handle edge cases gracefully', () => { + expect( trimURLForDisplay( 'https://a.com', 5 ) ).toBe( 'a.com' ); + expect( trimURLForDisplay( 'https://example.com', 0 ) ).toBe( 'example.com' ); + } ); +} ); diff --git a/wp-parsely.php b/wp-parsely.php index 649a9856c..1fd048c00 100644 --- a/wp-parsely.php +++ b/wp-parsely.php @@ -32,6 +32,7 @@ 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; @@ -72,6 +73,9 @@ const PARSELY_VERSION = '3.15.0'; const PARSELY_FILE = __FILE__; +require_once __DIR__ . '/src/Models/class-base-model.php'; +require_once __DIR__ . '/src/Models/class-smart-link.php'; + require_once __DIR__ . '/src/class-parsely.php'; require_once __DIR__ . '/src/class-scripts.php'; require_once __DIR__ . '/src/class-dashboard-link.php'; @@ -172,6 +176,7 @@ function parsely_wp_admin_early_register(): void { require_once __DIR__ . '/src/Endpoints/content-suggestions/class-suggest-linked-reference-api-proxy.php'; require_once __DIR__ . '/src/Endpoints/user-meta/class-dashboard-widget-settings-endpoint.php'; require_once __DIR__ . '/src/Endpoints/user-meta/class-editor-sidebar-settings-endpoint.php'; +require_once __DIR__ . '/src/Endpoints/content-helper/class-smart-linking-endpoint.php'; // RemoteAPI base classes. require_once __DIR__ . '/src/RemoteAPI/interface-cache.php'; @@ -207,6 +212,9 @@ function parsely_rest_api_init(): void { ( 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,