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

Yoast / wordpress-seo / a3ce2577a13a8e5e3f011dd2808fbf67906e5f15

02 Jul 2024 07:50AM UTC coverage: 54.108% (+0.5%) from 53.658%
a3ce2577a13a8e5e3f011dd2808fbf67906e5f15

push

github

YoastBot
Bump version to 23.0 on free

7399 of 13400 branches covered (55.22%)

Branch coverage included in aggregate %.

28477 of 52904 relevant lines covered (53.83%)

63690.15 hits per line

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

0.0
/packages/js/src/components/AdvancedSettings.js
1
/* global wpseoAdminL10n */
2
import { Fragment, useEffect } from "@wordpress/element";
3
import { __, sprintf } from "@wordpress/i18n";
4
import { Alert, MultiSelect, RadioButtonGroup, Select, TextInput } from "@yoast/components";
5
import { join } from "@yoast/helpers";
6
import PropTypes from "prop-types";
7
import { LocationConsumer } from "@yoast/externals/contexts";
8

9
/**
10
 * Boolean that tells whether the current object refers to a post or a taxonomy.
11
 *
12
 * @returns {Boolean} Whether this is a post or not.
13
 */
14
const isPost = () => !! window.wpseoScriptData.isPost;
×
15

16
/**
17
 * The values that are used for the noIndex field differ for posts and taxonomies. This function returns an array of
18
 * options that can be used to populate a select field.
19
 *
20
 * @param {Object} editorContext An object containing context about this editor.
21
 *
22
 * @returns {Object[]} Returns an array of options for the noIndex setting.
23
 */
24
const getNoIndexOptions = ( editorContext ) => {
×
25
        const translatedNo = __( "No", "wordpress-seo" );
×
26
        const translatedYes = __( "Yes", "wordpress-seo" );
×
27
        const noIndex = editorContext.noIndex ? translatedNo : translatedYes;
×
28

29
        if ( isPost() ) {
×
30
                return [
×
31
                        {
32
                                name: sprintf(
33
                                        /* translators: the first %s translates to "yes" or "no", the second %s translates to the content type label in plural form */
34
                                        __( "%s (current default for %s)", "wordpress-seo" ),
35
                                        noIndex,
36
                                        editorContext.postTypeNamePlural
37
                                ),
38
                                value: "0",
39
                        },
40
                        { name: translatedNo, value: "1" },
41
                        { name: translatedYes, value: "2" },
42
                ];
43
        }
44
        return [
×
45
                {
46
                        name: sprintf(
47
                                /* translators: the first %s translates to "yes" or "no", the second %s translates to the content type label in plural form */
48
                                __( "%s (current default for %s)", "wordpress-seo" ),
49
                                noIndex,
50
                                editorContext.postTypeNamePlural
51
                        ),
52
                        value: "default",
53
                },
54
                { name: translatedYes, value: "index" },
55
                { name: translatedNo, value: "noindex" },
56
        ];
57
};
58

59
/**
60
 * Functional component for the Meta Robots No-Index option.
61
 *
62
 * @param {Object} props The props object
63
 *
64
 * @returns {JSX.Element} The Meta Robots No-Index.
65
 */
66
const MetaRobotsNoIndex = ( { noIndex, onNoIndexChange, editorContext, isPrivateBlog } ) => {
×
67
        const metaRobotsNoIndexOptions = getNoIndexOptions( editorContext );
×
68

69
        return <LocationConsumer>
×
70
                { location => {
71
                        return <Fragment>
×
72
                                {
73
                                        isPrivateBlog &&
×
74
                                        <Alert type="warning">
75
                                                { __(
76
                                                        // eslint-disable-next-line max-len
77
                                                        "Even though you can set the meta robots setting here, the entire site is set to noindex in the sitewide privacy settings, so these settings won't have an effect.",
78
                                                        "wordpress-seo"
79
                                                ) }
80
                                        </Alert>
81
                                }
82
                                <Select
83
                                        label={ __( "Allow search engines to show this content in search results?", "wordpress-seo" ) }
84
                                        onChange={ onNoIndexChange }
85
                                        id={ join( [ "yoast-meta-robots-noindex", location ] ) }
86
                                        options={ metaRobotsNoIndexOptions }
87
                                        selected={ noIndex }
88
                                        linkTo={ wpseoAdminL10n[ "shortlinks.advanced.allow_search_engines" ] }
89
                                        /* translators: Hidden accessibility text. */
90
                                        linkText={ __( "Learn more about the no-index setting on our help page.", "wordpress-seo" ) }
91
                                />
92
                        </Fragment>;
93
                } }
94
        </LocationConsumer>;
95
};
96

97
MetaRobotsNoIndex.propTypes = {
×
98
        noIndex: PropTypes.string.isRequired,
99
        onNoIndexChange: PropTypes.func.isRequired,
100
        editorContext: PropTypes.object.isRequired,
101
        isPrivateBlog: PropTypes.bool,
102
};
103

104
MetaRobotsNoIndex.defaultProps = {
×
105
        isPrivateBlog: false,
106
};
107

108
/**
109
 * Functional component for the Meta Robots No-Follow option.
110
 *
111
 * @returns {JSX.Element} The Meta Robots No-Follow option.
112
 */
113
const MetaRobotsNoFollow = ( { noFollow, onNoFollowChange } ) => {
×
114
        return <LocationConsumer>
×
115
                { location => {
116
                        const id = join( [ "yoast-meta-robots-nofollow", location ] );
×
117

118
                        return <RadioButtonGroup
×
119
                                id={ id }
120
                                options={ [ { value: "0", label: "Yes" }, { value: "1", label: "No" } ] }
121
                                label={ __( "Should search engines follow links on this content?", "wordpress-seo" ) }
122
                                groupName={ id }
123
                                onChange={ onNoFollowChange }
124
                                selected={ noFollow }
125
                                linkTo={ wpseoAdminL10n[ "shortlinks.advanced.follow_links" ] }
126
                                /* translators: Hidden accessibility text. */
127
                                linkText={ __( "Learn more about the no-follow setting on our help page.", "wordpress-seo" ) }
128
                        />;
129
                } }
130
        </LocationConsumer>;
131
};
132

133
MetaRobotsNoFollow.propTypes = {
×
134
        noFollow: PropTypes.string.isRequired,
135
        onNoFollowChange: PropTypes.func.isRequired,
136
};
137

138
/**
139
 * Functional component for the Meta Robots Advanced field.
140
 *
141
 * @param {Object} props The props object
142
 *
143
 * @returns {JSX.Element} The Meta Robots advanced field.
144
 */
145
const MetaRobotsAdvanced = ( { advanced, onAdvancedChange } ) => {
×
146
        return <LocationConsumer>
×
147
                { location => {
148
                        const id = join( [ "yoast-meta-robots-advanced", location ] );
×
149
                        const inputId = `${ id }-input`;
×
150

151
                        return <MultiSelect
×
152
                                label={ __( "Meta robots advanced", "wordpress-seo" ) }
153
                                onChange={ onAdvancedChange }
154
                                id={ id }
155
                                inputId={ inputId }
156
                                options={ [
157
                                        { name: __( "No Image Index", "wordpress-seo" ), value: "noimageindex" },
158
                                        { name: __( "No Archive", "wordpress-seo" ), value: "noarchive" },
159
                                        { name: __( "No Snippet", "wordpress-seo" ), value: "nosnippet" },
160
                                ] }
161
                                selected={ advanced }
162
                                linkTo={ wpseoAdminL10n[ "shortlinks.advanced.meta_robots" ] }
163
                                /* translators: Hidden accessibility text. */
164
                                linkText={ __( "Learn more about advanced meta robots settings on our help page.", "wordpress-seo" ) }
165
                        />;
166
                } }
167
        </LocationConsumer>;
168
};
169

170
MetaRobotsAdvanced.propTypes = {
×
171
        advanced: PropTypes.array.isRequired,
172
        onAdvancedChange: PropTypes.func.isRequired,
173
};
174

175
/**
176
 * Functional component for the Breadcrumbs Title.
177
 *
178
 * @param {Object} props The props object
179
 *
180
 * @returns {JSX.Element} The Breadcrumbs title.
181
 */
182
const BreadcrumbsTitle = ( { breadcrumbsTitle, onBreadcrumbsTitleChange } ) => {
×
183
        return <LocationConsumer>
×
184
                {
185
                        location => {
186
                                return <TextInput
×
187
                                        label={ __( "Breadcrumbs Title", "wordpress-seo" ) }
188
                                        id={ join( [ "yoast-breadcrumbs-title", location ] ) }
189
                                        onChange={ onBreadcrumbsTitleChange }
190
                                        value={ breadcrumbsTitle }
191
                                        linkTo={ wpseoAdminL10n[ "shortlinks.advanced.breadcrumbs_title" ] }
192
                                        /* translators: Hidden accessibility text. */
193
                                        linkText={ __( "Learn more about the breadcrumbs title setting on our help page.", "wordpress-seo" ) }
194
                                />;
195
                        }
196
                }
197
        </LocationConsumer>;
198
};
199

200
BreadcrumbsTitle.propTypes = {
×
201
        breadcrumbsTitle: PropTypes.string.isRequired,
202
        onBreadcrumbsTitleChange: PropTypes.func.isRequired,
203
};
204

205
/**
206
 * Functional component for the Canonical URL.
207
 *
208
 * @param {Object} props The props object
209
 *
210
 * @returns {JSX.Element} The canonical URL.
211
 */
212
const CanonicalURL = ( { canonical, onCanonicalChange } ) => {
×
213
        return <LocationConsumer>
×
214
                {
215
                        location => {
216
                                return <TextInput
×
217
                                        label={ __( "Canonical URL", "wordpress-seo" ) }
218
                                        id={ join( [ "yoast-canonical", location ] ) }
219
                                        onChange={ onCanonicalChange }
220
                                        value={ canonical }
221
                                        linkTo={ "https://yoa.st/canonical-url" }
222
                                        /* translators: Hidden accessibility text. */
223
                                        linkText={ __( "Learn more about canonical URLs on our help page.", "wordpress-seo" ) }
224
                                />;
225
                        }
226
                }
227
        </LocationConsumer>;
228
};
229

230
CanonicalURL.propTypes = {
×
231
        canonical: PropTypes.string.isRequired,
232
        onCanonicalChange: PropTypes.func.isRequired,
233
};
234

235
/**
236
 * The Advanced Settings component.
237
 *
238
 * @param {Object} props The props object
239
 *
240
 * @returns {wp.Element} The AdvancedSettings component.
241
 */
242
const AdvancedSettings = ( props ) => {
×
243
        const {
244
                noIndex,
245
                noFollow,
246
                advanced,
247
                breadcrumbsTitle,
248
                canonical,
249
                onNoIndexChange,
250
                onNoFollowChange,
251
                onAdvancedChange,
252
                onBreadcrumbsTitleChange,
253
                onCanonicalChange,
254
                onLoad,
255
                isLoading,
256
                editorContext,
257
                isBreadcrumbsDisabled,
258
                isPrivateBlog,
259
        } = props;
×
260

261
        useEffect( () => {
×
262
                setTimeout( () => {
×
263
                        if ( isLoading ) {
×
264
                                onLoad();
×
265
                        }
266
                } );
267
        } );
268

269
        const noIndexProps = {
×
270
                noIndex,
271
                onNoIndexChange,
272
                editorContext,
273
                isPrivateBlog,
274
        };
275

276
        const noFollowProps = {
×
277
                noFollow,
278
                onNoFollowChange,
279
        };
280

281
        const advancedProps = {
×
282
                advanced,
283
                onAdvancedChange,
284
        };
285
        const breadcrumbsTitleProps = {
×
286
                breadcrumbsTitle,
287
                onBreadcrumbsTitleChange,
288
        };
289

290
        const canonicalProps = {
×
291
                canonical,
292
                onCanonicalChange,
293
        };
294

295
        if ( isLoading ) {
×
296
                return null;
×
297
        }
298

299
        return (
×
300
                <Fragment>
301
                        <MetaRobotsNoIndex { ...noIndexProps } />
302
                        { editorContext.isPost && <MetaRobotsNoFollow { ...noFollowProps } /> }
×
303
                        { editorContext.isPost && <MetaRobotsAdvanced { ...advancedProps } /> }
×
304
                        {
305
                                ! isBreadcrumbsDisabled && <BreadcrumbsTitle { ...breadcrumbsTitleProps } />
×
306
                        }
307
                        <CanonicalURL { ...canonicalProps } />
308
                </Fragment>
309
        );
310
};
311

312
AdvancedSettings.propTypes = {
×
313
        noIndex: PropTypes.string.isRequired,
314
        canonical: PropTypes.string.isRequired,
315
        onNoIndexChange: PropTypes.func.isRequired,
316
        onCanonicalChange: PropTypes.func.isRequired,
317
        onLoad: PropTypes.func.isRequired,
318
        isLoading: PropTypes.bool.isRequired,
319
        editorContext: PropTypes.object.isRequired,
320
        isBreadcrumbsDisabled: PropTypes.bool.isRequired,
321
        isPrivateBlog: PropTypes.bool,
322
        advanced: PropTypes.array,
323
        onAdvancedChange: PropTypes.func,
324
        noFollow: PropTypes.string,
325
        onNoFollowChange: PropTypes.func,
326
        breadcrumbsTitle: PropTypes.string,
327
        onBreadcrumbsTitleChange: PropTypes.func,
328
};
329

330
AdvancedSettings.defaultProps = {
×
331
        advanced: [],
332
        onAdvancedChange: () => {},
333
        noFollow: "",
334
        onNoFollowChange: () => {},
335
        breadcrumbsTitle: "",
336
        onBreadcrumbsTitleChange: () => {},
337
        isPrivateBlog: false,
338
};
339

340
export default AdvancedSettings;
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