Skip to content

Commit

Permalink
[FEATURE] Added Flesch reading score to Insights, updated Prominent w…
Browse files Browse the repository at this point in the history
…ords with default component from Yoast
  • Loading branch information
RinyVT committed Feb 3, 2025
1 parent fed07f1 commit 5bf4c74
Show file tree
Hide file tree
Showing 14 changed files with 273 additions and 38 deletions.
137 changes: 137 additions & 0 deletions Build/resources/javascript/Components/FleschReadingScore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, {useMemo} from 'react';
import {connect} from 'react-redux';
import LoadingIndicator from './LoadingIndicator';
import { InsightsCard } from '@yoast/components';
import { DIFFICULTY } from "yoastseo";
import { __ } from '@wordpress/i18n';

// See @wordpress-seo/packages/js/src/insights/src/components/flesch-reading-ease.js

/**
* Returns the difficulty feedback string (e.g. 'very easy')
*
* @param {DIFFICULTY} difficulty The Flesch reading ease difficulty.
*
* @returns {string} The difficulty feedback string.
*/
function getDifficultyFeedback( difficulty ) {
switch ( difficulty ) {
case DIFFICULTY.NO_DATA:
return __( "no data", "wordpress-seo" );
case DIFFICULTY.VERY_EASY:
return __( "very easy", "wordpress-seo" );
case DIFFICULTY.EASY:
return __( "easy", "wordpress-seo" );
case DIFFICULTY.FAIRLY_EASY:
return __( "fairly easy", "wordpress-seo" );
case DIFFICULTY.OKAY:
return __( "okay", "wordpress-seo" );
case DIFFICULTY.FAIRLY_DIFFICULT:
return __( "fairly difficult", "wordpress-seo" );
case DIFFICULTY.DIFFICULT:
return __( "difficult", "wordpress-seo" );
case DIFFICULTY.VERY_DIFFICULT:
return __( "very difficult", "wordpress-seo" );
}
}

/**
* Returns the call to action.
*
* @param {DIFFICULTY} difficulty The Flesch reading ease difficulty.
*
* @returns {string} The call to action.
*/
function getCallToAction( difficulty ) {
switch ( difficulty ) {
case DIFFICULTY.FAIRLY_DIFFICULT:
case DIFFICULTY.DIFFICULT:
case DIFFICULTY.VERY_DIFFICULT:
return __( "Try to make shorter sentences, using less difficult words to improve readability", "wordpress-seo" );
case DIFFICULTY.NO_DATA:
return __( "Continue writing to get insight into the readability of your text!", "wordpress-seo" );
default:
return __( "Good job!", "wordpress-seo" );
}
}

/**
* Generates the description given a score and difficulty.
*
* @param {number} score The flesch reading ease score.
* @param {DIFFICULTY} difficulty The flesch reading ease difficulty.
*
* @returns {string} The description.
*/
function getDescription( score, difficulty ) {
// A score of -1 signals that no valid FRE was calculated.
if ( score === -1 ) {
return sprintf(
__(
"Your text should be slightly longer to calculate your Flesch reading ease score.",
"wordpress-seo"
)
);
}
return sprintf(
__(
"The copy scores %1$s in the test, which is considered %2$s to read.",
"wordpress-seo"
),
score,
getDifficultyFeedback( difficulty )
);
}

/**
* Retrieves the description as a React element.
*
* @param {number} score The Flesch reading ease score.
* @param {DIFFICULTY} difficulty The difficulty.
* @param {string} link The link to the call to action.
*
* @returns {JSX.Element} The React element.
*/
function getDescriptionElement( score, difficulty, link ) {
const callToAction = getCallToAction( difficulty );
return <span>
{getDescription(score, difficulty)}
&nbsp;
{difficulty >= DIFFICULTY.FAIRLY_DIFFICULT
? <a href={link} target="_blank" rel="noopener noreferrer">{callToAction + "."}</a>
: callToAction
}
</span>;
}

const FleschReadingScore = ({flesch}) => {
if (flesch) {
let score = flesch.result.score;

const description = useMemo(() => {
return getDescriptionElement(score, flesch.result.difficulty, 'https://yoa.st/34s');
})

if ( score === -1 ) {
score = "?";
}

return <InsightsCard
amount={ score }
unit={ __( "out of 100", "wordpress-seo" ) }
title={ __( "Flesch reading ease", "wordpress-seo" ) }
linkTo={ 'https://yoa.st/34r' }
linkText={ __( "Learn more about Flesch reading ease", "wordpress-seo" ) }
description={ description }
/>
}
return <LoadingIndicator />
}

const mapStateToProps = (state) => {
return {
...state.flesch
}
}

export default connect(mapStateToProps)(FleschReadingScore);
14 changes: 2 additions & 12 deletions Build/resources/javascript/Components/Insights.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
import React from 'react';
import {connect} from 'react-redux';
import LoadingIndicator from './LoadingIndicator';
import { WordOccurrenceInsights } from '@yoast/components';

const Insights = ({insights}) => {
if (insights) {
let keywords = insights.result.slice(0, 20);
return (
<ol className="yoast-keyword-suggestions__list">
{keywords.map((word) => {
return (
<li key={word.getStem()}
className="yoast-keyword-suggestions__item">
<strong>{word.getStem()}</strong> ({word.getOccurrences()})
</li>
);
})}
</ol>
);
return <WordOccurrenceInsights words={keywords} researchArticleLink={'https://yoa.st/keyword-research-metabox'} />
}
return <LoadingIndicator />
}
Expand Down
4 changes: 3 additions & 1 deletion Build/resources/javascript/analysis/refreshAnalysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import measureTextWidth from '../helpers/measureTextWidth';
import {analyzeData} from '../redux/actions/analysis';
import {getRelevantWords} from '../redux/actions/relevantWords';
import {getInsights} from "../redux/actions/insights";
import {getFleschReadingScore} from "../redux/actions/flesch";

export default function refreshAnalysis(worker, store) {
const state = store.getState();
Expand All @@ -20,6 +21,7 @@ export default function refreshAnalysis(worker, store) {
return Promise.all([
store.dispatch(analyzeData(worker, paper, YoastConfig.relatedKeyphrases)),
store.dispatch(getRelevantWords(worker, paper)),
store.dispatch(getInsights(worker, paper))
store.dispatch(getInsights(worker, paper)),
store.dispatch(getFleschReadingScore(worker, paper)),
]);
}
6 changes: 6 additions & 0 deletions Build/resources/javascript/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import TitleProgressBar from './Components/TitleProgressBar';
import DescriptionProgressBar from './Components/DescriptionProgressBar';
import LinkingSuggestions from "./Components/LinkingSuggestions";
import Insights from "./Components/Insights";
import FleschReadingScore from "./Components/FleschReadingScore";
import store from './redux/store';
import {getContent, updateContent} from './redux/actions/content';
import {setFocusKeyword} from './redux/actions/focusKeyword';
Expand Down Expand Up @@ -222,6 +223,11 @@ let YoastPlugin = {
const insightsRoot = createRoot(container);
insightsRoot.render(<Provider store={store}><Insights /></Provider>);
});

document.querySelectorAll('[data-yoast-flesch]').forEach(container => {
const fleschRoot = createRoot(container);
fleschRoot.render(<Provider store={store}><FleschReadingScore /></Provider>);
});
},

initCornerstone: () => {
Expand Down
17 changes: 17 additions & 0 deletions Build/resources/javascript/redux/actions/flesch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const GET_FLESCH_REQUEST = 'GET_FLESCH_REQUEST';
export const GET_FLESCH_SUCCESS = 'GET_FLESCH_SUCCESS';

export function getFleschReadingScore(worker, paper) {
return dispatch => {
dispatch({type: GET_FLESCH_REQUEST});

return worker
.runResearch('getFleschReadingScore', paper)
.then((results) => {
dispatch({type: GET_FLESCH_SUCCESS, payload: results});
}).catch((error) => {
console.error('An error occured while analyzing the text:');
console.error(error);
});
};
}
2 changes: 2 additions & 0 deletions Build/resources/javascript/redux/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {setFocusKeywordSynonyms} from './focusKeywordSynonyms';
import {analyzeData} from "./analysis";
import {getRelevantWords} from "./relevantWords";
import {getInsights} from "./insights";
import {getFleschReadingScore} from "./flesch";
import {getLinkingSuggestions} from "./linkingSuggestions";

export default {
Expand All @@ -13,5 +14,6 @@ export default {
analyzeData,
getRelevantWords,
getInsights,
getFleschReadingScore,
getLinkingSuggestions
};
19 changes: 19 additions & 0 deletions Build/resources/javascript/redux/reducers/flesch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {GET_FLESCH_REQUEST, GET_FLESCH_SUCCESS} from '../actions/flesch';

const initialState = {
isCheckingFlesch: false,
words: []
};

function fleschReducer (state = initialState, action) {
switch(action.type) {
case GET_FLESCH_REQUEST:
return {...state, isCheckingFlesch: true};
case GET_FLESCH_SUCCESS:
return {...state, isCheckingFlesch: false, flesch: action.payload};
default:
return state;
}
}

export default fleschReducer;
2 changes: 2 additions & 0 deletions Build/resources/javascript/redux/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import focusKeywordSynonyms from './focusKeywordSynonyms';
import analysis from './analysis';
import relevantWords from './relevantWords';
import insights from "./insights";
import flesch from "./flesch";
import linkingSuggestions from "./linkingSuggestions";
export default {
content,
Expand All @@ -12,5 +13,6 @@ export default {
analysis,
relevantWords,
insights,
flesch,
linkingSuggestions
}
85 changes: 80 additions & 5 deletions Build/resources/sass/yoast.scss
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,90 @@ div.yoast-analysis {
}

.yoastSeo-insights {
ol {
padding: 0;
margin: 1em 2em;
}

a {
font-weight: bold;
}
a:hover {
text-decoration: underline;
}

.yoast-field-group__title {
font-weight: 600;
}

.yoast-help {
margin-left: 5px;

&__icon svg {
fill: #707070;
height: 12px;
transition: all 150ms ease-out;
width: 12px;
}

&:focus svg, &:hover svg {
fill: #000;
}
}

.screen-reader-text {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}

.yoast-data-model {
width: 300px;
padding: 3px 0 0 0;
list-style: none;
}

.yoast-data-model li {
line-height: 1.8;
padding: 0 8px;
position: relative;
z-index: 2;
font-weight: 600;
}

.yoast-data-model span {
float: right;
font-weight: 400;
}

.yoast-data-model li + li {
margin-top: 9px;
}

.yoast-data-model li:after {
position: absolute;
left: 0;
height: 20px;
background: var(--typo3-surface-container-info, #d5eef6);
content: "";
width: var(--yoast-width);
z-index: -1;
}

.yoast-insights-card {
&__content {
padding-top: 5px;
display: flex;
}
&__score {
flex-shrink: 0;
margin-right: 2em;
}
&__amount {
display: block;
font-size: 3.5em;
line-height: 1;
}
&__description {
max-width: 600px;
}
}
}
1 change: 0 additions & 1 deletion Classes/Service/TcaService.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ protected function addDefaultFields(): void
],
],
'tx_yoastseo_insights' => [
'label' => self::LL_PREFIX_TCA . 'pages.fields.tx_yoastseo_insights',
'exclude' => true,
'config' => [
'type' => 'none',
Expand Down
9 changes: 0 additions & 9 deletions Resources/Private/Language/TCA.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,6 @@
<trans-unit id="pages.fields.tx_yoastseo_focuskeyword_related" resname="pages.fields.tx_yoastseo_focuskeyword_related">
<source>Focus keywords</source>
</trans-unit>
<trans-unit id="pages.fields.tx_yoastseo_insights" resname="pages.fields.tx_yoastseo_insights">
<source>Prominent words</source>
</trans-unit>
<trans-unit id="pages.fields.tx_yoastseo_insights.intro" resname="pages.fields.tx_yoastseo_insights.intro">
<source>The following words occur the most in the content. These give an indication of what your content focuses on. If the words differ a lot from your topic, you might want to rewrite your content accordingly.</source>
</trans-unit>
<trans-unit id="pages.fields.tx_yoastseo_insights.more_information" resname="pages.fields.tx_yoastseo_insights.more_information">
<source><![CDATA[Read our <a href="%s" target="_blank">ultimate guide to keyword research</a> to learn more about keyword research and keyword strategy.]]></source>
</trans-unit>
<trans-unit id="pages.palettes.robots" resname="pages.palettes.robots">
<source>Advanced robot instructions</source>
</trans-unit>
Expand Down
Loading

0 comments on commit 5bf4c74

Please sign in to comment.