UNPKG

yoastseo

Version:

Yoast client-side content analysis

228 lines (217 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _i18n = require("@wordpress/i18n"); var _lodash = require("lodash"); var _assessment = _interopRequireDefault(require("../assessment")); var _helpers = require("../../../helpers"); var _AssessmentResult = _interopRequireDefault(require("../../../values/AssessmentResult")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * @typedef {import("../../../languageProcessing/AbstractResearcher").default } Researcher * @typedef {import("../../../values/").Paper } Paper */ /** * Represents an assessment that checks the length of the text and gives feedback accordingly. */ class TextLengthAssessment extends _assessment.default { /** * 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 }, countCharacters: false, urlTitle: (0, _helpers.createAnchorOpeningTag)("https://yoa.st/34n"), urlCallToAction: (0, _helpers.createAnchorOpeningTag)("https://yoa.st/34o"), cornerstoneContent: false, customContentType: "" }; this.identifier = "textLength"; this._config = (0, _lodash.merge)(defaultConfig, config); } /** * Executes the Assessment and returns 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 textLength = researcher.getResearch("wordCountInText"); if (researcher.getConfig("textLength")) { this._config = this.getLanguageSpecificConfig(researcher); } this._config.countCharacters = !!researcher.getConfig("countCharacters"); const calculatedResult = this.calculateResult(textLength.count); const assessmentResult = new _AssessmentResult.default(); assessmentResult.setScore(calculatedResult.score); assessmentResult.setText(calculatedResult.resultText); return assessmentResult; } /** * Checks if there is language-specific config, and if so, overwrites 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"); // Checks if a language has configuration for custom content types. if (Object.hasOwn(languageSpecificConfig, currentConfig.customContentType)) { return (0, _lodash.merge)(currentConfig, languageSpecificConfig[currentConfig.customContentType]); } // Checks if a language has a default cornerstone configuration. if (currentConfig.cornerstoneContent === true && currentConfig.customContentType === "" && Object.hasOwn(languageSpecificConfig, "defaultCornerstone")) { return (0, _lodash.merge)(currentConfig, languageSpecificConfig.defaultCornerstone); } // Uses the default language-specific config for posts and pages. return (0, _lodash.merge)(currentConfig, languageSpecificConfig.defaultAnalysis); } /** * Returns the feedback texts for the text length assessment. * * @returns {{firstSentence: (function(boolean, number): string), good: (function(string): string), slightlyBelow: (function(boolean, string): string), below: (function(boolean, string): string), farBelow: (function(boolean, string): string)}} */ getFeedbackTexts() { return { firstSentence: (useCharacter, textLength) => { const wordFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of words, %2$s expands to a link on yoast.com, %3$s expands to the anchor end tag. */ (0, _i18n._n)("%2$sText length%3$s: The text contains %1$d word.", "%2$sText length%3$s: The text contains %1$d words.", textLength, "wordpress-seo"), textLength, this._config.urlTitle, "</a>"); const characterFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of characters, %2$s expands to a link on yoast.com, %3$s expands to the anchor end tag. */ (0, _i18n._n)("%2$sText length%3$s: The text contains %1$d character.", "%2$sText length%3$s: The text contains %1$d characters.", textLength, "wordpress-seo"), textLength, this._config.urlTitle, "</a>"); return useCharacter ? characterFeedback : wordFeedback; }, good: textContains => { return (0, _i18n.sprintf)(/* translators: %1$s expands to the sentence "The text contains X word(s)." or "The text contains X character(s)." */ (0, _i18n.__)("%1$s Good job!", "wordpress-seo"), textContains); }, slightlyBelow: (useCharacter, textContains) => { const wordFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of words, %2$s expands to the sentence "The text contains X word(s).", %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag. */ (0, _i18n._n)("%2$s This is slightly below the recommended minimum of %1$d word. %3$sAdd more content%4$s.", "%2$s This is slightly below the recommended minimum of %1$d words. %3$sAdd more content%4$s.", this._config.recommendedMinimum, "wordpress-seo"), this._config.recommendedMinimum, textContains, this._config.urlCallToAction, "</a>"); const characterFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of characters, %2$s expands to the sentence "The text contains X character(s).", %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag. */ (0, _i18n._n)("%2$s This is slightly below the recommended minimum of %1$d character. %3$sAdd more content%4$s.", "%2$s This is slightly below the recommended minimum of %1$d characters. %3$sAdd more content%4$s.", this._config.recommendedMinimum, "wordpress-seo"), this._config.recommendedMinimum, textContains, this._config.urlCallToAction, "</a>"); return useCharacter ? characterFeedback : wordFeedback; }, below: (useCharacter, textContains) => { const wordFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of words, %2$s expands to the sentence "The text contains X word(s).", %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag. */ (0, _i18n._n)("%2$s This is below the recommended minimum of %1$d word. %3$sAdd more content%4$s.", "%2$s This is below the recommended minimum of %1$d words. %3$sAdd more content%4$s.", this._config.recommendedMinimum, "wordpress-seo"), this._config.recommendedMinimum, textContains, this._config.urlCallToAction, "</a>"); const characterFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of characters, %2$s expands to the sentence "The text contains X character(s).", %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag. */ (0, _i18n._n)("%2$s This is below the recommended minimum of %1$d character. %3$sAdd more content%4$s.", "%2$s This is below the recommended minimum of %1$d characters. %3$sAdd more content%4$s.", this._config.recommendedMinimum, "wordpress-seo"), this._config.recommendedMinimum, textContains, this._config.urlCallToAction, "</a>"); return useCharacter ? characterFeedback : wordFeedback; }, farBelow: (useCharacter, textContains) => { const wordFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of words, %2$s expands to the sentence "The text contains X word(s).", %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag. */ (0, _i18n._n)("%2$s This is far below the recommended minimum of %1$d word. %3$sAdd more content%4$s.", "%2$s This is far below the recommended minimum of %1$d words. %3$sAdd more content%4$s.", this._config.recommendedMinimum, "wordpress-seo"), this._config.recommendedMinimum, textContains, this._config.urlCallToAction, "</a>"); const characterFeedback = (0, _i18n.sprintf)(/* translators: %1$d expands to the number of characters, %2$s expands to the sentence "The text contains X character(s).", %3$s expands to a link on yoast.com, %4$s expands to the anchor end tag. */ (0, _i18n._n)("%2$s This is far below the recommended minimum of %1$d character. %3$sAdd more content%4$s.", "%2$s This is far below the recommended minimum of %1$d characters. %3$sAdd more content%4$s.", this._config.recommendedMinimum, "wordpress-seo"), this._config.recommendedMinimum, textContains, this._config.urlCallToAction, "</a>"); return useCharacter ? characterFeedback : wordFeedback; } }; } /** * Returns the score and the appropriate feedback string based on the current word count * for taxonomies (in WordPress) and collections (in Shopify). * * @param {number} textLength The amount of words or characters to be checked against. * @returns {{score: number, resultText: string}} The score and the feedback string. */ calculateTaxonomyResult(textLength) { // Gets functions used to create feedback strings. const feedbackTexts = this.getFeedbackTexts(); const firstSentence = feedbackTexts.firstSentence(this._config.countCharacters, textLength); if (textLength >= this._config.recommendedMinimum) { return { score: this._config.scores.recommendedMinimum, resultText: feedbackTexts.good(firstSentence) }; } if ((0, _lodash.inRange)(textLength, this._config.slightlyBelowMinimum, this._config.recommendedMinimum)) { return { score: this._config.scores.slightlyBelowMinimum, resultText: feedbackTexts.slightlyBelow(this._config.countCharacters, firstSentence) }; } if ((0, _lodash.inRange)(textLength, this._config.veryFarBelowMinimum, this._config.slightlyBelowMinimum)) { return { score: this._config.scores.belowMinimum, resultText: feedbackTexts.below(this._config.countCharacters, firstSentence) }; } return { score: this._config.scores.veryFarBelowMinimum, resultText: (0, _i18n.sprintf)(/* translators: %1$s expands to a link on yoast.com, %2$s expands to a link on yoast.com, %3$s expands to the anchor end tag. */ (0, _i18n.__)("%1$sText length%3$s: %2$sPlease add some content%3$s.", "wordpress-seo"), this._config.urlTitle, this._config.urlCallToAction, "</a>") }; } /** * Returns the score and the appropriate feedback string based on the current word count for every type of content. * * @param {number} textLength The amount of words or characters to be checked against. * * @returns {{score: number, resultText: string}} The score and the feedback string. */ calculateResult(textLength) { const customContentTypes = ["taxonomyAssessor", "collectionSEOAssessor", "collectionCornerstoneSEOAssessor"]; if (customContentTypes.includes(this._config.customContentType)) { return this.calculateTaxonomyResult(textLength); } // Gets functions used to create feedback strings. const feedbackTexts = this.getFeedbackTexts(); const firstSentence = feedbackTexts.firstSentence(this._config.countCharacters, textLength); if (textLength >= this._config.recommendedMinimum) { return { score: this._config.scores.recommendedMinimum, resultText: feedbackTexts.good(firstSentence) }; } if ((0, _lodash.inRange)(textLength, 0, this._config.belowMinimum)) { let badScore = this._config.scores.farBelowMinimum; if ((0, _lodash.inRange)(textLength, 0, this._config.veryFarBelowMinimum)) { badScore = this._config.scores.veryFarBelowMinimum; } return { score: badScore, resultText: feedbackTexts.farBelow(this._config.countCharacters, firstSentence) }; } if ((0, _lodash.inRange)(textLength, this._config.slightlyBelowMinimum, this._config.recommendedMinimum)) { if (this._config.cornerstoneContent === false) { return { score: this._config.scores.slightlyBelowMinimum, resultText: feedbackTexts.slightlyBelow(this._config.countCharacters, firstSentence) }; } return { score: this._config.scores.slightlyBelowMinimum, resultText: feedbackTexts.below(this._config.countCharacters, firstSentence) }; } return { score: this._config.scores.belowMinimum, resultText: feedbackTexts.below(this._config.countCharacters, firstSentence) }; } } exports.default = TextLengthAssessment; //# sourceMappingURL=TextLengthAssessment.js.map