• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / b6d356674efe8af996c7529da12e66aad26e2cc0

08 Apr 2025 06:29AM UTC coverage: 57.651%. First build
b6d356674efe8af996c7529da12e66aad26e2cc0

Pull #22118

github

web-flow
Merge 371ea2ac2 into 1f39fa1ec
Pull Request #22118: Enable AI optimize in Classic editor

7801 of 13847 branches covered (56.34%)

Branch coverage included in aggregate %.

29 of 33 new or added lines in 5 files covered. (87.88%)

13486 of 23077 relevant lines covered (58.44%)

103287.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/js/src/components/contentAnalysis/ReadabilityAnalysis.js
1
/* global wpseoAdminL10n */
2
/* External components */
3
import { Component, Fragment } from "@wordpress/element";
4
import { withSelect } from "@wordpress/data";
5
import PropTypes from "prop-types";
6
import styled from "styled-components";
7
import { __, sprintf } from "@wordpress/i18n";
8
import { isNil } from "lodash";
9

10
/* Internal components */
11
import ScoreIconPortal from "../portals/ScoreIconPortal";
12
import Results from "../../containers/Results";
13
import Collapsible from "../SidebarCollapsible";
14
import getIndicatorForScore from "../../analysis/getIndicatorForScore";
15
import { getIconForScore } from "./mapResults";
16
import { LocationConsumer, RootContext } from "@yoast/externals/contexts";
17
import HelpLink from "../HelpLink";
18
import ReadabilityResultsPortal from "../portals/ReadabilityResultsPortal";
19
import { isWordComplexitySupported } from "../../helpers/assessmentUpsellHelpers";
20
import { addQueryArgs } from "@wordpress/url";
21
import getL10nObject from "../../analysis/getL10nObject";
22
import AIOptimizeButton from "../../ai-optimizer/components/ai-optimize-button";
23

24
const AnalysisHeader = styled.span`
×
25
        font-size: 1em;
26
        font-weight: bold;
27
        margin: 0 0 8px;
28
        display: block;
29
`;
30

31
const ReadabilityResultsTabContainer = styled.div`
×
32
        padding: 16px;
33
`;
34

35
const StyledHelpLink = styled( HelpLink )`
×
36
        margin: -8px 0 -4px 4px;
37
`;
38

39
/**
40
 * Redux container for the readability analysis.
41
 */
42
class ReadabilityAnalysis extends Component {
43
        /**
44
         * Renders the Readability Analysis results.
45
         *
46
         * @param {Array} upsellResults The array of upsell results.
47
         *
48
         * @returns {wp.Element} The Readability Analysis results.
49
         */
50
        renderResults( upsellResults ) {
51
                const highlightingUpsellLink = "shortlinks.upsell.sidebar.highlighting_readability_analysis";
×
52

53
                return (
×
54
                        <Fragment>
55
                                <AnalysisHeader>
56
                                        { __( "Analysis results", "wordpress-seo" ) }
57
                                        <StyledHelpLink
58
                                                href={ wpseoAdminL10n[ "shortlinks.readability_analysis_info" ] }
59
                                                className="dashicons"
60
                                        >
61
                                                <span className="screen-reader-text">
62
                                                        {
63
                                                                /* translators: Hidden accessibility text. */
64
                                                                __( "Learn more about the readability analysis", "wordpress-seo" )
65
                                                        }
66
                                                </span>
67
                                        </StyledHelpLink>
68
                                </AnalysisHeader>
69
                                <Results
70
                                        results={ this.props.results }
71
                                        upsellResults={ upsellResults }
72
                                        marksButtonClassName="yoast-tooltip yoast-tooltip-w"
73
                                        marksButtonStatus={ this.props.marksButtonStatus }
74
                                        highlightingUpsellLink={ highlightingUpsellLink }
75
                                        shouldUpsellHighlighting={ this.props.shouldUpsellHighlighting }
76
                                        renderAIOptimizeButton={ this.renderAIOptimizeButton }
77
                                />
78
                        </Fragment>
79
                );
80
        }
81

82
        /**
83
         * Returns the list of results used to upsell the user to Premium.
84
         *
85
         * @param {string} location                 Where this component is rendered (metabox or sidebar).
86
         * @param {string} locationContext         In which editor this component is rendered.
87
         *
88
         * @returns {Array} The upsell results.
89
         */
90
        getUpsellResults( location, locationContext ) {
91
                let link = wpseoAdminL10n[ "shortlinks.upsell.metabox.word_complexity" ];
×
92
                if ( location === "sidebar" ) {
×
93
                        link = wpseoAdminL10n[ "shortlinks.upsell.sidebar.word_complexity" ];
×
94
                }
95

96
                link = addQueryArgs( link, { context: locationContext } );
×
97

98
                /*
99
                 * We don't show the upsell for Word complexity assessment if it's not supported for the current locale.
100
                 */
101
                if ( ! isWordComplexitySupported() ) {
×
102
                        return [];
×
103
                }
104

105
                const wordComplexityUpsellText = sprintf(
×
106
                        /* Translators: %1$s is a span tag that adds styling to 'Word complexity', %2$s is a closing span tag.
107
                           %3$s is an anchor tag with a link to yoast.com, %4$s is a closing anchor tag.*/
108
                        __(
109
                                "%1$sWord complexity%2$s: Is your vocabulary suited for a larger audience? %3$sYoast SEO Premium will tell you!%4$s",
110
                                "wordpress-seo"
111
                        ),
112
                        "<span style='text-decoration: underline'>",
113
                        "</span>",
114
                        `<a href="${ link }" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" target="_blank">`,
115
                        "</a>"
116
                );
117

118
                return [
×
119
                        {
120
                                score: 0,
121
                                rating: "upsell",
122
                                hasMarks: false,
123
                                id: "wordComplexity",
124
                                text: wordComplexityUpsellText,
125
                                markerId: "wordComplexity",
126
                        },
127
                ];
128
        }
129

130

131
        /**
132
         * Renders the Yoast AI Optimize button.
133
         * The button is shown when:
134
         * - The assessment can be fixed through Yoast AI Optimize.
135
         * - The AI feature is enabled (for Yoast SEO Premium users; for Free users, the button is shown with an upsell).
136
         * - We are in the block editor.
137
         * - We are not in the Elementor editor, nor in the Elementor in-between screen.
138
         *
139
         * @param {boolean} hasAIFixes Whether the assessment can be fixed through Yoast AI Optimize.
140
         * @param {string} id The assessment ID.
141
         *
142
         * @returns {void|JSX.Element} The AI Optimize button, or nothing if the button should not be shown.
143
         */
NEW
144
        renderAIOptimizeButton = ( hasAIFixes, id ) => {
×
145
                const { isElementor, isAiFeatureEnabled } = this.props;
×
146
                const isPremium = getL10nObject().isPremium;
×
147

148
                // Don't show the button if the AI feature is not enabled for Yoast SEO Premium users.
149
                if ( isPremium && ! isAiFeatureEnabled ) {
×
150
                        return;
×
151
                }
152

153
                const isElementorEditorPageActive =  document.body.classList.contains( "elementor-editor-active" );
×
154
                // Check if the current editor is either Elementor or the Elementor in-between screen. In that case, don't show the button.
155
                const isNotElementorPage =  ! isElementor && ! isElementorEditorPageActive;
×
156

157
                // Show the button if the assessment can be fixed through Yoast AI Optimize, and we are not in the Elementor editor.
NEW
158
                return hasAIFixes && isNotElementorPage && (
×
159
                        <AIOptimizeButton id={ id } isPremium={ isPremium } />
160
                );
161
        };
162

163

164
        /**
165
         * Renders the Readability Analysis component.
166
         *
167
         * @returns {wp.Element} The Readability Analysis component.
168
         */
169
        render() {
170
                const score = getIndicatorForScore( this.props.overallScore );
×
171

172
                if ( isNil( this.props.overallScore ) ) {
×
173
                        score.className = "loading";
×
174
                }
175

176
                return (
×
177
                        <LocationConsumer>
178
                                { location => {
179
                                        return (
×
180
                                                <RootContext.Consumer>
181
                                                        { ( { locationContext } ) => {
182
                                                                let upsellResults = [];
×
183
                                                                if ( this.props.shouldUpsell ) {
×
184
                                                                        upsellResults = this.getUpsellResults( location, locationContext );
×
185
                                                                }
186
                                                                if ( location === "sidebar" ) {
×
187
                                                                        return (
×
188
                                                                                <Collapsible
189
                                                                                        title={ __( "Readability analysis", "wordpress-seo" ) }
190
                                                                                        titleScreenReaderText={ score.screenReaderReadabilityText }
191
                                                                                        prefixIcon={ getIconForScore( score.className ) }
192
                                                                                        prefixIconCollapsed={ getIconForScore( score.className ) }
193
                                                                                        id={ `yoast-readability-analysis-collapsible-${ location }` }
194
                                                                                >
195
                                                                                        { this.renderResults( upsellResults ) }
196
                                                                                </Collapsible>
197
                                                                        );
198
                                                                }
199

200
                                                                if ( location === "metabox" ) {
×
201
                                                                        return (
×
202
                                                                                <ReadabilityResultsPortal target="wpseo-metabox-readability-root">
203
                                                                                        <ReadabilityResultsTabContainer>
204
                                                                                                <ScoreIconPortal
205
                                                                                                        target="wpseo-readability-score-icon"
206
                                                                                                        scoreIndicator={ score.className }
207
                                                                                                />
208
                                                                                                { this.renderResults( upsellResults ) }
209
                                                                                        </ReadabilityResultsTabContainer>
210
                                                                                </ReadabilityResultsPortal>
211
                                                                        );
212
                                                                }
213
                                                        } }
214
                                                </RootContext.Consumer>
215
                                        );
216
                                } }
217
                        </LocationConsumer>
218
                );
219
        }
220
}
221

222
ReadabilityAnalysis.propTypes = {
×
223
        results: PropTypes.array.isRequired,
224
        marksButtonStatus: PropTypes.string.isRequired,
225
        overallScore: PropTypes.number,
226
        shouldUpsell: PropTypes.bool,
227
        shouldUpsellHighlighting: PropTypes.bool,
228
        isAiFeatureEnabled: PropTypes.bool,
229
        isElementor: PropTypes.bool,
230
};
231

232
ReadabilityAnalysis.defaultProps = {
×
233
        overallScore: null,
234
        shouldUpsell: false,
235
        shouldUpsellHighlighting: false,
236
        isAiFeatureEnabled: false,
237
        isElementor: false,
238
};
239

240
export default withSelect( select => {
241
        const {
242
                getReadabilityResults,
243
                getMarkButtonStatus,
244
                getIsElementorEditor,
245
                getIsAiFeatureEnabled,
246
        } = select( "yoast-seo/editor" );
×
247

248
        return {
×
249
                ...getReadabilityResults(),
250
                marksButtonStatus: getMarkButtonStatus(),
251
                isElementor: getIsElementorEditor(),
252
                isAiFeatureEnabled: getIsAiFeatureEnabled(),
253
        };
254
} )( ReadabilityAnalysis );
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc