UNPKG

yoastseo-dep

Version:

Yoast clientside page analysis

234 lines (210 loc) 8.23 kB
import { __, _n, sprintf } from "@wordpress/i18n"; import { inRange, merge } from "lodash-es"; import Assessment from "../assessment"; import { createAnchorOpeningTag } from "../../../helpers/shortlinker"; import AssessmentResult from "../../../values/AssessmentResult"; /** * Assessment that will test if the text is long enough. */ export default class TextLengthAssessment extends Assessment { /** * Sets the identifier and the config. * * @param {Object} [config] The configuration to use. * * @returns {void} */ constructor( config = {} ) { super(); const defaultConfig = { recommendedMinimum: 300, slightlyBelowMinimum: 250, belowMinimum: 200, veryFarBelowMinimum: 100, scores: { recommendedMinimum: 9, slightlyBelowMinimum: 6, belowMinimum: 3, farBelowMinimum: -10, veryFarBelowMinimum: -20, }, countTextIn: { singular: __( "word", "wordpress-seo" ), plural: __( "words", "wordpress-seo" ), }, urlTitle: createAnchorOpeningTag( "https://yoa.st/34n" ), urlCallToAction: createAnchorOpeningTag( "https://yoa.st/34o" ), cornerstoneContent: false, customContentType: "", }; this.identifier = "textLength"; this._config = merge( defaultConfig, config ); } /** * Execute the Assessment and return a result. * * @param {Paper} paper The Paper object to assess. * @param {Researcher} researcher The Researcher object containing all available researches. * * @returns {AssessmentResult} The result of the assessment, containing both a score and a descriptive text. */ getResult( paper, researcher ) { const wordCount = researcher.getResearch( "wordCountInText" ); if ( researcher.getConfig( "textLength" ) ) { this._config = this.getLanguageSpecificConfig( researcher ); } const countTextInCharacters = researcher.getConfig( "countCharacters" ); if ( countTextInCharacters ) { this._config.countTextIn.singular = __( "character", "wordpress-seo" ); this._config.countTextIn.plural = __( "characters", "wordpress-seo" ); } const calculatedResult = this.calculateResult( wordCount.count ); const assessmentResult = new AssessmentResult(); assessmentResult.setScore( calculatedResult.score ); assessmentResult.setText( calculatedResult.resultText ); return assessmentResult; } /** * Check if there is language-specific config, and if so, overwrite the current config with it. * * @param {Researcher} researcher The researcher to use. * * @returns {Object} The config that should be used. */ getLanguageSpecificConfig( researcher ) { const currentConfig = this._config; const languageSpecificConfig = researcher.getConfig( "textLength" ); // Check if a language has configuration for custom content types. if ( languageSpecificConfig.hasOwnProperty( currentConfig.customContentType ) ) { return merge( currentConfig, languageSpecificConfig[ currentConfig.customContentType ] ); } // Check if a language has a default cornerstone configuration. if ( currentConfig.cornerstoneContent === true && currentConfig.customContentType === "" && languageSpecificConfig.hasOwnProperty( "defaultCornerstone" ) ) { return merge( currentConfig, languageSpecificConfig.defaultCornerstone ); } // Use the default language-specific config for posts and pages. return merge( currentConfig, languageSpecificConfig.defaultAnalysis ); } /** * Returns the score and the appropriate feedback string based on the current word count. * * @param {number} wordCount The amount of words to be checked against. * * @returns {Object} The score and the feedback string. */ calculateResult( wordCount ) { if ( wordCount >= this._config.recommendedMinimum ) { return { score: this._config.scores.recommendedMinimum, resultText: sprintf( /* translators: %1$d expands to the number of words / characters in the text, %2$s expands to a link on yoast.com, %3$s expands to the anchor end tag, %4$s expands to the word 'words' or 'characters'. */ __( "%2$sText length%3$s: The text contains %1$d %4$s. Good job!", "wordpress-seo" ), wordCount, this._config.urlTitle, "</a>", this._config.countTextIn.plural ), }; } if ( inRange( wordCount, 0, this._config.belowMinimum ) ) { let badScore = this._config.scores.farBelowMinimum; if ( inRange( wordCount, 0, this._config.veryFarBelowMinimum ) ) { badScore = this._config.scores.veryFarBelowMinimum; } return { score: badScore, resultText: sprintf( /* translators: %1$d expands to the number of words / characters in the text, %2$s expands to a link on yoast.com, %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag, %5$d expands to the recommended minimum of words / characters, %6$s expands to the word 'word' or 'character', %7$s expands to the word 'words' or 'characters'. */ _n( // eslint-disable-next-line max-len "%2$sText length%4$s: The text contains %1$d %6$s. This is far below the recommended minimum of %5$d %7$s. %3$sAdd more content%4$s.", // eslint-disable-next-line max-len "%2$sText length%4$s: The text contains %1$d %7$s. This is far below the recommended minimum of %5$d %7$s. %3$sAdd more content%4$s.", wordCount, "wordpress-seo" ), wordCount, this._config.urlTitle, this._config.urlCallToAction, "</a>", this._config.recommendedMinimum, this._config.countTextIn.singular, this._config.countTextIn.plural ), }; } if ( inRange( wordCount, this._config.slightlyBelowMinimum, this._config.recommendedMinimum ) ) { if ( this._config.cornerstoneContent === false ) { return { score: this._config.scores.slightlyBelowMinimum, resultText: sprintf( /* translators: %1$d expands to the number of words / characters in the text, %2$s expands to a link on yoast.com, %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag, %5$d expands to the recommended minimum of words / characters, %6$s expands to the word 'words' or 'characters'. */ __( // eslint-disable-next-line max-len "%2$sText length%4$s: The text contains %1$d %6$s. This is slightly below the recommended minimum of %5$d %6$s. %3$sAdd a bit more copy%4$s.", "wordpress-seo" ), wordCount, this._config.urlTitle, this._config.urlCallToAction, "</a>", this._config.recommendedMinimum, this._config.countTextIn.plural ), }; } return { score: this._config.scores.slightlyBelowMinimum, resultText: sprintf( /* translators: %1$d expands to the number of words / characters in the text, %2$s expands to a link on yoast.com, %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag, %5$d expands to the recommended minimum of words / characters, %6$s expands to the word 'words' or 'characters'. */ __( // eslint-disable-next-line max-len "%2$sText length%4$s: The text contains %1$d %6$s. This is below the recommended minimum of %5$d %6$s. %3$sAdd more content%4$s.", "wordpress-seo" ), wordCount, this._config.urlTitle, this._config.urlCallToAction, "</a>", this._config.recommendedMinimum, this._config.countTextIn.plural ), }; } return { score: this._config.scores.belowMinimum, resultText: sprintf( /* translators: %1$d expands to the number of words / characters in the text, %2$s expands to a link on yoast.com, %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag, %5$d expands to the recommended minimum of words / characters, %6$s expands to the word 'words' or 'characters'. */ __( // eslint-disable-next-line max-len "%2$sText length%4$s: The text contains %1$d %6$s. This is below the recommended minimum of %5$d %6$s. %3$sAdd more content%4$s.", "wordpress-seo" ), wordCount, this._config.urlTitle, this._config.urlCallToAction, "</a>", this._config.recommendedMinimum, this._config.countTextIn.plural ), }; } }