yoastseo
Version:
Yoast client-side content analysis
308 lines (281 loc) • 10.3 kB
JavaScript
"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