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

Yoast / wordpress-seo / 8f3e5a46c2569624b5ae510e261e6366a15e4633

06 Feb 2025 08:10AM UTC coverage: 28.755%. First build
8f3e5a46c2569624b5ae510e261e6366a15e4633

Pull #22020

github

web-flow
Merge 8ef1153c8 into aa075c54a
Pull Request #22020: Add data formatter

1870 of 7574 branches covered (24.69%)

Branch coverage included in aggregate %.

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

4118 of 13250 relevant lines covered (31.08%)

5.08 hits per line

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

0.0
/packages/js/src/general/initialize.js
1
import { SlotFillProvider } from "@wordpress/components";
2
import { select } from "@wordpress/data";
3
import domReady from "@wordpress/dom-ready";
4
import { render } from "@wordpress/element";
5
import { Root } from "@yoast/ui-library";
6
import { get } from "lodash";
7
import { createHashRouter, createRoutesFromElements, Navigate, Route, RouterProvider } from "react-router-dom";
8
import { Dashboard } from "../dashboard";
9
import { DataFormatter } from "../dashboard/services/data-formatter";
10
import { DataProvider } from "../dashboard/services/data-provider";
11
import { RemoteDataProvider } from "../dashboard/services/remote-data-provider";
12
import { WidgetFactory } from "../dashboard/services/widget-factory";
13
import { ADMIN_URL_NAME, LINK_PARAMS_NAME } from "../shared-admin/store";
14
import App from "./app";
15
import { RouteErrorFallback } from "./components";
16
import { ConnectedPremiumUpsellList } from "./components/connected-premium-upsell-list";
17
import { SidebarLayout } from "./components/sidebar-layout";
18
import { STORE_NAME } from "./constants";
19
import { AlertCenter, FirstTimeConfiguration, ROUTES } from "./routes";
20
import registerStore from "./store";
21
import { ADMIN_NOTICES_NAME } from "./store/admin-notices";
22
import { ALERT_CENTER_NAME } from "./store/alert-center";
23

24
/**
25
 * @type {import("../index").ContentType} ContentType
26
 * @type {import("../index").Features} Features
27
 * @type {import("../index").Links} Links
28
 * @type {import("../index").Endpoints} Endpoints
29
 */
30

31
domReady( () => {
×
32
        const root = document.getElementById( "yoast-seo-general" );
×
33
        if ( ! root ) {
×
34
                return;
×
35
        }
36
        registerStore( {
×
37
                initialState: {
38
                        [ ADMIN_URL_NAME ]: get( window, "wpseoScriptData.adminUrl", "" ),
39
                        [ LINK_PARAMS_NAME ]: get( window, "wpseoScriptData.linkParams", {} ),
40
                        [ ALERT_CENTER_NAME ]: { alerts: get( window, "wpseoScriptData.alerts", [] ) },
41
                        currentPromotions: { promotions: get( window, "wpseoScriptData.currentPromotions", [] ) },
42
                        dismissedAlerts: get( window, "wpseoScriptData.dismissedAlerts", {} ),
43
                        isPremium: get( window, "wpseoScriptData.preferences.isPremium", false ),
44
                        [ ADMIN_NOTICES_NAME ]: { resolvedNotices: [] },
45
                },
46
        } );
47
        const isRtl = select( STORE_NAME ).selectPreference( "isRtl", false );
×
48

49
        /** @type {ContentType[]} */
50
        const contentTypes = get( window, "wpseoScriptData.dashboard.contentTypes", [] );
×
51
        /** @type {string} */
52
        const userName = get( window, "wpseoScriptData.dashboard.displayName", "User" );
×
NEW
53
        const userLocale = document.getElementsByTagName( "html" )?.[ 0 ]?.getAttribute( "lang" ) || "en-US";
×
54
        /** @type {Features} */
55
        const features = {
×
56
                indexables: get( window, "wpseoScriptData.dashboard.indexablesEnabled", false ),
57
                seoAnalysis: get( window, "wpseoScriptData.dashboard.enabledAnalysisFeatures.keyphraseAnalysis", false ),
58
                readabilityAnalysis: get( window, "wpseoScriptData.dashboard.enabledAnalysisFeatures.readabilityAnalysis", false ),
59
        };
60

61
        /** @type {Endpoints} */
62
        const endpoints = {
×
63
                seoScores: get( window, "wpseoScriptData.dashboard.endpoints.seoScores", "" ),
64
                readabilityScores: get( window, "wpseoScriptData.dashboard.endpoints.readabilityScores", "" ),
65
                topPages: get( window, "wpseoScriptData.dashboard.endpoints.topPageResults", "" ),
66
        };
67
        /** @type {Object<string,string>} */
68
        const headers = {
×
69
                "X-Wp-Nonce": get( window, "wpseoScriptData.dashboard.nonce", "" ),
70
        };
71

72
        /** @type {Links} */
73
        const links = {
×
74
                dashboardLearnMore: select( STORE_NAME ).selectLink( "https://yoa.st/dashboard-learn-more" ),
75
                errorSupport: select( STORE_NAME ).selectAdminLink( "?page=wpseo_page_support" ),
76
        };
77

78
        const remoteDataProvider = new RemoteDataProvider( { headers } );
×
79
        const dataProvider = new DataProvider( { contentTypes, userName, features, endpoints, headers, links } );
×
NEW
80
        const dataFormatter = new DataFormatter( { locale: userLocale } );
×
NEW
81
        const widgetFactory = new WidgetFactory( dataProvider, remoteDataProvider, dataFormatter );
×
82

83
        const initialWidgets = [ "seoScores", "readabilityScores" ];
×
84
        // If site kit feature is enabled, active and connected: add the top pages widget.
85
        if (
×
86
                get( window, "wpseoScriptData.dashboard.siteKitConfiguration.feature_enabled", false ) &&
×
87
                get( window, "wpseoScriptData.dashboard.siteKitConfiguration.isActive", false ) &&
88
                // get( window, "wpseoScriptData.dashboard.siteKitConfiguration.isConnected", false )
89
                true
90
        ) {
91
                initialWidgets.push( "topPages" );
×
92
        }
93

94
        const router = createHashRouter(
×
95
                createRoutesFromElements(
96
                        <Route path="/" element={ <App /> } errorElement={ <RouteErrorFallback className="yst-m-8" /> }>
97
                                <Route
98
                                        path={ ROUTES.dashboard }
99
                                        element={
100
                                                <SidebarLayout>
101
                                                        <Dashboard
102
                                                                widgetFactory={ widgetFactory }
103
                                                                initialWidgets={ initialWidgets }
104
                                                                userName={ userName }
105
                                                                features={ features }
106
                                                                links={ links }
107
                                                        />
108
                                                        <ConnectedPremiumUpsellList />
109
                                                </SidebarLayout>
110
                                        }
111
                                        errorElement={ <RouteErrorFallback /> }
112
                                />
113
                                <Route
114
                                        path={ ROUTES.alertCenter }
115
                                        element={ <SidebarLayout><AlertCenter /><ConnectedPremiumUpsellList /></SidebarLayout> }
116
                                        errorElement={ <RouteErrorFallback /> }
117
                                />
118
                                <Route path={ ROUTES.firstTimeConfiguration } element={ <FirstTimeConfiguration /> } errorElement={ <RouteErrorFallback /> } />
119
                                {
120
                                        /**
121
                                         * Fallback route: redirect to the dashboard.
122
                                         * A redirect is used to support the activePath in the menu. E.g. `pathname` matches exactly.
123
                                         * It replaces the current path to not introduce invalid history in the browser (that would just redirect again).
124
                                         */
125
                                }
126
                                <Route path="*" element={ <Navigate to={ ROUTES.dashboard } replace={ true } /> } />
127
                        </Route>
128
                )
129
        );
130

131
        render(
×
132
                <Root context={ { isRtl } }>
133
                        <SlotFillProvider>
134
                                <RouterProvider router={ router } />
135
                        </SlotFillProvider>
136
                </Root>,
137
                root
138
        );
139
} );
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