UNPKG

yoastseo

Version:

Yoast client-side content analysis

308 lines (281 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _i18n = require("@wordpress/i18n"); var _lodash = require("lodash"); var _AssessmentResult = _interopRequireDefault(require("../../values/AssessmentResult.js")); var _build = require("../../parse/build"); var _LanguageProcessor = _interopRequireDefault(require("../../parse/language/LanguageProcessor.js")); var _missingArgument = _interopRequireDefault(require("../../errors/missingArgument.js")); var _removeDuplicateMarks = _interopRequireDefault(require("../../markers/removeDuplicateMarks.js")); var _errors = require("../../helpers/errors.js"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } // External dependencies. // Internal dependencies. // The maximum score of individual assessment is 9. This is why we set the "score rating" here to 9. const ScoreRating = 9; /** * The Assessor is a base class for all assessors. */ class Assessor { /** * Creates a new Assessor instance. * @param {Researcher} researcher The researcher to use. * @param {Object} [options] The assessor options. */ constructor(researcher, options) { this.type = "assessor"; this.setResearcher(researcher); /** * The list of assessments. * @type {Assessment[]} * @private */ this._assessments = []; /** * The list of results. * @type {AssessmentResult[]} */ this.results = []; /** * The options. * @type {Object|{}} * @private */ this._options = options || {}; /** * The ScoreAggregator for this assessor. * @type {ScoreAggregator} * @private */ this._scoreAggregator = null; } /** * Checks if the researcher is defined and sets it. * * @param {Researcher} researcher The researcher to use in the assessor. * * @throws {MissingArgument} Parameter needs to be a valid researcher object. * @returns {void} */ setResearcher(researcher) { if ((0, _lodash.isUndefined)(researcher)) { throw new _missingArgument.default("The assessor requires a researcher."); } this._researcher = researcher; } /** * Gets all available assessments. * @returns {Assessment[]} assessment */ getAvailableAssessments() { return this._assessments; } /** * Checks whether the Assessment is applicable. * * @param {Assessment} assessment The Assessment object that needs to be checked. * @param {Paper} paper The Paper object to check against. * @param {Researcher} [researcher] The Researcher object containing additional information. * @returns {boolean} Whether or not the Assessment is applicable. */ isApplicable(assessment, paper, researcher) { if (typeof assessment.isApplicable === "undefined") { return true; } return assessment.isApplicable(paper, researcher); } /** * Determines whether an assessment has a marker. * * @param {Assessment} assessment The assessment to check for. * @returns {boolean} Whether or not the assessment has a marker. */ hasMarker(assessment) { return (0, _lodash.isFunction)(this._options.marker) && (Object.hasOwn(assessment, "getMarks") || typeof assessment.getMarks === "function"); } /** * Returns the specific marker for this assessor. * * @returns {Function} The specific marker for this assessor. */ getSpecificMarker() { return this._options.marker; } /** * Returns the paper that was most recently assessed. * * @returns {Paper} The paper that was most recently assessed. */ getPaper() { return this._lastPaper; } /** * Returns the marker for a given assessment, composes the specific marker with the assessment getMarks function. * * @param {Assessment} assessment The assessment for which we are retrieving the composed marker. * @param {Paper} paper The paper to retrieve the marker for. * @param {Researcher} researcher The researcher for the paper. * @returns {Function} A function that can mark the given paper according to the given assessment. */ getMarker(assessment, paper, researcher) { const specificMarker = this._options.marker; return function () { let marks = assessment.getMarks(paper, researcher); marks = (0, _removeDuplicateMarks.default)(marks); specificMarker(paper, marks); }; } /** * Runs the researches defined in the task list or the default researches. * * @param {Paper} paper The paper to run assessments on. * @returns {void} */ assess(paper) { this._researcher.setPaper(paper); const languageProcessor = new _LanguageProcessor.default(this._researcher); const shortcodes = paper._attributes && paper._attributes.shortcodes; paper.setTree((0, _build.build)(paper, languageProcessor, shortcodes)); let assessments = this.getAvailableAssessments(); assessments = assessments.filter(assessment => this.isApplicable(assessment, paper, this._researcher)); this.setHasMarkers(false); this.results = assessments.map(assessment => this.executeAssessment(paper, this._researcher, assessment)); this._lastPaper = paper; } /** * Sets the value of has markers with a boolean to determine if there are markers. * * @param {boolean} hasMarkers True when there are markers, otherwise it is false. * @returns {void} */ setHasMarkers(hasMarkers) { this._hasMarkers = hasMarkers; } /** * Returns true when there are markers. * * @returns {boolean} Are there markers */ hasMarkers() { return this._hasMarkers; } /** * Executes an assessment and returns the AssessmentResult. * * @param {Paper} paper The paper to pass to the assessment. * @param {Researcher} researcher The researcher to pass to the assessment. * @param {Assessment} assessment The assessment to execute. * @returns {AssessmentResult} The result of the assessment. */ executeAssessment(paper, researcher, assessment) { let result; try { result = assessment.getResult(paper, researcher); result.setIdentifier(assessment.identifier); if (result.hasMarks()) { result.marks = assessment.getMarks(paper, researcher); result.marks = (0, _removeDuplicateMarks.default)(result.marks); } if (result.hasMarks() && this.hasMarker(assessment)) { this.setHasMarkers(true); result.setMarker(this.getMarker(assessment, paper, researcher)); } } catch (assessmentError) { (0, _errors.showTrace)(assessmentError); result = new _AssessmentResult.default(); result.setScore(-1); result.setText((0, _i18n.sprintf)(/* translators: %1$s expands to the name of the assessment. */ (0, _i18n.__)("An error occurred in the '%1$s' assessment", "wordpress-seo"), assessment.identifier, assessmentError)); } return result; } /** * Filters out all assessment results that have no score and no text. * * @returns {AssessmentResult[]} The array with all the valid assessments. */ getValidResults() { return this.results.filter(result => this.isValidResult(result)); } /** * Returns if an assessmentResult is valid. * * @param {AssessmentResult} assessmentResult The assessmentResult to validate. * @returns {boolean} whether or not the result is valid. */ isValidResult(assessmentResult) { return assessmentResult.hasScore() && assessmentResult.hasText(); } /** * Returns the overall score. Calculates the total score by adding all scores and dividing these * by the number of results times the ScoreRating. * * @returns {number} The overall score. */ calculateOverallScore() { const results = this.getValidResults(); const totalScore = results.reduce((total, assessmentResult) => total + assessmentResult.getScore(), 0); return Math.round(totalScore / (results.length * ScoreRating) * 100) || 0; } /** * Registers an assessment and adds it to the internal assessments object. * * @param {string} name The name of the assessment. * @param {Assessment} assessment The object containing function to run as an assessment and it's requirements. * @returns {boolean} Whether registering the assessment was successful. */ addAssessment(name, assessment) { if (!Object.hasOwn(assessment, "identifier")) { assessment.identifier = name; } // If the assessor already has the same assessment, remove it and replace it with the new assessment with the same identifier. if (this.getAssessment(assessment.identifier)) { this.removeAssessment(assessment.identifier); } this._assessments.push(assessment); return true; } /** * Removes a specific Assessment from the list of Assessments. * * @param {string} name The Assessment to remove from the list of assessments. * @returns {void} */ removeAssessment(name) { const toDelete = this._assessments.findIndex(assessment => Object.hasOwn(assessment, "identifier") && name === assessment.identifier); if (-1 !== toDelete) { this._assessments.splice(toDelete, 1); } } /** * Returns an assessment by identifier * * @param {string} identifier The identifier of the assessment. * @returns {Assessment} The object if found, otherwise undefined. */ getAssessment(identifier) { return this._assessments.find(assessment => Object.hasOwn(assessment, "identifier") && identifier === assessment.identifier); } /** * Checks which of the available assessments are applicable and returns an array with applicable assessments. * * @returns {Assessment[]} The array with applicable assessments. */ getApplicableAssessments() { const availableAssessments = this.getAvailableAssessments(); return availableAssessments.filter(assessment => this.isApplicable(assessment, this.getPaper(), this._researcher)); } /** * Returns the ScoreAggregator for this assessor. * * @returns {ScoreAggregator} The specific marker for this assessor. */ getScoreAggregator() { return this._scoreAggregator; } } var _default = exports.default = Assessor; //# sourceMappingURL=assessor.js.map