UNPKG

yoastseo-dep

Version:

Yoast clientside page analysis

185 lines (171 loc) 6.51 kB
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;