yoastseo-dep
Version:
Yoast clientside page analysis
185 lines (171 loc) • 6.51 kB
JavaScript
import { __, sprintf } from "@wordpress/i18n";
import AssessmentResult from "../../values/AssessmentResult";
/**
* Analyzes a paper by doing a list of assessments on a tree representation of a text and its metadata.
* Aggregates the scores on each individual assessment into an overall score.
*
* This score can represent anything from the readability to the SEO of the given text and metadata.
*
* @memberOf module:parsedPaper/assess
*/
class TreeAssessor {
/**
* Creates a new assessor.
*
* @param {Object} options Assessor options.
* @param {module:parsedPaper/research.TreeResearcher} options.researcher Supplies the assessments with researches and their
* (cached) results.
* @param {module:parsedPaper/assess.ScoreAggregator} options.scoreAggregator Aggregates the scores on the individual assessments into one.
* @param {module:parsedPaper/assess.Assessment[]} [options.assessments] The list of assessments to apply.
*/
constructor( options ) {
/**
* Supplies the assessments with researches and their (cached) results.
* @type {module:parsedPaper/research.TreeResearcher}
*/
this.researcher = options.researcher;
/**
* Aggregates the scores on the individual assessments into one overall score.
* @type {module:parsedPaper/assess.ScoreAggregator}
*/
this.scoreAggregator = options.scoreAggregator;
/**
* The list of assessments to apply.
* @type {module:parsedPaper/assess.Assessment[]}
*/
this._assessments = options.assessments || [];
// Make sure that all of the assessments have the researcher.
this._assessments.forEach( assessment => assessment.setResearcher( this.researcher ) );
}
/**
* Returns the list of available assessments.
*
* @returns {module:parsedPaper/assess.Assessment[]} The list of all available assessments.
*/
getAssessments() {
return this._assessments;
}
/**
* Assesses the given text by applying all the assessments to it
* and aggregating the resulting scores.
*
* @param {Paper} paper The paper to assess. This contains metadata about the text.
* @param {module:parsedPaper/structure.Node} node The root node of the tree to check.
*
* @returns {Promise<{results: AssessmentResult[], score: number}>} The assessment results and the overall score.
*/
async assess( paper, node ) {
const applicableAssessments = await this.getApplicableAssessments( paper, node );
/*
Apply every applicable assessment on the document.
Wait before they are done before aggregating the results
and returning the results and final score.
*/
const results = await Promise.all(
applicableAssessments.map( assessment => this.applyAssessment( assessment, paper, node ) )
);
// Filter out errored assessments.
const validResults = results.filter( result => result.getScore() !== -1 );
// Compute overall score.
const score = this.scoreAggregator.aggregate( validResults );
return { results, score };
}
/**
* Applies the given assessment to the paper-node combination.
*
* @param {module:parsedPaper/assess.Assessment} assessment The assessment to apply.
* @param {Paper} paper The paper to apply the assessment to.
* @param {module:parsedPaper/structure.Node} node The root node of the tree to apply the assessment to.
*
* @returns {Promise<AssessmentResult>} The result of the assessment.
*/
async applyAssessment( assessment, paper, node ) {
return assessment.apply( paper, node ).catch(
() => {
return new AssessmentResult( {
text: sprintf(
/* translators: %1$s expands to the name of the assessment. */
__( "An error occurred in the '%1$s' assessment", "wordpress-seo" ),
assessment.name
),
score: -1,
} );
}
);
}
/**
* Adds the assessment to the list of assessments to apply.
*
* @param {string} name The name to register the assessment under.
* @param {module:parsedPaper/assess.Assessment} assessment The assessment to add.
*
* @returns {void}
*/
registerAssessment( name, assessment ) {
assessment.name = name;
assessment.setResearcher( this.researcher );
this._assessments.push( assessment );
}
/**
* Removes the assessment registered under the given name, if it exists.
*
* @param {string} name The name of the assessment to remove.
*
* @returns {module:parsedPaper/assess.Assessment|null} The deleted assessment, or null if no assessment has been deleted.
*/
removeAssessment( name ) {
const index = this._assessments.findIndex( assessment => assessment.name === name );
if ( index > -1 ) {
const deleted = this._assessments.splice( index, 1 );
return deleted[ 0 ];
}
return null;
}
/**
* Returns the assessment registered under the given name.
* Returns `null` if no assessment is registered under the given name.
*
* @param {string} name The name of the assessment to get.
*
* @returns {Assessment|null} The assessment.
*/
getAssessment( name ) {
const assessmentToReturn = this._assessments.find( assessment => assessment.name === name );
return assessmentToReturn ? assessmentToReturn : null;
}
/**
* Sets the assessments that this assessor needs to apply.
*
* @param {module:parsedPaper/assess.Assessment[]} assessments The assessments to set.
*
* @returns {void}
*/
setAssessments( assessments ) {
this._assessments = assessments;
}
/**
* Returns the list of applicable assessments.
*
* @param {Paper} paper The paper to check.
* @param {module:parsedPaper/structure.Node} node The tree to check.
*
* @returns {Promise<Array>} The list of applicable assessments.
*/
async getApplicableAssessments( paper, node ) {
// List to store the applicable assessments in (empty for now).
const applicableAssessments = [];
// Asynchronously add each assessment to the list if they are applicable.
const promises = this._assessments.map( assessment =>
assessment.isApplicable( paper, node ).then(
applicable => {
if ( applicable ) {
applicableAssessments.push( assessment );
}
}
)
);
// Wait before all the applicable assessments have been added before returning them.
return Promise.all( promises ).then( () => applicableAssessments );
}
}
export default TreeAssessor;