diff --git a/packages/yoastseo/spec/languageProcessing/values/ClauseSpec.js b/packages/yoastseo/spec/languageProcessing/values/ClauseSpec.js
index 96487b4dc36..436e286a7f5 100644
--- a/packages/yoastseo/spec/languageProcessing/values/ClauseSpec.js
+++ b/packages/yoastseo/spec/languageProcessing/values/ClauseSpec.js
@@ -40,11 +40,5 @@ describe( "a test for serializing and parsing a Clause class instance", function
isPassive: false,
participles: [],
} );
- expect( mockClause.parse( mockClause.serialize() ) ).toEqual( {
- _clauseText: "The cat is loved.",
- _auxiliaries: [ "is" ],
- _isPassive: false,
- _participles: [],
- } );
} );
} );
diff --git a/packages/yoastseo/spec/languageProcessing/values/SentenceSpec.js b/packages/yoastseo/spec/languageProcessing/values/SentenceSpec.js
index 80bf8ad6d62..20689cd8bf4 100644
--- a/packages/yoastseo/spec/languageProcessing/values/SentenceSpec.js
+++ b/packages/yoastseo/spec/languageProcessing/values/SentenceSpec.js
@@ -64,15 +64,5 @@ describe( "Creates a sentence object", function() {
isPassive: true,
sentenceText: "Cats are adored.",
} );
- expect( sentence.parse( sentence.serialize() ) ).toEqual( {
- _clauses: [
- { _auxiliaries: [ "are" ],
- _clauseText: "Cats are adored",
- _isPassive: true,
- _participles: [],
- } ],
- _isPassive: true,
- _sentenceText: "Cats are adored.",
- } );
} );
} );
diff --git a/packages/yoastseo/src/app.js b/packages/yoastseo/src/app.js
index da808c96d21..cade6bdcd96 100644
--- a/packages/yoastseo/src/app.js
+++ b/packages/yoastseo/src/app.js
@@ -13,14 +13,14 @@ import AssessorPresenter from "./scoring/renderers/AssessorPresenter.js";
import SEOAssessor from "./scoring/seoAssessor.js";
import Paper from "./values/Paper.js";
-var inputDebounceDelay = 800;
+const inputDebounceDelay = 800;
/**
* Default config for YoastSEO.js
*
* @type {Object}
*/
-var defaults = {
+const defaults = {
callbacks: {
bindElementEvents: noop,
updateSnippetValues: noop,
@@ -192,630 +192,637 @@ function verifyArguments( args ) {
*
* @constructor
*/
-var App = function( args ) {
- if ( ! isObject( args ) ) {
- args = {};
- }
-
- defaultsDeep( args, defaults );
-
- verifyArguments( args );
+class App {
+ /**
+ * Creates a new App instance.
+ * @param {Object} args The arguments.
+ */
+ constructor( args ) {
+ if ( ! isObject( args ) ) {
+ args = {};
+ }
- this.config = args;
+ defaultsDeep( args, defaults );
- if ( args.debouncedRefresh === true ) {
- this.refresh = debounce( this.refresh.bind( this ), inputDebounceDelay );
- }
- this._pureRefresh = throttle( this._pureRefresh.bind( this ), this.config.typeDelay );
+ verifyArguments( args );
- this.callbacks = this.config.callbacks;
+ this.config = args;
- setLocaleData( this.config.translations.locale_data[ "wordpress-seo" ], "wordpress-seo" );
+ if ( args.debouncedRefresh === true ) {
+ this.refresh = debounce( this.refresh.bind( this ), inputDebounceDelay );
+ }
+ this._pureRefresh = throttle( this._pureRefresh.bind( this ), this.config.typeDelay );
- this.initializeAssessors( args );
+ this.callbacks = this.config.callbacks;
- this.pluggable = new Pluggable( this );
+ setLocaleData( this.config.translations.locale_data[ "wordpress-seo" ], "wordpress-seo" );
- this.getData();
+ this.initializeAssessors( args );
- this.defaultOutputElement = this.getDefaultOutputElement( args );
+ this.pluggable = new Pluggable( this );
- if ( this.defaultOutputElement !== "" ) {
- this.showLoadingDialog();
- }
+ this.getData();
- this._assessorOptions = {
- useCornerStone: false,
- };
+ this.defaultOutputElement = this.getDefaultOutputElement( args );
- this.initAssessorPresenters();
-};
+ if ( this.defaultOutputElement !== "" ) {
+ this.showLoadingDialog();
+ }
-/**
- * Returns the default output element based on which analyses are active.
- *
- * @param {Object} args The arguments passed to the App.
- * @returns {string} The ID of the target that is active.
- */
-App.prototype.getDefaultOutputElement = function( args ) {
- if ( args.keywordAnalysisActive ) {
- return args.targets.output;
- }
+ this._assessorOptions = {
+ useCornerStone: false,
+ };
- if ( args.contentAnalysisActive ) {
- return args.targets.contentOutput;
+ this.initAssessorPresenters();
}
- return "";
-};
-
-/**
- * Sets the assessors based on the assessor options and refreshes them.
- *
- * @param {Object} assessorOptions The specific options.
- * @returns {void}
- */
-App.prototype.changeAssessorOptions = function( assessorOptions ) {
- this._assessorOptions = merge( this._assessorOptions, assessorOptions );
-
- // Set the assessors based on the new assessor options.
- this.seoAssessor = this.getSeoAssessor();
- this.contentAssessor = this.getContentAssessor();
-
- // Refresh everything so the user sees the changes.
- this.initAssessorPresenters();
- this.refresh();
-};
+ /**
+ * Returns the default output element based on which analyses are active.
+ *
+ * @param {Object} args The arguments passed to the App.
+ * @returns {string} The ID of the target that is active.
+ */
+ getDefaultOutputElement( args ) {
+ if ( args.keywordAnalysisActive ) {
+ return args.targets.output;
+ }
-/**
- * Returns an instance of the seo assessor to use.
- *
- * @returns {Assessor} The assessor instance.
- */
-App.prototype.getSeoAssessor = function() {
- const { useCornerStone } = this._assessorOptions;
- return useCornerStone ? this.cornerStoneSeoAssessor : this.defaultSeoAssessor;
-};
+ if ( args.contentAnalysisActive ) {
+ return args.targets.contentOutput;
+ }
-/**
- * Returns an instance of the content assessor to use.
- *
- * @returns {Assessor} The assessor instance.
- */
-App.prototype.getContentAssessor = function() {
- const { useCornerStone } = this._assessorOptions;
- return useCornerStone ? this.cornerStoneContentAssessor : this.defaultContentAssessor;
-};
+ return "";
+ }
+
+ /**
+ * Sets the assessors based on the assessor options and refreshes them.
+ *
+ * @param {Object} assessorOptions The specific options.
+ * @returns {void}
+ */
+ changeAssessorOptions( assessorOptions ) {
+ this._assessorOptions = merge( this._assessorOptions, assessorOptions );
+
+ // Set the assessors based on the new assessor options.
+ this.seoAssessor = this.getSeoAssessor();
+ this.contentAssessor = this.getContentAssessor();
+
+ // Refresh everything so the user sees the changes.
+ this.initAssessorPresenters();
+ this.refresh();
+ }
+
+ /**
+ * Returns an instance of the seo assessor to use.
+ *
+ * @returns {Assessor} The assessor instance.
+ */
+ getSeoAssessor() {
+ const { useCornerStone } = this._assessorOptions;
+ return useCornerStone ? this.cornerStoneSeoAssessor : this.defaultSeoAssessor;
+ }
+
+ /**
+ * Returns an instance of the content assessor to use.
+ *
+ * @returns {Assessor} The assessor instance.
+ */
+ getContentAssessor() {
+ const { useCornerStone } = this._assessorOptions;
+ return useCornerStone ? this.cornerStoneContentAssessor : this.defaultContentAssessor;
+ }
+
+ /**
+ * Initializes assessors based on if the respective analysis is active.
+ *
+ * @param {Object} args The arguments passed to the App.
+ * @returns {void}
+ */
+ initializeAssessors( args ) {
+ this.initializeSEOAssessor( args );
+ this.initializeContentAssessor( args );
+ }
+
+ /**
+ * Initializes the SEO assessor.
+ *
+ * @param {Object} args The arguments passed to the App.
+ * @returns {void}
+ */
+ initializeSEOAssessor( args ) {
+ if ( ! args.keywordAnalysisActive ) {
+ return;
+ }
-/**
- * Initializes assessors based on if the respective analysis is active.
- *
- * @param {Object} args The arguments passed to the App.
- * @returns {void}
- */
-App.prototype.initializeAssessors = function( args ) {
- this.initializeSEOAssessor( args );
- this.initializeContentAssessor( args );
-};
+ this.defaultSeoAssessor = new SEOAssessor( { marker: this.config.marker } );
+ this.cornerStoneSeoAssessor = new CornerstoneSEOAssessor( { marker: this.config.marker } );
-/**
- * Initializes the SEO assessor.
- *
- * @param {Object} args The arguments passed to the App.
- * @returns {void}
- */
-App.prototype.initializeSEOAssessor = function( args ) {
- if ( ! args.keywordAnalysisActive ) {
- return;
+ // Set the assessor
+ if ( isUndefined( args.seoAssessor ) ) {
+ this.seoAssessor = this.defaultSeoAssessor;
+ } else {
+ this.seoAssessor = args.seoAssessor;
+ }
}
- this.defaultSeoAssessor = new SEOAssessor( { marker: this.config.marker } );
- this.cornerStoneSeoAssessor = new CornerstoneSEOAssessor( { marker: this.config.marker } );
+ /**
+ * Initializes the content assessor.
+ *
+ * @param {Object} args The arguments passed to the App.
+ * @returns {void}
+ */
+ initializeContentAssessor( args ) {
+ if ( ! args.contentAnalysisActive ) {
+ return;
+ }
- // Set the assessor
- if ( isUndefined( args.seoAssessor ) ) {
- this.seoAssessor = this.defaultSeoAssessor;
- } else {
- this.seoAssessor = args.seoAssessor;
- }
-};
+ this.defaultContentAssessor = new ContentAssessor( { marker: this.config.marker, locale: this.config.locale } );
+ this.cornerStoneContentAssessor = new CornerstoneContentAssessor( { marker: this.config.marker, locale: this.config.locale } );
-/**
- * Initializes the content assessor.
- *
- * @param {Object} args The arguments passed to the App.
- * @returns {void}
- */
-App.prototype.initializeContentAssessor = function( args ) {
- if ( ! args.contentAnalysisActive ) {
- return;
+ // Set the content assessor
+ if ( isUndefined( args._contentAssessor ) ) {
+ this.contentAssessor = this.defaultContentAssessor;
+ } else {
+ this.contentAssessor = args._contentAssessor;
+ }
}
- this.defaultContentAssessor = new ContentAssessor( { marker: this.config.marker, locale: this.config.locale } );
- this.cornerStoneContentAssessor = new CornerstoneContentAssessor( { marker: this.config.marker, locale: this.config.locale } );
+ /**
+ * Extend the config with defaults.
+ *
+ * @param {Object} args The arguments to be extended.
+ * @returns {Object} args The extended arguments.
+ */
+ extendConfig( args ) {
+ args.sampleText = this.extendSampleText( args.sampleText );
+ args.locale = args.locale || "en_US";
- // Set the content assessor
- if ( isUndefined( args._contentAssessor ) ) {
- this.contentAssessor = this.defaultContentAssessor;
- } else {
- this.contentAssessor = args._contentAssessor;
+ return args;
}
-};
-/**
- * Extend the config with defaults.
- *
- * @param {Object} args The arguments to be extended.
- * @returns {Object} args The extended arguments.
- */
-App.prototype.extendConfig = function( args ) {
- args.sampleText = this.extendSampleText( args.sampleText );
- args.locale = args.locale || "en_US";
+ /**
+ * Extend sample text config with defaults.
+ *
+ * @param {Object} sampleText The sample text to be extended.
+ * @returns {Object} sampleText The extended sample text.
+ */
+ extendSampleText( sampleText ) {
+ const defaultSampleText = defaults.sampleText;
- return args;
-};
+ if ( isUndefined( sampleText ) ) {
+ return defaultSampleText;
+ }
-/**
- * Extend sample text config with defaults.
- *
- * @param {Object} sampleText The sample text to be extended.
- * @returns {Object} sampleText The extended sample text.
- */
-App.prototype.extendSampleText = function( sampleText ) {
- var defaultSampleText = defaults.sampleText;
+ for ( const key in sampleText ) {
+ if ( isUndefined( sampleText[ key ] ) ) {
+ sampleText[ key ] = defaultSampleText[ key ];
+ }
+ }
- if ( isUndefined( sampleText ) ) {
- return defaultSampleText;
+ return sampleText;
}
- for ( var key in sampleText ) {
- if ( isUndefined( sampleText[ key ] ) ) {
- sampleText[ key ] = defaultSampleText[ key ];
+ /**
+ * Registers a custom data callback.
+ *
+ * @param {Function} callback The callback to register.
+ *
+ * @returns {void}
+ */
+ registerCustomDataCallback( callback ) {
+ if ( ! this.callbacks.custom ) {
+ this.callbacks.custom = [];
}
- }
- return sampleText;
-};
-
-/**
- * Registers a custom data callback.
- *
- * @param {Function} callback The callback to register.
- *
- * @returns {void}
- */
-App.prototype.registerCustomDataCallback = function( callback ) {
- if ( ! this.callbacks.custom ) {
- this.callbacks.custom = [];
- }
-
- if ( isFunction( callback ) ) {
- this.callbacks.custom.push( callback );
+ if ( isFunction( callback ) ) {
+ this.callbacks.custom.push( callback );
+ }
}
-};
-/**
- * Retrieves data from the callbacks.getData and applies modification to store these in this.rawData.
- *
- * @returns {void}
- */
-App.prototype.getData = function() {
- this.rawData = this.callbacks.getData();
+ /**
+ * Retrieves data from the callbacks.getData and applies modification to store these in this.rawData.
+ *
+ * @returns {void}
+ */
+ getData() {
+ this.rawData = this.callbacks.getData();
- // Add the custom data to the raw data.
- if ( isArray( this.callbacks.custom ) ) {
- this.callbacks.custom.forEach( ( customCallback ) => {
- const customData = customCallback();
+ // Add the custom data to the raw data.
+ if ( isArray( this.callbacks.custom ) ) {
+ this.callbacks.custom.forEach( ( customCallback ) => {
+ const customData = customCallback();
- this.rawData = merge( this.rawData, customData );
- } );
- }
-
- if ( this.pluggable.loaded ) {
- this.rawData.metaTitle = this.pluggable._applyModifications( "data_page_title", this.rawData.metaTitle );
- this.rawData.meta = this.pluggable._applyModifications( "data_meta_desc", this.rawData.meta );
- }
+ this.rawData = merge( this.rawData, customData );
+ } );
+ }
- this.rawData.titleWidth = measureTextWidth( this.rawData.metaTitle );
+ if ( this.pluggable.loaded ) {
+ this.rawData.metaTitle = this.pluggable._applyModifications( "data_page_title", this.rawData.metaTitle );
+ this.rawData.meta = this.pluggable._applyModifications( "data_meta_desc", this.rawData.meta );
+ }
- this.rawData.locale = this.config.locale;
-};
+ this.rawData.titleWidth = measureTextWidth( this.rawData.metaTitle );
-/**
- * Refreshes the analyzer and output of the analyzer, is debounced for a better experience.
- *
- * @returns {void}
- */
-App.prototype.refresh = function() {
- // Until all plugins are loaded, do not trigger a refresh.
- if ( ! this.pluggable.loaded ) {
- return;
+ this.rawData.locale = this.config.locale;
}
- this._pureRefresh();
-};
-
-/**
- * Refreshes the analyzer and output of the analyzer, is throttled to prevent performance issues.
- *
- * @returns {void}
- *
- * @private
- */
-App.prototype._pureRefresh = function() {
- this.getData();
- this.runAnalyzer();
-};
+ /**
+ * Refreshes the analyzer and output of the analyzer, is debounced for a better experience.
+ *
+ * @returns {void}
+ */
+ refresh() {
+ // Until all plugins are loaded, do not trigger a refresh.
+ if ( ! this.pluggable.loaded ) {
+ return;
+ }
-/**
- * Initializes the assessor presenters for content and SEO.
- *
- * @returns {void}
- */
-App.prototype.initAssessorPresenters = function() {
- // Pass the assessor result through to the formatter
- if ( ! isUndefined( this.config.targets.output ) ) {
- this.seoAssessorPresenter = new AssessorPresenter( {
- targets: {
- output: this.config.targets.output,
- },
- assessor: this.seoAssessor,
- } );
+ this._pureRefresh();
}
- if ( ! isUndefined( this.config.targets.contentOutput ) ) {
- // Pass the assessor result through to the formatter
- this.contentAssessorPresenter = new AssessorPresenter( {
- targets: {
- output: this.config.targets.contentOutput,
- },
- assessor: this.contentAssessor,
- } );
+ /**
+ * Refreshes the analyzer and output of the analyzer, is throttled to prevent performance issues.
+ *
+ * @returns {void}
+ *
+ * @private
+ */
+ _pureRefresh() {
+ this.getData();
+ this.runAnalyzer();
}
-};
-/**
- * Sets the startTime timestamp.
- *
- * @returns {void}
- */
-App.prototype.startTime = function() {
- this.startTimestamp = new Date().getTime();
-};
-
-/**
- * Sets the endTime timestamp and compares with startTime to determine typeDelayincrease.
- *
- * @returns {void}
- */
-App.prototype.endTime = function() {
- this.endTimestamp = new Date().getTime();
- if ( this.endTimestamp - this.startTimestamp > this.config.typeDelay ) {
- if ( this.config.typeDelay < ( this.config.maxTypeDelay - this.config.typeDelayStep ) ) {
- this.config.typeDelay += this.config.typeDelayStep;
+ /**
+ * Initializes the assessor presenters for content and SEO.
+ *
+ * @returns {void}
+ */
+ initAssessorPresenters() {
+ // Pass the assessor result through to the formatter
+ if ( ! isUndefined( this.config.targets.output ) ) {
+ this.seoAssessorPresenter = new AssessorPresenter( {
+ targets: {
+ output: this.config.targets.output,
+ },
+ assessor: this.seoAssessor,
+ } );
}
- }
-};
-/**
- * Inits a new pageAnalyzer with the inputs from the getInput function and calls the scoreFormatter
- * to format outputs.
- *
- * @returns {void}
- */
-App.prototype.runAnalyzer = function() {
- if ( this.pluggable.loaded === false ) {
- return;
+ if ( ! isUndefined( this.config.targets.contentOutput ) ) {
+ // Pass the assessor result through to the formatter
+ this.contentAssessorPresenter = new AssessorPresenter( {
+ targets: {
+ output: this.config.targets.contentOutput,
+ },
+ assessor: this.contentAssessor,
+ } );
+ }
}
- if ( this.config.dynamicDelay ) {
- this.startTime();
+ /**
+ * Sets the startTime timestamp.
+ *
+ * @returns {void}
+ */
+ startTime() {
+ this.startTimestamp = new Date().getTime();
+ }
+
+ /**
+ * Sets the endTime timestamp and compares with startTime to determine typeDelayincrease.
+ *
+ * @returns {void}
+ */
+ endTime() {
+ this.endTimestamp = new Date().getTime();
+ if ( this.endTimestamp - this.startTimestamp > this.config.typeDelay ) {
+ if ( this.config.typeDelay < ( this.config.maxTypeDelay - this.config.typeDelayStep ) ) {
+ this.config.typeDelay += this.config.typeDelayStep;
+ }
+ }
}
- this.analyzerData = this.modifyData( this.rawData );
+ /**
+ * Inits a new pageAnalyzer with the inputs from the getInput function and calls the scoreFormatter
+ * to format outputs.
+ *
+ * @returns {void}
+ */
+ runAnalyzer() {
+ if ( this.pluggable.loaded === false ) {
+ return;
+ }
- let text = this.analyzerData.text;
+ if ( this.config.dynamicDelay ) {
+ this.startTime();
+ }
- // Insert HTML stripping code
- text = removeHtmlBlocks( text );
+ this.analyzerData = this.modifyData( this.rawData );
- const titleWidth = this.analyzerData.titleWidth;
- // Create a paper object for the Researcher
- this.paper = new Paper( text, {
- keyword: this.analyzerData.keyword,
- synonyms: this.analyzerData.synonyms,
- description: this.analyzerData.meta,
- slug: this.analyzerData.slug,
- title: this.analyzerData.metaTitle,
- titleWidth: titleWidth,
- locale: this.config.locale,
- permalink: this.analyzerData.permalink,
- } );
+ let text = this.analyzerData.text;
- this.config.researcher.setPaper( this.paper );
+ // Insert HTML stripping code
+ text = removeHtmlBlocks( text );
- this.runKeywordAnalysis();
+ const titleWidth = this.analyzerData.titleWidth;
- this.runContentAnalysis();
+ // Create a paper object for the Researcher
+ this.paper = new Paper( text, {
+ keyword: this.analyzerData.keyword,
+ synonyms: this.analyzerData.synonyms,
+ description: this.analyzerData.meta,
+ slug: this.analyzerData.slug,
+ title: this.analyzerData.metaTitle,
+ titleWidth: titleWidth,
+ locale: this.config.locale,
+ permalink: this.analyzerData.permalink,
+ } );
- this._renderAnalysisResults();
+ this.config.researcher.setPaper( this.paper );
- if ( this.config.dynamicDelay ) {
- this.endTime();
- }
-};
+ this.runKeywordAnalysis();
-/**
- * Runs the keyword analysis and calls the appropriate callbacks.
- *
- * @returns {void}
- */
-App.prototype.runKeywordAnalysis = function() {
- if ( this.config.keywordAnalysisActive ) {
- this.seoAssessor.assess( this.paper );
- const overallSeoScore = this.seoAssessor.calculateOverallScore();
+ this.runContentAnalysis();
- if ( ! isUndefined( this.callbacks.updatedKeywordsResults ) ) {
- this.callbacks.updatedKeywordsResults( this.seoAssessor.results, overallSeoScore );
- }
+ this._renderAnalysisResults();
- if ( ! isUndefined( this.callbacks.saveScores ) ) {
- this.callbacks.saveScores( overallSeoScore, this.seoAssessorPresenter );
+ if ( this.config.dynamicDelay ) {
+ this.endTime();
}
}
-};
-/**
- * Runs the content analysis and calls the appropriate callbacks.
- *
- * @returns {void}
- */
-App.prototype.runContentAnalysis = function() {
- if ( this.config.contentAnalysisActive ) {
- this.contentAssessor.assess( this.paper );
- const overallContentScore = this.contentAssessor.calculateOverallScore();
+ /**
+ * Runs the keyword analysis and calls the appropriate callbacks.
+ *
+ * @returns {void}
+ */
+ runKeywordAnalysis() {
+ if ( this.config.keywordAnalysisActive ) {
+ this.seoAssessor.assess( this.paper );
+ const overallSeoScore = this.seoAssessor.calculateOverallScore();
- if ( ! isUndefined( this.callbacks.updatedContentResults ) ) {
- this.callbacks.updatedContentResults( this.contentAssessor.results, overallContentScore );
- }
+ if ( ! isUndefined( this.callbacks.updatedKeywordsResults ) ) {
+ this.callbacks.updatedKeywordsResults( this.seoAssessor.results, overallSeoScore );
+ }
- if ( ! isUndefined( this.callbacks.saveContentScore ) ) {
- this.callbacks.saveContentScore( overallContentScore, this.contentAssessorPresenter );
+ if ( ! isUndefined( this.callbacks.saveScores ) ) {
+ this.callbacks.saveScores( overallSeoScore, this.seoAssessorPresenter );
+ }
}
}
-};
-/**
- * Modifies the data with plugins before it is sent to the analyzer.
- *
- * @param {Object} data The data to be modified.
- * @returns {Object} The data with the applied modifications.
- */
-App.prototype.modifyData = function( data ) {
- // Copy rawdata to lose object reference.
- data = JSON.parse( JSON.stringify( data ) );
-
- data.text = this.pluggable._applyModifications( "content", data.text );
- data.metaTitle = this.pluggable._applyModifications( "title", data.metaTitle );
-
- return data;
-};
-
-/**
- * Function to fire the analyzer when all plugins are loaded, removes the loading dialog.
- *
- * @returns {void}
- */
-App.prototype.pluginsLoaded = function() {
- this.removeLoadingDialog();
- this.refresh();
-};
+ /**
+ * Runs the content analysis and calls the appropriate callbacks.
+ *
+ * @returns {void}
+ */
+ runContentAnalysis() {
+ if ( this.config.contentAnalysisActive ) {
+ this.contentAssessor.assess( this.paper );
+ const overallContentScore = this.contentAssessor.calculateOverallScore();
-/**
- * Shows the loading dialog which shows the loading of the plugins.
- *
- * @returns {void}
- */
-App.prototype.showLoadingDialog = function() {
- var outputElement = document.getElementById( this.defaultOutputElement );
+ if ( ! isUndefined( this.callbacks.updatedContentResults ) ) {
+ this.callbacks.updatedContentResults( this.contentAssessor.results, overallContentScore );
+ }
- if ( this.defaultOutputElement !== "" && ! isEmpty( outputElement ) ) {
- var dialogDiv = document.createElement( "div" );
- dialogDiv.className = "YoastSEO_msg";
- dialogDiv.id = "YoastSEO-plugin-loading";
- document.getElementById( this.defaultOutputElement ).appendChild( dialogDiv );
+ if ( ! isUndefined( this.callbacks.saveContentScore ) ) {
+ this.callbacks.saveContentScore( overallContentScore, this.contentAssessorPresenter );
+ }
+ }
}
-};
-/**
- * Updates the loading plugins. Uses the plugins as arguments to show which plugins are loading.
- *
- * @param {Object} plugins The plugins to be parsed into the dialog.
- * @returns {void}
- */
-App.prototype.updateLoadingDialog = function( plugins ) {
- var outputElement = document.getElementById( this.defaultOutputElement );
-
- if ( this.defaultOutputElement === "" || isEmpty( outputElement ) ) {
- return;
+ /**
+ * Modifies the data with plugins before it is sent to the analyzer.
+ *
+ * @param {Object} data The data to be modified.
+ * @returns {Object} The data with the applied modifications.
+ */
+ modifyData( data ) {
+ // Copy rawdata to lose object reference.
+ data = JSON.parse( JSON.stringify( data ) );
+
+ data.text = this.pluggable._applyModifications( "content", data.text );
+ data.metaTitle = this.pluggable._applyModifications( "title", data.metaTitle );
+
+ return data;
+ }
+
+ /**
+ * Function to fire the analyzer when all plugins are loaded, removes the loading dialog.
+ *
+ * @returns {void}
+ */
+ pluginsLoaded() {
+ this.removeLoadingDialog();
+ this.refresh();
+ }
+
+ /**
+ * Shows the loading dialog which shows the loading of the plugins.
+ *
+ * @returns {void}
+ */
+ showLoadingDialog() {
+ const outputElement = document.getElementById( this.defaultOutputElement );
+
+ if ( this.defaultOutputElement !== "" && ! isEmpty( outputElement ) ) {
+ const dialogDiv = document.createElement( "div" );
+ dialogDiv.className = "YoastSEO_msg";
+ dialogDiv.id = "YoastSEO-plugin-loading";
+ document.getElementById( this.defaultOutputElement ).appendChild( dialogDiv );
+ }
}
- var dialog = document.getElementById( "YoastSEO-plugin-loading" );
- dialog.textContent = "";
+ /**
+ * Updates the loading plugins. Uses the plugins as arguments to show which plugins are loading.
+ *
+ * @param {Object} plugins The plugins to be parsed into the dialog.
+ * @returns {void}
+ */
+ updateLoadingDialog( plugins ) {
+ const outputElement = document.getElementById( this.defaultOutputElement );
- forEach( plugins, function( plugin, pluginName ) {
- dialog.innerHTML += "" + pluginName + "" + plugin.status + "
";
- } );
+ if ( this.defaultOutputElement === "" || isEmpty( outputElement ) ) {
+ return;
+ }
- dialog.innerHTML += "";
-};
+ const dialog = document.getElementById( "YoastSEO-plugin-loading" );
+ dialog.textContent = "";
-/**
- * Removes the pluging load dialog.
- *
- * @returns {void}
- */
-App.prototype.removeLoadingDialog = function() {
- var outputElement = document.getElementById( this.defaultOutputElement );
- var loadingDialog = document.getElementById( "YoastSEO-plugin-loading" );
+ forEach( plugins, function( plugin, pluginName ) {
+ dialog.innerHTML += "" + pluginName + "" + plugin.status + "
";
+ } );
- if ( ( this.defaultOutputElement !== "" && ! isEmpty( outputElement ) ) && ! isEmpty( loadingDialog ) ) {
- document.getElementById( this.defaultOutputElement ).removeChild( document.getElementById( "YoastSEO-plugin-loading" ) );
+ dialog.innerHTML += "";
}
-};
-// ***** PLUGGABLE PUBLIC DSL ***** //
+ /**
+ * Removes the pluging load dialog.
+ *
+ * @returns {void}
+ */
+ removeLoadingDialog() {
+ const outputElement = document.getElementById( this.defaultOutputElement );
+ const loadingDialog = document.getElementById( "YoastSEO-plugin-loading" );
-/**
- * Delegates to `YoastSEO.app.pluggable.registerPlugin`
- *
- * @param {string} pluginName The name of the plugin to be registered.
- * @param {object} options The options object.
- * @param {string} options.status The status of the plugin being registered. Can either be "loading" or "ready".
- * @returns {boolean} Whether or not it was successfully registered.
- */
-App.prototype.registerPlugin = function( pluginName, options ) {
- return this.pluggable._registerPlugin( pluginName, options );
-};
-
-/**
- * Delegates to `YoastSEO.app.pluggable.ready`
- *
- * @param {string} pluginName The name of the plugin to check.
- * @returns {boolean} Whether or not the plugin is ready.
- */
-App.prototype.pluginReady = function( pluginName ) {
- return this.pluggable._ready( pluginName );
-};
-
-/**
- * Delegates to `YoastSEO.app.pluggable.reloaded`
- *
- * @param {string} pluginName The name of the plugin to reload
- * @returns {boolean} Whether or not the plugin was reloaded.
- */
-App.prototype.pluginReloaded = function( pluginName ) {
- return this.pluggable._reloaded( pluginName );
-};
-
-/**
- * Delegates to `YoastSEO.app.pluggable.registerModification`.
- *
- * @param {string} modification The name of the filter
- * @param {function} callable The callable function
- * @param {string} pluginName The plugin that is registering the modification.
- * @param {number} [priority] Used to specify the order in which the callables associated with a particular filter are called.
- * Lower numbers correspond with earlier execution.
- *
- * @returns {boolean} Whether or not the modification was successfully registered.
- */
-App.prototype.registerModification = function( modification, callable, pluginName, priority ) {
- return this.pluggable._registerModification( modification, callable, pluginName, priority );
-};
-
-/**
- * Registers a custom assessment for use in the analyzer, this will result in a new line in the analyzer results.
- * The function needs to use the assessmentresult to return an result based on the contents of the page/posts.
- *
- * Score 0 results in a grey circle if it is not explicitly set by using setscore
- * Scores 0, 1, 2, 3 and 4 result in a red circle
- * Scores 6 and 7 result in a yellow circle
- * Scores 8, 9 and 10 result in a green circle
- *
- * @param {string} name Name of the test.
- * @param {function} assessment The assessment to run
- * @param {string} pluginName The plugin that is registering the test.
- * @returns {boolean} Whether or not the test was successfully registered.
- */
-App.prototype.registerAssessment = function( name, assessment, pluginName ) {
- if ( ! isUndefined( this.seoAssessor ) ) {
- return this.pluggable._registerAssessment( this.defaultSeoAssessor, name, assessment, pluginName ) &&
- this.pluggable._registerAssessment( this.cornerStoneSeoAssessor, name, assessment, pluginName );
+ if ( ( this.defaultOutputElement !== "" && ! isEmpty( outputElement ) ) && ! isEmpty( loadingDialog ) ) {
+ document.getElementById( this.defaultOutputElement ).removeChild( document.getElementById( "YoastSEO-plugin-loading" ) );
+ }
}
-};
-/**
- * Disables markers visually in the UI.
- *
- * @returns {void}
- */
-App.prototype.disableMarkers = function() {
- if ( ! isUndefined( this.seoAssessorPresenter ) ) {
- this.seoAssessorPresenter.disableMarker();
+ // ***** PLUGGABLE PUBLIC DSL ***** //
+ /**
+ * Delegates to `YoastSEO.app.pluggable.registerPlugin`
+ *
+ * @param {string} pluginName The name of the plugin to be registered.
+ * @param {object} options The options object.
+ * @param {string} options.status The status of the plugin being registered. Can either be "loading" or "ready".
+ * @returns {boolean} Whether or not it was successfully registered.
+ */
+ registerPlugin( pluginName, options ) {
+ return this.pluggable._registerPlugin( pluginName, options );
+ }
+
+ /**
+ * Delegates to `YoastSEO.app.pluggable.ready`
+ *
+ * @param {string} pluginName The name of the plugin to check.
+ * @returns {boolean} Whether or not the plugin is ready.
+ */
+ pluginReady( pluginName ) {
+ return this.pluggable._ready( pluginName );
+ }
+
+ /**
+ * Delegates to `YoastSEO.app.pluggable.reloaded`
+ *
+ * @param {string} pluginName The name of the plugin to reload
+ * @returns {boolean} Whether or not the plugin was reloaded.
+ */
+ pluginReloaded( pluginName ) {
+ return this.pluggable._reloaded( pluginName );
+ }
+
+ /**
+ * Delegates to `YoastSEO.app.pluggable.registerModification`.
+ *
+ * @param {string} modification The name of the filter
+ * @param {function} callable The callable function
+ * @param {string} pluginName The plugin that is registering the modification.
+ * @param {number} [priority] Used to specify the order in which the callables associated with a particular filter are called.
+ * Lower numbers correspond with earlier execution.
+ *
+ * @returns {boolean} Whether or not the modification was successfully registered.
+ */
+ registerModification( modification, callable, pluginName, priority ) {
+ return this.pluggable._registerModification( modification, callable, pluginName, priority );
+ }
+
+ /**
+ * Registers a custom assessment for use in the analyzer, this will result in a new line in the analyzer results.
+ * The function needs to use the assessmentresult to return an result based on the contents of the page/posts.
+ *
+ * Score 0 results in a grey circle if it is not explicitly set by using setscore
+ * Scores 0, 1, 2, 3 and 4 result in a red circle
+ * Scores 6 and 7 result in a yellow circle
+ * Scores 8, 9 and 10 result in a green circle
+ *
+ * @param {string} name Name of the test.
+ * @param {function} assessment The assessment to run
+ * @param {string} pluginName The plugin that is registering the test.
+ * @returns {boolean} Whether or not the test was successfully registered.
+ */
+ registerAssessment( name, assessment, pluginName ) {
+ if ( ! isUndefined( this.seoAssessor ) ) {
+ return this.pluggable._registerAssessment( this.defaultSeoAssessor, name, assessment, pluginName ) &&
+ this.pluggable._registerAssessment( this.cornerStoneSeoAssessor, name, assessment, pluginName );
+ }
}
- if ( ! isUndefined( this.contentAssessorPresenter ) ) {
- this.contentAssessorPresenter.disableMarker();
- }
-};
+ /**
+ * Disables markers visually in the UI.
+ *
+ * @returns {void}
+ */
+ disableMarkers() {
+ if ( ! isUndefined( this.seoAssessorPresenter ) ) {
+ this.seoAssessorPresenter.disableMarker();
+ }
-/**
- * Renders the content and keyword analysis results.
- *
- * @returns {void}
- */
-App.prototype._renderAnalysisResults = function() {
- if ( this.config.contentAnalysisActive && ! isUndefined( this.contentAssessorPresenter ) ) {
- this.contentAssessorPresenter.renderIndividualRatings();
- }
- if ( this.config.keywordAnalysisActive && ! isUndefined( this.seoAssessorPresenter ) ) {
- this.seoAssessorPresenter.setKeyword( this.paper.getKeyword() );
- this.seoAssessorPresenter.render();
+ if ( ! isUndefined( this.contentAssessorPresenter ) ) {
+ this.contentAssessorPresenter.disableMarker();
+ }
}
-};
-// Deprecated functions
-/**
- * The analyzeTimer calls the checkInputs function with a delay, so the function won't be executed
- * at every keystroke checks the reference object, so this function can be called from anywhere,
- * without problems with different scopes.
- *
- * @deprecated: 1.3 - Use this.refresh() instead.
- *
- * @returns {void}
- */
-App.prototype.analyzeTimer = function() {
- this.refresh();
-};
-
-/**
- * Registers a custom test for use in the analyzer, this will result in a new line in the analyzer results. The function
- * has to return a result based on the contents of the page/posts.
- *
- * The scoring object is a special object with definitions about how to translate a result from your analysis function
- * to a SEO score.
- *
- * Negative scores result in a red circle
- * Scores 1, 2, 3, 4 and 5 result in a orange circle
- * Scores 6 and 7 result in a yellow circle
- * Scores 8, 9 and 10 result in a red circle
- *
- * @returns {void}
- *
- * @deprecated since version 1.2
- */
-App.prototype.registerTest = function() {
- console.error( "This function is deprecated, please use registerAssessment" );
-};
+ /**
+ * Renders the content and keyword analysis results.
+ *
+ * @returns {void}
+ */
+ _renderAnalysisResults() {
+ if ( this.config.contentAnalysisActive && ! isUndefined( this.contentAssessorPresenter ) ) {
+ this.contentAssessorPresenter.renderIndividualRatings();
+ }
+ if ( this.config.keywordAnalysisActive && ! isUndefined( this.seoAssessorPresenter ) ) {
+ this.seoAssessorPresenter.setKeyword( this.paper.getKeyword() );
+ this.seoAssessorPresenter.render();
+ }
+ }
-/**
- * Switches between the cornerstone and default assessors.
- *
- * @deprecated 1.35.0 - Use changeAssessorOption instead.
- *
- * @param {boolean} useCornerStone True when cornerstone should be used.
- *
- * @returns {void}
- */
-App.prototype.switchAssessors = function( useCornerStone ) {
- // eslint-disable-next-line no-console
- console.warn( "Switch assessor is deprecated since YoastSEO.js version 1.35.0" );
+ // Deprecated functions
+ /**
+ * The analyzeTimer calls the checkInputs function with a delay, so the function won't be executed
+ * at every keystroke checks the reference object, so this function can be called from anywhere,
+ * without problems with different scopes.
+ *
+ * @deprecated: 1.3 - Use this.refresh() instead.
+ *
+ * @returns {void}
+ */
+ analyzeTimer() {
+ this.refresh();
+ }
+
+ /**
+ * Registers a custom test for use in the analyzer, this will result in a new line in the analyzer results. The function
+ * has to return a result based on the contents of the page/posts.
+ *
+ * The scoring object is a special object with definitions about how to translate a result from your analysis function
+ * to a SEO score.
+ *
+ * Negative scores result in a red circle
+ * Scores 1, 2, 3, 4 and 5 result in a orange circle
+ * Scores 6 and 7 result in a yellow circle
+ * Scores 8, 9 and 10 result in a red circle
+ *
+ * @returns {void}
+ *
+ * @deprecated since version 1.2
+ */
+ registerTest() {
+ console.error( "This function is deprecated, please use registerAssessment" );
+ }
+
+ /**
+ * Switches between the cornerstone and default assessors.
+ *
+ * @deprecated 1.35.0 - Use changeAssessorOption instead.
+ *
+ * @param {boolean} useCornerStone True when cornerstone should be used.
+ *
+ * @returns {void}
+ */
+ switchAssessors( useCornerStone ) {
+ // eslint-disable-next-line no-console
+ console.warn( "Switch assessor is deprecated since YoastSEO.js version 1.35.0" );
+
+ this.changeAssessorOptions( {
+ useCornerStone,
+ } );
+ }
+}
- this.changeAssessorOptions( {
- useCornerStone,
- } );
-};
export default App;
diff --git a/packages/yoastseo/src/languageProcessing/values/Clause.js b/packages/yoastseo/src/languageProcessing/values/Clause.js
index b25fbc4ba90..42510f37ade 100644
--- a/packages/yoastseo/src/languageProcessing/values/Clause.js
+++ b/packages/yoastseo/src/languageProcessing/values/Clause.js
@@ -97,7 +97,7 @@ class Clause {
*
* @returns {Clause} The parsed Clause.
*/
- parse( serialized ) {
+ static parse( serialized ) {
const clause = new Clause( serialized.clauseText, serialized.auxiliaries );
clause.setPassive( serialized.isPassive );
diff --git a/packages/yoastseo/src/languageProcessing/values/ProminentWord.js b/packages/yoastseo/src/languageProcessing/values/ProminentWord.js
index 49a994eb188..fc3cb373129 100644
--- a/packages/yoastseo/src/languageProcessing/values/ProminentWord.js
+++ b/packages/yoastseo/src/languageProcessing/values/ProminentWord.js
@@ -1,90 +1,95 @@
/**
* Represents a prominent word in the context of relevant words.
- *
- * @constructor
- *
- * @param {string} word The word.
- * @param {string} [stem] The stem / base form of the word, defaults to the word.
- * @param {number} [occurrences] The number of occurrences, defaults to 0.
- */
-function ProminentWord( word, stem, occurrences ) {
- this._word = word;
- this._stem = stem ? stem : word;
- this._occurrences = occurrences || 0;
-}
+*/
+class ProminentWord {
+ /**
+ * Constructs Prominent word object.
+ *
+ * @constructor
+ *
+ * @param {string} word The word.
+ * @param {string} [stem] The stem / base form of the word, defaults to the word.
+ * @param {number} [occurrences] The number of occurrences, defaults to 0.
+ */
+ constructor( word, stem, occurrences ) {
+ this._word = word;
+ this._stem = stem ? stem : word;
+ this._occurrences = occurrences || 0;
+ }
-/**
- * Sets the word.
- *
- * @param {string} word The word to set.
- *
- * @returns {void}.
- */
-ProminentWord.prototype.setWord = function( word ) {
- this._word = word;
-};
+ /**
+ * Sets the word.
+ *
+ * @param {string} word The word to set.
+ *
+ * @returns {void}.
+ */
+ setWord( word ) {
+ this._word = word;
+ }
-/**
- * Returns the word.
- *
- * @returns {string} The word.
- */
-ProminentWord.prototype.getWord = function() {
- return this._word;
-};
+ /**
+ * Returns the word.
+ *
+ * @returns {string} The word.
+ */
+ getWord() {
+ return this._word;
+ }
-/**
- * Returns the stem of the word.
- *
- * @returns {string} The stem.
- */
-ProminentWord.prototype.getStem = function() {
- return this._stem;
-};
+ /**
+ * Returns the stem of the word.
+ *
+ * @returns {string} The stem.
+ */
+ getStem() {
+ return this._stem;
+ }
-/**
- * Sets the number of occurrences to the word.
- *
- * @param {int} numberOfOccurrences The number of occurrences to set.
- *
- * @returns {void}.
- */
-ProminentWord.prototype.setOccurrences = function( numberOfOccurrences ) {
- this._occurrences = numberOfOccurrences;
-};
+ /**
+ * Sets the number of occurrences to the word.
+ *
+ * @param {int} numberOfOccurrences The number of occurrences to set.
+ *
+ * @returns {void}.
+ */
+ setOccurrences( numberOfOccurrences ) {
+ this._occurrences = numberOfOccurrences;
+ }
-/**
- * Returns the amount of occurrences of this word.
- *
- * @returns {number} The number of occurrences.
- */
-ProminentWord.prototype.getOccurrences = function() {
- return this._occurrences;
-};
+ /**
+ * Returns the amount of occurrences of this word.
+ *
+ * @returns {number} The number of occurrences.
+ */
+ getOccurrences() {
+ return this._occurrences;
+ }
-/**
- * Serializes the ProminentWord instance to an object.
- *
- * @returns {Object} The serialized ProminentWord.
- */
-ProminentWord.prototype.serialize = function() {
- return {
- _parseClass: "ProminentWord",
- word: this._word,
- stem: this._stem,
- occurrences: this._occurrences,
- };
-};
+ /**
+ * Serializes the ProminentWord instance to an object.
+ *
+ * @returns {Object} The serialized ProminentWord.
+ */
+ serialize() {
+ return {
+ _parseClass: "ProminentWord",
+ word: this._word,
+ stem: this._stem,
+ occurrences: this._occurrences,
+ };
+ }
-/**
- * Parses the object to a ProminentWord.
- *
- * @param {Object} serialized The serialized object.
- *
- * @returns {ProminentWord} The parsed ProminentWord.
- */
-ProminentWord.parse = function( serialized ) {
- return new ProminentWord( serialized.word, serialized.stem, serialized.occurrences );
-};
+ /**
+ * Parses the object to a ProminentWord.
+ *
+ * @param {Object} serialized The serialized object.
+ *
+ * @returns {ProminentWord} The parsed ProminentWord.
+ */
+ static parse( serialized ) {
+ return new ProminentWord( serialized.word, serialized.stem, serialized.occurrences );
+ }
+}
export default ProminentWord;
diff --git a/packages/yoastseo/src/languageProcessing/values/Sentence.js b/packages/yoastseo/src/languageProcessing/values/Sentence.js
index af164af4399..948fc5354f7 100644
--- a/packages/yoastseo/src/languageProcessing/values/Sentence.js
+++ b/packages/yoastseo/src/languageProcessing/values/Sentence.js
@@ -99,7 +99,7 @@ class Sentence {
*
* @returns {Sentence} The parsed Sentence.
*/
- parse( serialized ) {
+ static parse( serialized ) {
const sentence = new Sentence( serialized.sentenceText );
sentence.setClauses( serialized.clauses );
sentence.setPassive( serialized.isPassive );
diff --git a/packages/yoastseo/src/scoring/assessor.js b/packages/yoastseo/src/scoring/assessor.js
index 9d99662c64d..34f9e02041d 100644
--- a/packages/yoastseo/src/scoring/assessor.js
+++ b/packages/yoastseo/src/scoring/assessor.js
@@ -12,292 +12,292 @@ import { build } from "../parse/build";
const ScoreRating = 9;
/**
- * Creates the Assessor.
- *
- * @param {Researcher} researcher The researcher to use in the assessor.
- * @param {Object?} options The options for this assessor.
- * @param {Function} options.marker The marker to pass the list of marks to.
- *
- * @constructor
+ * The Assessor is a base class for all assessors.
*/
-const Assessor = function( researcher, options ) {
- this.type = "assessor";
- this.setResearcher( researcher );
- this._assessments = [];
-
- this._options = options || {};
-};
-
-/**
- * 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}
- */
-Assessor.prototype.setResearcher = function( researcher ) {
- if ( isUndefined( researcher ) ) {
- throw new MissingArgument( "The assessor requires a researcher." );
+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 );
+ this._assessments = [];
+
+ this._options = options || {};
}
- this._researcher = researcher;
-};
-/**
- * Gets all available assessments.
- * @returns {object} assessment
- */
-Assessor.prototype.getAvailableAssessments = function() {
- return this._assessments;
-};
-
-/**
- * Checks whether the Assessment is applicable.
- *
- * @param {Object} 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.
- */
-Assessor.prototype.isApplicable = function( assessment, paper, researcher ) {
- if ( assessment.hasOwnProperty( "isApplicable" ) || typeof assessment.isApplicable === "function" ) {
- return assessment.isApplicable( paper, researcher );
+ /**
+ * 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 ( isUndefined( researcher ) ) {
+ throw new MissingArgument( "The assessor requires a researcher." );
+ }
+ this._researcher = researcher;
}
- return true;
-};
-
-/**
- * Determines whether an assessment has a marker.
- *
- * @param {Object} assessment The assessment to check for.
- * @returns {boolean} Whether or not the assessment has a marker.
- */
-Assessor.prototype.hasMarker = function( assessment ) {
- return isFunction( this._options.marker ) && ( assessment.hasOwnProperty( "getMarks" ) || typeof assessment.getMarks === "function" );
-};
-
-/**
- * Returns the specific marker for this assessor.
- *
- * @returns {Function} The specific marker for this assessor.
- */
-Assessor.prototype.getSpecificMarker = function() {
- return this._options.marker;
-};
+ /**
+ * Gets all available assessments.
+ * @returns {object} assessment
+ */
+ getAvailableAssessments() {
+ return this._assessments;
+ }
-/**
- * Returns the paper that was most recently assessed.
- *
- * @returns {Paper} The paper that was most recently assessed.
- */
-Assessor.prototype.getPaper = function() {
- return this._lastPaper;
-};
+ /**
+ * Checks whether the Assessment is applicable.
+ *
+ * @param {Object} 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 ( assessment.hasOwnProperty( "isApplicable" ) || typeof assessment.isApplicable === "function" ) {
+ return assessment.isApplicable( paper, researcher );
+ }
-/**
- * Returns the marker for a given assessment, composes the specific marker with the assessment getMarks function.
- *
- * @param {Object} 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.
- */
-Assessor.prototype.getMarker = function( assessment, paper, researcher ) {
- const specificMarker = this._options.marker;
+ return true;
+ }
- return function() {
- let marks = assessment.getMarks( paper, researcher );
- marks = removeDuplicateMarks( marks );
+ /**
+ * Determines whether an assessment has a marker.
+ *
+ * @param {Object} assessment The assessment to check for.
+ * @returns {boolean} Whether or not the assessment has a marker.
+ */
+ hasMarker( assessment ) {
+ return isFunction( this._options.marker ) && ( assessment.hasOwnProperty( "getMarks" ) || typeof assessment.getMarks === "function" );
+ }
- specificMarker( paper, marks );
- };
-};
+ /**
+ * Returns the specific marker for this assessor.
+ *
+ * @returns {Function} The specific marker for this assessor.
+ */
+ getSpecificMarker() {
+ return this._options.marker;
+ }
-/**
- * Runs the researches defined in the task list or the default researches.
- *
- * @param {Paper} paper The paper to run assessments on.
- * @returns {void}
- */
-Assessor.prototype.assess = function( paper ) {
- this._researcher.setPaper( paper );
+ /**
+ * Returns the paper that was most recently assessed.
+ *
+ * @returns {Paper} The paper that was most recently assessed.
+ */
+ getPaper() {
+ return this._lastPaper;
+ }
- const languageProcessor = new LanguageProcessor( this._researcher );
- const shortcodes = paper._attributes && paper._attributes.shortcodes;
- paper.setTree( build( paper, languageProcessor, shortcodes ) );
+ /**
+ * Returns the marker for a given assessment, composes the specific marker with the assessment getMarks function.
+ *
+ * @param {Object} 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 = removeDuplicateMarks( marks );
+
+ specificMarker( paper, marks );
+ };
+ }
- let assessments = this.getAvailableAssessments();
- this.results = [];
+ /**
+ * 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 );
- assessments = filter( assessments, function( assessment ) {
- return this.isApplicable( assessment, paper, this._researcher );
- }.bind( this ) );
+ const languageProcessor = new LanguageProcessor( this._researcher );
+ const shortcodes = paper._attributes && paper._attributes.shortcodes;
+ paper.setTree( build( paper, languageProcessor, shortcodes ) );
- this.setHasMarkers( false );
- this.results = map( assessments, this.executeAssessment.bind( this, paper, this._researcher ) );
+ let assessments = this.getAvailableAssessments();
+ this.results = [];
- this._lastPaper = paper;
-};
+ assessments = filter( assessments, function( assessment ) {
+ return this.isApplicable( assessment, paper, this._researcher );
+ }.bind( this ) );
-/**
- * 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}
- */
-Assessor.prototype.setHasMarkers = function( hasMarkers ) {
- this._hasMarkers = hasMarkers;
-};
+ this.setHasMarkers( false );
+ this.results = map( assessments, this.executeAssessment.bind( this, paper, this._researcher ) );
-/**
- * Returns true when there are markers.
- *
- * @returns {boolean} Are there markers
- */
-Assessor.prototype.hasMarkers = function() {
- 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 {Object} assessment The assessment to execute.
- * @returns {AssessmentResult} The result of the assessment.
- */
-Assessor.prototype.executeAssessment = function( paper, researcher, assessment ) {
- let result;
-
- try {
- result = assessment.getResult( paper, researcher );
- result.setIdentifier( assessment.identifier );
+ this._lastPaper = paper;
+ }
- if ( result.hasMarks() ) {
- result.marks = assessment.getMarks( paper, researcher );
- result.marks = removeDuplicateMarks( result.marks );
- }
+ /**
+ * 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;
+ }
- if ( result.hasMarks() && this.hasMarker( assessment ) ) {
- this.setHasMarkers( true );
+ /**
+ * Returns true when there are markers.
+ *
+ * @returns {boolean} Are there markers
+ */
+ hasMarkers() {
+ return this._hasMarkers;
+ }
- result.setMarker( this.getMarker( assessment, paper, researcher ) );
+ /**
+ * 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 {Object} 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 = removeDuplicateMarks( result.marks );
+ }
+
+ if ( result.hasMarks() && this.hasMarker( assessment ) ) {
+ this.setHasMarkers( true );
+
+ result.setMarker( this.getMarker( assessment, paper, researcher ) );
+ }
+ } catch ( assessmentError ) {
+ showTrace( assessmentError );
+
+ result = new AssessmentResult();
+
+ result.setScore( -1 );
+ result.setText( sprintf(
+ /* translators: %1$s expands to the name of the assessment. */
+ __( "An error occurred in the '%1$s' assessment", "wordpress-seo" ),
+ assessment.identifier,
+ assessmentError
+ ) );
}
- } catch ( assessmentError ) {
- showTrace( assessmentError );
-
- result = new AssessmentResult();
-
- result.setScore( -1 );
- result.setText( sprintf(
- /* translators: %1$s expands to the name of the assessment. */
- __( "An error occurred in the '%1$s' assessment", "wordpress-seo" ),
- assessment.identifier,
- assessmentError
- ) );
+ return result;
}
- return result;
-};
-/**
- * Filters out all assessment results that have no score and no text.
- *
- * @returns {Array} The array with all the valid assessments.
- */
-Assessor.prototype.getValidResults = function() {
- return filter( this.results, function( result ) {
- return this.isValidResult( result );
- }.bind( this ) );
-};
-
-/**
- * Returns if an assessmentResult is valid.
- *
- * @param {object} assessmentResult The assessmentResult to validate.
- * @returns {boolean} whether or not the result is valid.
- */
-Assessor.prototype.isValidResult = function( assessmentResult ) {
- return assessmentResult.hasScore() && assessmentResult.hasText();
-};
+ /**
+ * Filters out all assessment results that have no score and no text.
+ *
+ * @returns {Array} The array with all the valid assessments.
+ */
+ getValidResults() {
+ return filter( this.results, function( result ) {
+ return this.isValidResult( result );
+ }.bind( this ) );
+ }
-/**
- * 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.
- */
-Assessor.prototype.calculateOverallScore = function() {
- const results = this.getValidResults();
+ /**
+ * Returns if an assessmentResult is valid.
+ *
+ * @param {object} assessmentResult The assessmentResult to validate.
+ * @returns {boolean} whether or not the result is valid.
+ */
+ isValidResult( assessmentResult ) {
+ return assessmentResult.hasScore() && assessmentResult.hasText();
+ }
- const totalScore = results.reduce( ( total, assessmentResult ) => total + assessmentResult.getScore(), 0 );
+ /**
+ * 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();
- return Math.round( totalScore / ( results.length * ScoreRating ) * 100 ) || 0;
-};
+ const totalScore = results.reduce( ( total, assessmentResult ) => total + assessmentResult.getScore(), 0 );
-/**
- * Register an assessment to add it to the internal assessments object.
- *
- * @param {string} name The name of the assessment.
- * @param {object} assessment The object containing function to run as an assessment and it's requirements.
- * @returns {boolean} Whether registering the assessment was successful.
- * @private
- */
-Assessor.prototype.addAssessment = function( name, assessment ) {
- if ( ! assessment.hasOwnProperty( "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 );
+ return Math.round( totalScore / ( results.length * ScoreRating ) * 100 ) || 0;
}
- this._assessments.push( assessment );
- return true;
-};
+ /**
+ * Register an assessment to add it to the internal assessments object.
+ *
+ * @param {string} name The name of the assessment.
+ * @param {object} 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 ( ! assessment.hasOwnProperty( "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 );
+ }
-/**
- * Remove a specific Assessment from the list of Assessments.
- *
- * @param {string} name The Assessment to remove from the list of assessments.
- * @returns {void}
- */
-Assessor.prototype.removeAssessment = function( name ) {
- const toDelete = findIndex( this._assessments, function( assessment ) {
- return assessment.hasOwnProperty( "identifier" ) && name === assessment.identifier;
- } );
+ this._assessments.push( assessment );
+ return true;
+ }
- if ( -1 !== toDelete ) {
- this._assessments.splice( toDelete, 1 );
+ /**
+ * Remove 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 = findIndex( this._assessments, function( assessment ) {
+ return assessment.hasOwnProperty( "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 {undefined|Assessment} The object if found, otherwise undefined.
- */
-Assessor.prototype.getAssessment = function( identifier ) {
- return find( this._assessments, function( assessment ) {
- return assessment.hasOwnProperty( "identifier" ) && identifier === assessment.identifier;
- } );
-};
+ /**
+ * Returns an assessment by identifier
+ *
+ * @param {string} identifier The identifier of the assessment.
+ * @returns {undefined|Assessment} The object if found, otherwise undefined.
+ */
+ getAssessment( identifier ) {
+ return find( this._assessments, function( assessment ) {
+ return assessment.hasOwnProperty( "identifier" ) && identifier === assessment.identifier;
+ } );
+ }
-/**
- * Checks which of the available assessments are applicable and returns an array with applicable assessments.
- *
- * @returns {Array} The array with applicable assessments.
- */
-Assessor.prototype.getApplicableAssessments = function() {
- const availableAssessments = this.getAvailableAssessments();
- return filter(
- availableAssessments,
- function( availableAssessment ) {
- return this.isApplicable( availableAssessment, this.getPaper(), this._researcher );
- }.bind( this )
- );
-};
+ /**
+ * Checks which of the available assessments are applicable and returns an array with applicable assessments.
+ *
+ * @returns {Array} The array with applicable assessments.
+ */
+ getApplicableAssessments() {
+ const availableAssessments = this.getAvailableAssessments();
+ return filter(
+ availableAssessments,
+ function( availableAssessment ) {
+ return this.isApplicable( availableAssessment, this.getPaper(), this._researcher );
+ }.bind( this )
+ );
+ }
+}
export default Assessor;
diff --git a/packages/yoastseo/src/scoring/contentAssessor.js b/packages/yoastseo/src/scoring/contentAssessor.js
index 0ff14bb18ae..ca7e1f3d974 100644
--- a/packages/yoastseo/src/scoring/contentAssessor.js
+++ b/packages/yoastseo/src/scoring/contentAssessor.js
@@ -1,3 +1,4 @@
+import { map, sum } from "lodash";
import Assessor from "./assessor.js";
import ParagraphTooLong from "./assessments/readability/ParagraphTooLongAssessment.js";
import SentenceLengthInText from "./assessments/readability/SentenceLengthInTextAssessment.js";
@@ -6,168 +7,156 @@ import TransitionWords from "./assessments/readability/TransitionWordsAssessment
import PassiveVoice from "./assessments/readability/PassiveVoiceAssessment.js";
import SentenceBeginnings from "./assessments/readability/SentenceBeginningsAssessment.js";
import TextPresence from "./assessments/readability/TextPresenceAssessment.js";
-
-/*
- Temporarily disabled:
- var sentenceLengthInDescription = require( "./assessments/sentenceLengthInDescriptionAssessment.js" );
- */
-
import scoreToRating from "./interpreters/scoreToRating";
-import { map, sum } from "lodash";
-
-/**
- * Creates the Assessor
- *
- * @param {object} researcher The researcher to use for the analysis.
- * @param {Object} options The options for this assessor.
- * @param {Object} options.marker The marker to pass the list of marks to.
- *
- * @constructor
- */
-const ContentAssessor = function( researcher, options = {} ) {
- Assessor.call( this, researcher, options );
- this.type = "contentAssessor";
- this._assessments = [
- new SubheadingDistributionTooLong(),
- new ParagraphTooLong(),
- new SentenceLengthInText(),
- new TransitionWords(),
- new PassiveVoice(),
- new TextPresence(),
- new SentenceBeginnings(),
- // Temporarily disabled: wordComplexity,
- ];
-};
-
-require( "util" ).inherits( ContentAssessor, Assessor );
-
/**
- * Calculates the weighted rating for languages that have all assessments based on a given rating.
- *
- * @param {number} rating The rating to be weighted.
- * @returns {number} The weighted rating.
+ * The ContentAssessor class is used for the readability analysis.
*/
-ContentAssessor.prototype.calculatePenaltyPointsFullSupport = function( rating ) {
- switch ( rating ) {
- case "bad":
- return 3;
- case "ok":
- return 2;
- default:
- case "good":
- return 0;
+export default class ContentAssessor extends Assessor {
+ /**
+ * Creates a new ContentAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "contentAssessor";
+
+ this._assessments = [
+ new SubheadingDistributionTooLong(),
+ new ParagraphTooLong(),
+ new SentenceLengthInText(),
+ new TransitionWords(),
+ new PassiveVoice(),
+ new TextPresence(),
+ new SentenceBeginnings(),
+ ];
}
-};
-/**
- * Calculates the weighted rating for languages that don't have all assessments based on a given rating.
- *
- * @param {number} rating The rating to be weighted.
- * @returns {number} The weighted rating.
- */
-ContentAssessor.prototype.calculatePenaltyPointsPartialSupport = function( rating ) {
- switch ( rating ) {
- case "bad":
- return 4;
- case "ok":
- return 2;
- default:
- case "good":
- return 0;
+ /**
+ * Calculates the weighted rating for languages that have all assessments based on a given rating.
+ *
+ * @param {string} rating The rating to be weighted.
+ * @returns {number} The weighted rating.
+ */
+ calculatePenaltyPointsFullSupport( rating ) {
+ switch ( rating ) {
+ case "bad":
+ return 3;
+ case "ok":
+ return 2;
+ default:
+ case "good":
+ return 0;
+ }
}
-};
-/**
- * Determines whether a language is fully supported. If a language supports 8 content assessments
- * it is fully supported
- *
- * @returns {boolean} True if fully supported.
- */
-ContentAssessor.prototype._allAssessmentsSupported = function() {
- const numberOfAssessments = this._assessments.length;
- const applicableAssessments = this.getApplicableAssessments();
- return applicableAssessments.length === numberOfAssessments;
-};
+ /**
+ * Calculates the weighted rating for languages that don't have all assessments based on a given rating.
+ *
+ * @param {string} rating The rating to be weighted.
+ * @returns {number} The weighted rating.
+ */
+ calculatePenaltyPointsPartialSupport( rating ) {
+ switch ( rating ) {
+ case "bad":
+ return 4;
+ case "ok":
+ return 2;
+ default:
+ case "good":
+ return 0;
+ }
+ }
-/**
- * Calculates the penalty points based on the assessment results.
- *
- * @returns {number} The total penalty points for the results.
- */
-ContentAssessor.prototype.calculatePenaltyPoints = function() {
- const results = this.getValidResults();
+ /**
+ * Determines whether a language is fully supported. If a language supports 8 content assessments
+ * it is fully supported
+ *
+ * @returns {boolean} True if fully supported.
+ */
+ _allAssessmentsSupported() {
+ const numberOfAssessments = this._assessments.length;
+ const applicableAssessments = this.getApplicableAssessments();
+ return applicableAssessments.length === numberOfAssessments;
+ }
- const penaltyPoints = map( results, function( result ) {
- const rating = scoreToRating( result.getScore() );
+ /**
+ * Calculates the penalty points based on the assessment results.
+ *
+ * @returns {number} The total penalty points for the results.
+ */
+ calculatePenaltyPoints() {
+ const results = this.getValidResults();
- if ( this._allAssessmentsSupported() ) {
- return this.calculatePenaltyPointsFullSupport( rating );
- }
+ const penaltyPoints = map( results, function( result ) {
+ const rating = scoreToRating( result.getScore() );
- return this.calculatePenaltyPointsPartialSupport( rating );
- }.bind( this ) );
+ if ( this._allAssessmentsSupported() ) {
+ return this.calculatePenaltyPointsFullSupport( rating );
+ }
- return sum( penaltyPoints );
-};
+ return this.calculatePenaltyPointsPartialSupport( rating );
+ }.bind( this ) );
-/**
- * Rates the penalty points
- *
- * @param {number} totalPenaltyPoints The amount of penalty points.
- * @returns {number} The score based on the amount of penalty points.
- *
- * @private
- */
-ContentAssessor.prototype._ratePenaltyPoints = function( totalPenaltyPoints ) {
- if ( this.getValidResults().length === 1 ) {
- // If we have only 1 result, we only have a "no content" result
- return 30;
+ return sum( penaltyPoints );
}
- if ( this._allAssessmentsSupported() ) {
- // Determine the total score based on the total penalty points.
- if ( totalPenaltyPoints > 6 ) {
- // A red indicator.
- return 30;
- }
-
- if ( totalPenaltyPoints > 4 ) {
- // An orange indicator.
- return 60;
- }
- } else {
- if ( totalPenaltyPoints > 4 ) {
- // A red indicator.
+ /**
+ * Rates the penalty points
+ *
+ * @param {number} totalPenaltyPoints The amount of penalty points.
+ * @returns {number} The score based on the amount of penalty points.
+ *
+ * @private
+ */
+ _ratePenaltyPoints( totalPenaltyPoints ) {
+ if ( this.getValidResults().length === 1 ) {
+ // If we have only 1 result, we only have a "no content" result
return 30;
}
- if ( totalPenaltyPoints > 2 ) {
- // An orange indicator.
- return 60;
+ if ( this._allAssessmentsSupported() ) {
+ // Determine the total score based on the total penalty points.
+ if ( totalPenaltyPoints > 6 ) {
+ // A red indicator.
+ return 30;
+ }
+
+ if ( totalPenaltyPoints > 4 ) {
+ // An orange indicator.
+ return 60;
+ }
+ } else {
+ if ( totalPenaltyPoints > 4 ) {
+ // A red indicator.
+ return 30;
+ }
+
+ if ( totalPenaltyPoints > 2 ) {
+ // An orange indicator.
+ return 60;
+ }
}
+ // A green indicator.
+ return 90;
}
- // A green indicator.
- return 90;
-};
-/**
- * Calculates the overall score based on the assessment results.
- *
- * @returns {number} The overall score.
- */
-ContentAssessor.prototype.calculateOverallScore = function() {
- const results = this.getValidResults();
-
- // If you have no content, you have a red indicator.
- if ( results.length === 0 ) {
- return 30;
- }
+ /**
+ * Calculates the overall score based on the assessment results.
+ *
+ * @returns {number} The overall score.
+ */
+ calculateOverallScore() {
+ const results = this.getValidResults();
- const totalPenaltyPoints = this.calculatePenaltyPoints();
-
- return this._ratePenaltyPoints( totalPenaltyPoints );
-};
+ // If you have no content, you have a red indicator.
+ if ( results.length === 0 ) {
+ return 30;
+ }
-export default ContentAssessor;
+ const totalPenaltyPoints = this.calculatePenaltyPoints();
+ return this._ratePenaltyPoints( totalPenaltyPoints );
+ }
+}
diff --git a/packages/yoastseo/src/scoring/cornerstone/contentAssessor.js b/packages/yoastseo/src/scoring/cornerstone/contentAssessor.js
index cb920a0f9c3..5911f39f77a 100644
--- a/packages/yoastseo/src/scoring/cornerstone/contentAssessor.js
+++ b/packages/yoastseo/src/scoring/cornerstone/contentAssessor.js
@@ -1,4 +1,3 @@
-import Assessor from "../assessor.js";
import ContentAssessor from "../contentAssessor";
import ParagraphTooLong from "../assessments/readability/ParagraphTooLongAssessment.js";
import SentenceLengthInText from "../assessments/readability/SentenceLengthInTextAssessment.js";
@@ -8,50 +7,38 @@ import PassiveVoice from "../assessments/readability/PassiveVoiceAssessment.js";
import SentenceBeginnings from "../assessments/readability/SentenceBeginningsAssessment.js";
import TextPresence from "../assessments/readability/TextPresenceAssessment.js";
-/*
- Temporarily disabled:
-
- var sentenceLengthInDescription = require( "./assessments/readability/sentenceLengthInDescriptionAssessment.js" );
- */
-
/**
- * Creates the Assessor
- *
- * @param {object} researcher The researcher used for the analysis.
- * @param {Object} options The options for this assessor.
- * @param {Object} options.marker The marker to pass the list of marks to.
- *
- * @constructor
+ * The CornerStoneContentAssessor class is used for the readability analysis on cornerstone content.
*/
-const CornerStoneContentAssessor = function( researcher, options = {} ) {
- Assessor.call( this, researcher, options );
- this.type = "cornerstoneContentAssessor";
-
- this._assessments = [
- new SubheadingDistributionTooLong( {
- parameters: {
- slightlyTooMany: 250,
- farTooMany: 300,
- recommendedMaximumLength: 250,
- },
- applicableIfTextLongerThan: 250,
- cornerstoneContent: true,
- } ),
- new ParagraphTooLong(),
- new SentenceLengthInText( {
- slightlyTooMany: 20,
- farTooMany: 25,
- }, true ),
- new TransitionWords(),
- new PassiveVoice(),
- new TextPresence(),
- new SentenceBeginnings(),
- // Temporarily disabled: wordComplexity,
- ];
-};
-
-require( "util" ).inherits( CornerStoneContentAssessor, ContentAssessor );
-
-
-export default CornerStoneContentAssessor;
-
+export default class CornerStoneContentAssessor extends ContentAssessor {
+ /**
+ * Creates a new CornerStoneContentAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "cornerstoneContentAssessor";
+
+ this._assessments = [
+ new SubheadingDistributionTooLong( {
+ parameters: {
+ slightlyTooMany: 250,
+ farTooMany: 300,
+ recommendedMaximumLength: 250,
+ },
+ applicableIfTextLongerThan: 250,
+ cornerstoneContent: true,
+ } ),
+ new ParagraphTooLong(),
+ new SentenceLengthInText( {
+ slightlyTooMany: 20,
+ farTooMany: 25,
+ }, true ),
+ new TransitionWords(),
+ new PassiveVoice(),
+ new TextPresence(),
+ new SentenceBeginnings(),
+ ];
+ }
+}
diff --git a/packages/yoastseo/src/scoring/cornerstone/relatedKeywordAssessor.js b/packages/yoastseo/src/scoring/cornerstone/relatedKeywordAssessor.js
index ca825e19bae..32010063806 100644
--- a/packages/yoastseo/src/scoring/cornerstone/relatedKeywordAssessor.js
+++ b/packages/yoastseo/src/scoring/cornerstone/relatedKeywordAssessor.js
@@ -1,6 +1,4 @@
-import { inherits } from "util";
import Assessor from "../assessor.js";
-
import IntroductionKeyword from "../assessments/seo/IntroductionKeywordAssessment.js";
import KeyphraseLength from "../assessments/seo/KeyphraseLengthAssessment.js";
import KeyphraseDensityAssessment from "../assessments/seo/KeywordDensityAssessment.js";
@@ -10,35 +8,32 @@ import FunctionWordsInKeyphrase from "../assessments/seo/FunctionWordsInKeyphras
import ImageKeyphrase from "../assessments/seo/KeyphraseInImageTextAssessment";
/**
- * Creates the Assessor
- *
- * @param {Researcher} researcher The researcher used for the analysis.
- * @param {Object?} options The options for this assessor.
- * @param {Function} options.marker The marker to pass the list of marks to.
- *
- * @constructor
+ * The relatedKeywordAssessor class is used for the related keyword analysis for cornerstone content.
*/
-const relatedKeywordAssessor = function( researcher, options ) {
- Assessor.call( this, researcher, options );
- this.type = "cornerstoneRelatedKeywordAssessor";
-
- this._assessments = [
- new IntroductionKeyword(),
- new KeyphraseLength( { isRelatedKeyphrase: true } ),
- new KeyphraseDensityAssessment(),
- new MetaDescriptionKeyword(),
- new TextCompetingLinks(),
- new FunctionWordsInKeyphrase(),
- new ImageKeyphrase( {
- scores: {
- withAltNonKeyword: 3,
- withAlt: 3,
- noAlt: 3,
- },
- } ),
- ];
-};
-
-inherits( relatedKeywordAssessor, Assessor );
+export default class relatedKeywordAssessor extends Assessor {
+ /**
+ * Creates a new relatedKeywordAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "cornerstoneRelatedKeywordAssessor";
-export default relatedKeywordAssessor;
+ this._assessments = [
+ new IntroductionKeyword(),
+ new KeyphraseLength( { isRelatedKeyphrase: true } ),
+ new KeyphraseDensityAssessment(),
+ new MetaDescriptionKeyword(),
+ new TextCompetingLinks(),
+ new FunctionWordsInKeyphrase(),
+ new ImageKeyphrase( {
+ scores: {
+ withAltNonKeyword: 3,
+ withAlt: 3,
+ noAlt: 3,
+ },
+ } ),
+ ];
+ }
+}
diff --git a/packages/yoastseo/src/scoring/cornerstone/seoAssessor.js b/packages/yoastseo/src/scoring/cornerstone/seoAssessor.js
index d816dcd6c51..c7ef48ed42c 100644
--- a/packages/yoastseo/src/scoring/cornerstone/seoAssessor.js
+++ b/packages/yoastseo/src/scoring/cornerstone/seoAssessor.js
@@ -1,98 +1,45 @@
-import { inherits } from "util";
-
-import IntroductionKeywordAssessment from "../assessments/seo/IntroductionKeywordAssessment";
-import KeyphraseLengthAssessment from "../assessments/seo/KeyphraseLengthAssessment";
-import KeyphraseDensityAssessment from "../assessments/seo/KeywordDensityAssessment";
-import MetaDescriptionKeywordAssessment from "../assessments/seo/MetaDescriptionKeywordAssessment";
-import TextCompetingLinksAssessment from "../assessments/seo/TextCompetingLinksAssessment";
-import InternalLinksAssessment from "../assessments/seo/InternalLinksAssessment";
-import KeyphraseInSEOTitleAssessment from "../assessments/seo/KeyphraseInSEOTitleAssessment";
-import SlugKeywordAssessment from "../assessments/seo/UrlKeywordAssessment";
-import Assessor from "../assessor";
import SEOAssessor from "../seoAssessor";
import MetaDescriptionLength from "../assessments/seo/MetaDescriptionLengthAssessment";
-import SubheadingsKeyword from "../assessments/seo/SubHeadingsKeywordAssessment";
import ImageKeyphrase from "../assessments/seo/KeyphraseInImageTextAssessment";
-import ImageCount from "../assessments/seo/ImageCountAssessment";
import TextLength from "../assessments/seo/TextLengthAssessment";
import OutboundLinks from "../assessments/seo/OutboundLinksAssessment";
import TitleWidth from "../assessments/seo/PageTitleWidthAssessment";
-import FunctionWordsInKeyphrase from "../assessments/seo/FunctionWordsInKeyphraseAssessment";
-import SingleH1Assessment from "../assessments/seo/SingleH1Assessment";
+import SlugKeywordAssessment from "../assessments/seo/UrlKeywordAssessment";
/**
- * Creates the Assessor
- *
- * @param {Researcher} researcher The researcher used for the analysis.
- * @param {Object?} options The options for this assessor.
- * @param {Function} options.marker The marker to pass the list of marks to.
- *
- * @constructor
+ * The CornerstoneSEOAssessor class is used for the SEO analysis for cornerstone content.
*/
-const CornerstoneSEOAssessor = function( researcher, options ) {
- Assessor.call( this, researcher, options );
- this.type = "cornerstoneSEOAssessor";
+export default class CornerstoneSEOAssessor extends SEOAssessor {
+ /**
+ * Creates a new CornerstoneSEOAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "cornerstoneSEOAssessor";
- this._assessments = [
- new IntroductionKeywordAssessment(),
- new KeyphraseLengthAssessment(),
- new KeyphraseDensityAssessment(),
- new MetaDescriptionKeywordAssessment(),
- new MetaDescriptionLength( {
- scores: {
- tooLong: 3,
- tooShort: 3,
- },
- } ),
- new SubheadingsKeyword(),
- new TextCompetingLinksAssessment(),
- new ImageKeyphrase( {
- scores: {
- withAltNonKeyword: 3,
- withAlt: 3,
- noAlt: 3,
- },
- } ),
- new ImageCount(),
- new TextLength( {
+ this.addAssessment( "metaDescriptionLength", new MetaDescriptionLength( {
+ scores: { tooLong: 3, tooShort: 3 },
+ } ) );
+ this.addAssessment( "imageKeyphrase", new ImageKeyphrase( {
+ scores: { withAltNonKeyword: 3, withAlt: 3, noAlt: 3 },
+ } ) );
+ this.addAssessment( "textLength", new TextLength( {
recommendedMinimum: 900,
slightlyBelowMinimum: 400,
belowMinimum: 300,
-
- scores: {
- belowMinimum: -20,
- farBelowMinimum: -20,
- },
-
+ scores: { belowMinimum: -20, farBelowMinimum: -20 },
cornerstoneContent: true,
- } ),
- new OutboundLinks( {
- scores: {
- noLinks: 3,
- },
- } ),
- new KeyphraseInSEOTitleAssessment(),
- new InternalLinksAssessment(),
- new TitleWidth(
- {
- scores: {
- widthTooShort: 9,
- },
- },
- true
- ),
- new SlugKeywordAssessment(
- {
- scores: {
- okay: 3,
- },
- }
- ),
- new FunctionWordsInKeyphrase(),
- new SingleH1Assessment(),
- ];
-};
-
-inherits( CornerstoneSEOAssessor, SEOAssessor );
-
-export default CornerstoneSEOAssessor;
+ } ) );
+ this.addAssessment( "externalLinks", new OutboundLinks( {
+ scores: { noLinks: 3 },
+ } ) );
+ this.addAssessment( "titleWidth", new TitleWidth( {
+ scores: { widthTooShort: 9 },
+ }, true ) );
+ this.addAssessment( "slugKeyword", new SlugKeywordAssessment( {
+ scores: { okay: 3 },
+ } ) );
+ }
+}
diff --git a/packages/yoastseo/src/scoring/inclusiveLanguageAssessor.js b/packages/yoastseo/src/scoring/inclusiveLanguageAssessor.js
index 5338b69eac8..aa37c643e1b 100644
--- a/packages/yoastseo/src/scoring/inclusiveLanguageAssessor.js
+++ b/packages/yoastseo/src/scoring/inclusiveLanguageAssessor.js
@@ -13,14 +13,13 @@ const defaultOptions = {
};
/**
- * An assessor that assesses a paper for potentially non-inclusive language.
+ * The InclusiveLanguageAssessor assesses a paper for potentially non-inclusive language.
*/
-class InclusiveLanguageAssessor extends Assessor {
+export default class InclusiveLanguageAssessor extends Assessor {
/**
- * Creates a new inclusive language assessor.
- *
- * @param {Researcher} researcher The researcher to use.
- * @param {Object} [options] The assessor options.
+ * Creates a new InclusiveLanguageAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
*/
constructor( researcher, options = {} ) {
super( researcher, options );
@@ -63,5 +62,3 @@ class InclusiveLanguageAssessor extends Assessor {
return 90;
}
}
-
-export default InclusiveLanguageAssessor;
diff --git a/packages/yoastseo/src/scoring/relatedKeywordAssessor.js b/packages/yoastseo/src/scoring/relatedKeywordAssessor.js
index ddf792d9abf..6f2c21647cf 100644
--- a/packages/yoastseo/src/scoring/relatedKeywordAssessor.js
+++ b/packages/yoastseo/src/scoring/relatedKeywordAssessor.js
@@ -1,38 +1,33 @@
-import { inherits } from "util";
-
import Assessor from "./assessor.js";
import IntroductionKeyword from "./assessments/seo/IntroductionKeywordAssessment.js";
import KeyphraseLength from "./assessments/seo/KeyphraseLengthAssessment.js";
import KeyphraseDensityAssessment from "./assessments/seo/KeywordDensityAssessment.js";
import MetaDescriptionKeyword from "./assessments/seo/MetaDescriptionKeywordAssessment.js";
-import ImageKeyphrase from "./assessments/seo/KeyphraseInImageTextAssessment";
import TextCompetingLinks from "./assessments/seo/TextCompetingLinksAssessment.js";
import FunctionWordsInKeyphrase from "./assessments/seo/FunctionWordsInKeyphraseAssessment";
+import ImageKeyphrase from "./assessments/seo/KeyphraseInImageTextAssessment";
/**
- * Creates the Assessor
- *
- * @param {Researcher} researcher The researcher to use for the analysis.
- * @param {Object?} options The options for this assessor.
- * @param {Function} options.marker The marker to pass the list of marks to.
- *
- * @constructor
+ * The relatedKeywordAssessor class is used for the related keyword analysis.
*/
-const relatedKeywordAssessor = function( researcher, options ) {
- Assessor.call( this, researcher, options );
- this.type = "relatedKeywordAssessor";
-
- this._assessments = [
- new IntroductionKeyword(),
- new KeyphraseLength( { isRelatedKeyphrase: true } ),
- new KeyphraseDensityAssessment(),
- new MetaDescriptionKeyword(),
- new TextCompetingLinks(),
- new FunctionWordsInKeyphrase(),
- new ImageKeyphrase(),
- ];
-};
-
-inherits( relatedKeywordAssessor, Assessor );
+export default class relatedKeywordAssessor extends Assessor {
+ /**
+ * Creates a new relatedKeywordAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "relatedKeywordAssessor";
-export default relatedKeywordAssessor;
+ this._assessments = [
+ new IntroductionKeyword(),
+ new KeyphraseLength( { isRelatedKeyphrase: true } ),
+ new KeyphraseDensityAssessment(),
+ new MetaDescriptionKeyword(),
+ new TextCompetingLinks(),
+ new FunctionWordsInKeyphrase(),
+ new ImageKeyphrase(),
+ ];
+ }
+}
diff --git a/packages/yoastseo/src/scoring/relatedKeywordTaxonomyAssessor.js b/packages/yoastseo/src/scoring/relatedKeywordTaxonomyAssessor.js
index bb75942b814..854d0d6e838 100644
--- a/packages/yoastseo/src/scoring/relatedKeywordTaxonomyAssessor.js
+++ b/packages/yoastseo/src/scoring/relatedKeywordTaxonomyAssessor.js
@@ -1,34 +1,30 @@
-import { inherits } from "util";
-
+import Assessor from "./assessor";
import IntroductionKeywordAssessment from "./assessments/seo/IntroductionKeywordAssessment";
import KeyphraseLengthAssessment from "./assessments/seo/KeyphraseLengthAssessment";
import KeyphraseDensityAssessment from "./assessments/seo/KeywordDensityAssessment";
import MetaDescriptionKeywordAssessment from "./assessments/seo/MetaDescriptionKeywordAssessment";
-import Assessor from "./assessor";
import FunctionWordsInKeyphrase from "./assessments/seo/FunctionWordsInKeyphraseAssessment";
/**
- * Creates the Assessor used for taxonomy pages.
- *
- * @param {Researcher} researcher The researcher to use for the analysis.
- * @param {Object?} options The options for this assessor.
- *
- * @constructor
+ * The RelatedKeywordTaxonomyAssessor class is used for the related keyword analysis on terms.
*/
-const RelatedKeywordTaxonomyAssessor = function( researcher, options ) {
- Assessor.call( this, researcher, options );
- this.type = "relatedKeywordsTaxonomyAssessor";
-
- this._assessments = [
- new IntroductionKeywordAssessment(),
- new KeyphraseLengthAssessment( { isRelatedKeyphrase: true } ),
- new KeyphraseDensityAssessment(),
- new MetaDescriptionKeywordAssessment(),
- // Text Images assessment here.
- new FunctionWordsInKeyphrase(),
- ];
-};
-
-inherits( RelatedKeywordTaxonomyAssessor, Assessor );
+export default class RelatedKeywordTaxonomyAssessor extends Assessor {
+ /**
+ * Creates a new RelatedKeywordTaxonomyAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "relatedKeywordsTaxonomyAssessor";
-export default RelatedKeywordTaxonomyAssessor;
+ this._assessments = [
+ new IntroductionKeywordAssessment(),
+ new KeyphraseLengthAssessment( { isRelatedKeyphrase: true } ),
+ new KeyphraseDensityAssessment(),
+ new MetaDescriptionKeywordAssessment(),
+ // Text Images assessment here.
+ new FunctionWordsInKeyphrase(),
+ ];
+ }
+}
diff --git a/packages/yoastseo/src/scoring/renderers/AssessorPresenter.js b/packages/yoastseo/src/scoring/renderers/AssessorPresenter.js
index ecc022c7d2b..6f91f3d6e1d 100644
--- a/packages/yoastseo/src/scoring/renderers/AssessorPresenter.js
+++ b/packages/yoastseo/src/scoring/renderers/AssessorPresenter.js
@@ -3,353 +3,358 @@ import scoreToRating from "../interpreters/scoreToRating.js";
import createConfig from "../../config/presenter.js";
/**
- * Constructs the AssessorPresenter.
- *
- * @param {Object} args A list of arguments to use in the presenter.
- * @param {object} args.targets The HTML elements to render the output to.
- * @param {string} args.targets.output The HTML element to render the individual ratings out to.
- * @param {string} args.targets.overall The HTML element to render the overall rating out to.
- * @param {string} args.keyword The keyword to use for checking, when calculating the overall rating.
- * @param {SEOAssessor} args.assessor The Assessor object to retrieve assessment results from.
- *
- * @constructor
+ * Represents the AssessorPresenter.
*/
-var AssessorPresenter = function( args ) {
- this.keyword = args.keyword;
- this.assessor = args.assessor;
- this.output = args.targets.output;
- this.overall = args.targets.overall || "overallScore";
- this.presenterConfig = createConfig();
+class AssessorPresenter {
+ /**
+ * Constructs the AssessorPresenter.
+ *
+ * @param {Object} args A list of arguments to use in the presenter.
+ * @param {object} args.targets The HTML elements to render the output to.
+ * @param {string} args.targets.output The HTML element to render the individual ratings out to.
+ * @param {string} args.targets.overall The HTML element to render the overall rating out to.
+ * @param {string} args.keyword The keyword to use for checking, when calculating the overall rating.
+ * @param {SEOAssessor} args.assessor The Assessor object to retrieve assessment results from.
+ *
+ * @constructor
+ */
+ constructor( args ) {
+ this.keyword = args.keyword;
+ this.assessor = args.assessor;
+ this.output = args.targets.output;
+ this.overall = args.targets.overall || "overallScore";
+ this.presenterConfig = createConfig();
+
+ this._disableMarkerButtons = false;
- this._disableMarkerButtons = false;
-
- this._activeMarker = false;
-};
-
-/**
- * Sets the keyword.
- *
- * @param {string} keyword The keyword to use.
- * @returns {void}
- */
-AssessorPresenter.prototype.setKeyword = function( keyword ) {
- this.keyword = keyword;
-};
-
-/**
- * Checks whether a specific property exists in the presenter configuration.
- *
- * @param {string} property The property name to search for.
- * @returns {boolean} Whether or not the property exists.
- */
-AssessorPresenter.prototype.configHasProperty = function( property ) {
- return this.presenterConfig.hasOwnProperty( property );
-};
-
-/**
- * Gets a fully formatted indicator object that can be used.
- *
- * @param {string} rating The rating to use.
- * @returns {Object} An object containing the class, the screen reader text, and the full text.
- */
-AssessorPresenter.prototype.getIndicator = function( rating ) {
- return {
- className: this.getIndicatorColorClass( rating ),
- screenReaderText: this.getIndicatorScreenReaderText( rating ),
- fullText: this.getIndicatorFullText( rating ),
- screenReaderReadabilityText: this.getIndicatorScreenReaderReadabilityText( rating ),
- };
-};
+ this._activeMarker = false;
+ }
-/**
- * Gets the indicator color class from the presenter configuration, if it exists.
- *
- * @param {string} rating The rating to check against the config.
- * @returns {string} String containing the CSS class to be used.
- */
-AssessorPresenter.prototype.getIndicatorColorClass = function( rating ) {
- if ( ! this.configHasProperty( rating ) ) {
- return "";
+ /**
+ * Sets the keyword.
+ *
+ * @param {string} keyword The keyword to use.
+ * @returns {void}
+ */
+ setKeyword( keyword ) {
+ this.keyword = keyword;
}
- return this.presenterConfig[ rating ].className;
-};
+ /**
+ * Checks whether a specific property exists in the presenter configuration.
+ *
+ * @param {string} property The property name to search for.
+ * @returns {boolean} Whether or not the property exists.
+ */
+ configHasProperty( property ) {
+ return this.presenterConfig.hasOwnProperty( property );
+ }
-/**
- * Get the indicator screen reader text from the presenter configuration, if it exists.
- *
- * @param {string} rating The rating to check against the config.
- * @returns {string} Translated string containing the screen reader text to be used.
- */
-AssessorPresenter.prototype.getIndicatorScreenReaderText = function( rating ) {
- if ( ! this.configHasProperty( rating ) ) {
- return "";
+ /**
+ * Gets a fully formatted indicator object that can be used.
+ *
+ * @param {string} rating The rating to use.
+ * @returns {Object} An object containing the class, the screen reader text, and the full text.
+ */
+ getIndicator( rating ) {
+ return {
+ className: this.getIndicatorColorClass( rating ),
+ screenReaderText: this.getIndicatorScreenReaderText( rating ),
+ fullText: this.getIndicatorFullText( rating ),
+ screenReaderReadabilityText: this.getIndicatorScreenReaderReadabilityText( rating ),
+ };
}
- return this.presenterConfig[ rating ].screenReaderText;
-};
+ /**
+ * Gets the indicator color class from the presenter configuration, if it exists.
+ *
+ * @param {string} rating The rating to check against the config.
+ * @returns {string} String containing the CSS class to be used.
+ */
+ getIndicatorColorClass( rating ) {
+ if ( ! this.configHasProperty( rating ) ) {
+ return "";
+ }
-/**
- * Get the indicator screen reader readability text from the presenter configuration, if it exists.
- *
- * @param {string} rating The rating to check against the config.
- * @returns {string} Translated string containing the screen reader readability text to be used.
- */
-AssessorPresenter.prototype.getIndicatorScreenReaderReadabilityText = function( rating ) {
- if ( ! this.configHasProperty( rating ) ) {
- return "";
+ return this.presenterConfig[ rating ].className;
}
- return this.presenterConfig[ rating ].screenReaderReadabilityText;
-};
+ /**
+ * Get the indicator screen reader text from the presenter configuration, if it exists.
+ *
+ * @param {string} rating The rating to check against the config.
+ * @returns {string} Translated string containing the screen reader text to be used.
+ */
+ getIndicatorScreenReaderText( rating ) {
+ if ( ! this.configHasProperty( rating ) ) {
+ return "";
+ }
-/**
- * Get the indicator full text from the presenter configuration, if it exists.
- *
- * @param {string} rating The rating to check against the config.
- * @returns {string} Translated string containing the full text to be used.
- */
-AssessorPresenter.prototype.getIndicatorFullText = function( rating ) {
- if ( ! this.configHasProperty( rating ) ) {
- return "";
+ return this.presenterConfig[ rating ].screenReaderText;
}
- return this.presenterConfig[ rating ].fullText;
-};
+ /**
+ * Get the indicator screen reader readability text from the presenter configuration, if it exists.
+ *
+ * @param {string} rating The rating to check against the config.
+ * @returns {string} Translated string containing the screen reader readability text to be used.
+ */
+ getIndicatorScreenReaderReadabilityText( rating ) {
+ if ( ! this.configHasProperty( rating ) ) {
+ return "";
+ }
-/**
- * Adds a rating based on the numeric score.
- *
- * @param {Object} result Object based on the Assessment result. Requires a score property to work.
- * @returns {Object} The Assessment result object with the rating added.
- */
-AssessorPresenter.prototype.resultToRating = function( result ) {
- if ( ! isObject( result ) ) {
- return "";
+ return this.presenterConfig[ rating ].screenReaderReadabilityText;
}
- result.rating = scoreToRating( result.score );
-
- return result;
-};
+ /**
+ * Get the indicator full text from the presenter configuration, if it exists.
+ *
+ * @param {string} rating The rating to check against the config.
+ * @returns {string} Translated string containing the full text to be used.
+ */
+ getIndicatorFullText( rating ) {
+ if ( ! this.configHasProperty( rating ) ) {
+ return "";
+ }
-/**
- * Takes the individual assessment results, sorts and rates them.
- *
- * @returns {Object} Object containing all the individual ratings.
- */
-AssessorPresenter.prototype.getIndividualRatings = function() {
- var ratings = {};
- var validResults = this.sort( this.assessor.getValidResults() );
- var mappedResults = validResults.map( this.resultToRating );
+ return this.presenterConfig[ rating ].fullText;
+ }
- forEach( mappedResults, function( item, key ) {
- ratings[ key ] = this.addRating( item );
- }.bind( this ) );
+ /**
+ * Adds a rating based on the numeric score.
+ *
+ * @param {Object} result Object based on the Assessment result. Requires a score property to work.
+ * @returns {Object} The Assessment result object with the rating added.
+ */
+ resultToRating( result ) {
+ if ( ! isObject( result ) ) {
+ return "";
+ }
- return ratings;
-};
+ result.rating = scoreToRating( result.score );
-/**
- * Excludes items from the results that are present in the exclude array.
- *
- * @param {Array} results Array containing the items to filter through.
- * @param {Array} exclude Array of results to exclude.
- * @returns {Array} Array containing items that remain after exclusion.
- */
-AssessorPresenter.prototype.excludeFromResults = function( results, exclude ) {
- return difference( results, exclude );
-};
+ return result;
+ }
-/**
- * Sorts results based on their score property and always places items considered to be unsortable, at the top.
- *
- * @param {Array} results Array containing the results that need to be sorted.
- * @returns {Array} Array containing the sorted results.
- */
-AssessorPresenter.prototype.sort = function( results ) {
- var unsortables = this.getUndefinedScores( results );
- var sortables = this.excludeFromResults( results, unsortables );
+ /**
+ * Takes the individual assessment results, sorts and rates them.
+ *
+ * @returns {Object} Object containing all the individual ratings.
+ */
+ getIndividualRatings() {
+ const ratings = {};
+ const validResults = this.sort( this.assessor.getValidResults() );
+ const mappedResults = validResults.map( this.resultToRating );
+
+ forEach( mappedResults, function( item, key ) {
+ ratings[ key ] = this.addRating( item );
+ }.bind( this ) );
+
+ return ratings;
+ }
- sortables.sort( function( a, b ) {
- return a.score - b.score;
- } );
+ /**
+ * Excludes items from the results that are present in the `exclude` array.
+ *
+ * @param {Array} results Array containing the items to filter through.
+ * @param {Array} exclude Array of results to exclude.
+ * @returns {Array} Array containing items that remain after exclusion.
+ */
+ excludeFromResults( results, exclude ) {
+ return difference( results, exclude );
+ }
- return unsortables.concat( sortables );
-};
+ /**
+ * Sorts results based on their score property and always places items considered to be non-sortable, at the top.
+ *
+ * @param {Array} results Array containing the results that need to be sorted.
+ * @returns {Array} Array containing the sorted results.
+ */
+ sort( results ) {
+ const nonSortables = this.getUndefinedScores( results );
+ const sortables = this.excludeFromResults( results, nonSortables );
+
+ sortables.sort( function( a, b ) {
+ return a.score - b.score;
+ } );
+
+ return nonSortables.concat( sortables );
+ }
-/**
- * Returns a subset of results that have an undefined score or a score set to zero.
- *
- * @param {Array} results The results to filter through.
- * @returns {Array} A subset of results containing items with an undefined score or where the score is zero.
- */
-AssessorPresenter.prototype.getUndefinedScores = function( results ) {
- return results.filter( function( result ) {
- return isUndefined( result.score ) || result.score === 0;
- } );
-};
+ /**
+ * Returns a subset of results that have an undefined score or a score set to zero.
+ *
+ * @param {Array} results The results to filter through.
+ * @returns {Array} A subset of results containing items with an undefined score or where the score is zero.
+ */
+ getUndefinedScores( results ) {
+ return results.filter( function( result ) {
+ return isUndefined( result.score ) || result.score === 0;
+ } );
+ }
-/**
- * Creates a rating object based on the item that is being passed.
- *
- * @param {AssessmentResult} item The item to check and create a rating object from.
- * @returns {Object} Object containing a parsed item, including a colored indicator.
- */
-AssessorPresenter.prototype.addRating = function( item ) {
- var indicator = this.getIndicator( item.rating );
- indicator.text = item.text;
- indicator.identifier = item.getIdentifier();
+ /**
+ * Creates a rating object based on the item that is being passed.
+ *
+ * @param {Object} item The item to check and create a rating object from.
+ * @returns {Object} Object containing a parsed item, including a colored indicator.
+ */
+ addRating( item ) {
+ const indicator = this.getIndicator( item.rating );
+ indicator.text = item.text;
+ indicator.identifier = item.getIdentifier();
+
+ if ( item.hasMarker() ) {
+ indicator.marker = item.getMarker();
+ }
- if ( item.hasMarker() ) {
- indicator.marker = item.getMarker();
+ return indicator;
}
- return indicator;
-};
+ /**
+ * Calculates the overall rating score based on the overall score.
+ *
+ * @param {Number} overallScore The overall score to use in the calculation.
+ * @returns {Object} The rating based on the score.
+ */
+ getOverallRating( overallScore ) {
+ let rating = 0;
+
+ if ( this.keyword === "" ) {
+ return this.resultToRating( { score: rating } );
+ }
-/**
- * Calculates the overall rating score based on the overall score.
- *
- * @param {Number} overallScore The overall score to use in the calculation.
- * @returns {Object} The rating based on the score.
- */
-AssessorPresenter.prototype.getOverallRating = function( overallScore ) {
- var rating = 0;
+ if ( isNumber( overallScore ) ) {
+ rating = ( overallScore / 10 );
+ }
- if ( this.keyword === "" ) {
return this.resultToRating( { score: rating } );
}
- if ( isNumber( overallScore ) ) {
- rating = ( overallScore / 10 );
- }
+ /**
+ * Mark with a given marker. This will set the active marker to the correct value.
+ *
+ * @param {string} identifier The identifier for the assessment/marker.
+ * @param {Function} marker The marker function.
+ * @returns {void}
+ */
+ markAssessment( identifier, marker ) {
+ if ( this._activeMarker === identifier ) {
+ this.removeAllMarks();
+ this._activeMarker = false;
+ } else {
+ marker();
+ this._activeMarker = identifier;
+ }
- return this.resultToRating( { score: rating } );
-};
+ this.render();
+ }
-/**
- * Mark with a given marker. This will set the active marker to the correct value.
- *
- * @param {string} identifier The identifier for the assessment/marker.
- * @param {Function} marker The marker function.
- * @returns {void}
- */
-AssessorPresenter.prototype.markAssessment = function( identifier, marker ) {
- if ( this._activeMarker === identifier ) {
- this.removeAllMarks();
+ /**
+ * Disables the currently active marker in the UI.
+ *
+ * @returns {void}
+ */
+ disableMarker() {
this._activeMarker = false;
- } else {
- marker();
- this._activeMarker = identifier;
+ this.render();
}
- this.render();
-};
+ /**
+ * Disables the marker buttons.
+ *
+ * @returns {void}
+ */
+ disableMarkerButtons() {
+ this._disableMarkerButtons = true;
+ this.render();
+ }
-/**
- * Disables the currently active marker in the UI.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.disableMarker = function() {
- this._activeMarker = false;
- this.render();
-};
+ /**
+ * Enables the marker buttons.
+ *
+ * @returns {void}
+ */
+ enableMarkerButtons() {
+ this._disableMarkerButtons = false;
+ this.render();
+ }
-/**
- * Disables the marker buttons.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.disableMarkerButtons = function() {
- this._disableMarkerButtons = true;
- this.render();
-};
+ /**
+ * Adds an event listener for the marker button
+ *
+ * @param {string} identifier The identifier for the assessment the marker belongs to.
+ * @param {Function} marker The marker function that can mark the assessment in the text.
+ * @returns {void}
+ */
+ addMarkerEventHandler( identifier, marker ) {
+ const container = document.getElementById( this.output );
+ const markButton = container.getElementsByClassName( "js-assessment-results__mark-" + identifier )[ 0 ];
+
+ markButton.addEventListener( "click", this.markAssessment.bind( this, identifier, marker ) );
+ }
-/**
- * Enables the marker buttons.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.enableMarkerButtons = function() {
- this._disableMarkerButtons = false;
- this.render();
-};
+ /**
+ * Renders out both the individual and the overall ratings.
+ *
+ * @returns {void}
+ */
+ render() {
+ this.renderIndividualRatings();
+ this.renderOverallRating();
+ }
-/**
- * Adds an event listener for the marker button
- *
- * @param {string} identifier The identifier for the assessment the marker belongs to.
- * @param {Function} marker The marker function that can mark the assessment in the text.
- * @returns {void}
- */
-AssessorPresenter.prototype.addMarkerEventHandler = function( identifier, marker ) {
- var container = document.getElementById( this.output );
- var markButton = container.getElementsByClassName( "js-assessment-results__mark-" + identifier )[ 0 ];
+ /**
+ * Adds event handlers to the mark buttons
+ *
+ * @param {Object} scores The list of rendered scores.
+ *
+ * @returns {void}
+ */
+ bindMarkButtons( scores ) {
+ // Make sure the button works for every score with a marker.
+ forEach( scores, function( score ) {
+ if ( score.hasOwnProperty( "marker" ) ) {
+ this.addMarkerEventHandler( score.identifier, score.marker );
+ }
+ }.bind( this ) );
+ }
- markButton.addEventListener( "click", this.markAssessment.bind( this, identifier, marker ) );
-};
+ /**
+ * Removes all marks currently on the text
+ *
+ * @returns {void}
+ */
+ removeAllMarks() {
+ const marker = this.assessor.getSpecificMarker();
-/**
- * Renders out both the individual and the overall ratings.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.render = function() {
- this.renderIndividualRatings();
- this.renderOverallRating();
-};
+ marker( this.assessor.getPaper(), [] );
+ }
-/**
- * Adds event handlers to the mark buttons
- *
- * @param {Array} scores The list of rendered scores.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.bindMarkButtons = function( scores ) {
- // Make sure the button works for every score with a marker.
- forEach( scores, function( score ) {
- if ( score.hasOwnProperty( "marker" ) ) {
- this.addMarkerEventHandler( score.identifier, score.marker );
+ /**
+ * Renders out the individual ratings.
+ * Here, this method is set to noop. In `post-scraper.js` and `term-scraper.js` where this method is called, it is overridden with noop as well.
+ *
+ * @returns {void}
+ */
+ renderIndividualRatings() {}
+
+ /**
+ * Renders out the overall rating.
+ *
+ * @returns {void}
+ */
+ renderOverallRating() {
+ const overallRating = this.getOverallRating( this.assessor.calculateOverallScore() );
+ const overallRatingElement = document.getElementById( this.overall );
+
+ if ( ! overallRatingElement ) {
+ return;
}
- }.bind( this ) );
-};
-/**
- * Removes all marks currently on the text
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.removeAllMarks = function() {
- var marker = this.assessor.getSpecificMarker();
-
- marker( this.assessor.getPaper(), [] );
-};
-
-/**
- * Renders out the individual ratings.
- * Here, this method is set to noop. In `post-scraper.js` and `term-scraper.js` where this method is called, it is overridden with noop as well.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.renderIndividualRatings = function() {};
-
-/**
- * Renders out the overall rating.
- *
- * @returns {void}
- */
-AssessorPresenter.prototype.renderOverallRating = function() {
- var overallRating = this.getOverallRating( this.assessor.calculateOverallScore() );
- var overallRatingElement = document.getElementById( this.overall );
-
- if ( ! overallRatingElement ) {
- return;
+ overallRatingElement.className = "overallScore " + this.getIndicatorColorClass( overallRating.rating );
}
-
- overallRatingElement.className = "overallScore " + this.getIndicatorColorClass( overallRating.rating );
-};
+}
export default AssessorPresenter;
diff --git a/packages/yoastseo/src/scoring/seoAssessor.js b/packages/yoastseo/src/scoring/seoAssessor.js
index ae228ea591d..aaa0a1bdb44 100644
--- a/packages/yoastseo/src/scoring/seoAssessor.js
+++ b/packages/yoastseo/src/scoring/seoAssessor.js
@@ -1,5 +1,4 @@
-import { inherits } from "util";
-
+import Assessor from "./assessor";
import IntroductionKeywordAssessment from "./assessments/seo/IntroductionKeywordAssessment";
import KeyphraseLengthAssessment from "./assessments/seo/KeyphraseLengthAssessment";
import KeyphraseDensityAssessment from "./assessments/seo/KeywordDensityAssessment";
@@ -8,7 +7,6 @@ import TextCompetingLinksAssessment from "./assessments/seo/TextCompetingLinksAs
import InternalLinksAssessment from "./assessments/seo/InternalLinksAssessment";
import KeyphraseInSEOTitleAssessment from "./assessments/seo/KeyphraseInSEOTitleAssessment";
import SlugKeywordAssessment from "./assessments/seo/UrlKeywordAssessment";
-import Assessor from "./assessor";
import MetaDescriptionLength from "./assessments/seo/MetaDescriptionLengthAssessment";
import SubheadingsKeyword from "./assessments/seo/SubHeadingsKeywordAssessment";
import ImageKeyphrase from "./assessments/seo/KeyphraseInImageTextAssessment";
@@ -20,43 +18,40 @@ import FunctionWordsInKeyphrase from "./assessments/seo/FunctionWordsInKeyphrase
import SingleH1Assessment from "./assessments/seo/SingleH1Assessment";
/**
- * Creates the Assessor
- *
- * @param {Researcher} researcher The researcher to use for the analysis.
- * @param {Object?} options The options for this assessor.
- * @param {Function} options.marker The marker to pass the list of marks to.
- *
- * @constructor
+ * The SEOAssessor class is used for the general SEO analysis.
*/
-const SEOAssessor = function( researcher, options ) {
- Assessor.call( this, researcher, options );
- this.type = "SEOAssessor";
-
- this._assessments = [
- new IntroductionKeywordAssessment(),
- new KeyphraseLengthAssessment(),
- new KeyphraseDensityAssessment(),
- new MetaDescriptionKeywordAssessment(),
- new MetaDescriptionLength(),
- new SubheadingsKeyword(),
- new TextCompetingLinksAssessment(),
- new ImageKeyphrase(),
- new ImageCount(),
- new TextLength(),
- new OutboundLinks(),
- new KeyphraseInSEOTitleAssessment(),
- new InternalLinksAssessment(),
- new TitleWidth( {
- scores: {
- widthTooShort: 9,
- },
- }, true ),
- new SlugKeywordAssessment(),
- new FunctionWordsInKeyphrase(),
- new SingleH1Assessment(),
- ];
-};
-
-inherits( SEOAssessor, Assessor );
+export default class SEOAssessor extends Assessor {
+ /**
+ * Creates a new SEOAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "SEOAssessor";
-export default SEOAssessor;
+ this._assessments = [
+ new IntroductionKeywordAssessment(),
+ new KeyphraseLengthAssessment(),
+ new KeyphraseDensityAssessment(),
+ new MetaDescriptionKeywordAssessment(),
+ new MetaDescriptionLength(),
+ new SubheadingsKeyword(),
+ new TextCompetingLinksAssessment(),
+ new ImageKeyphrase(),
+ new ImageCount(),
+ new TextLength(),
+ new OutboundLinks(),
+ new KeyphraseInSEOTitleAssessment(),
+ new InternalLinksAssessment(),
+ new TitleWidth( {
+ scores: {
+ widthTooShort: 9,
+ },
+ }, true ),
+ new SlugKeywordAssessment(),
+ new FunctionWordsInKeyphrase(),
+ new SingleH1Assessment(),
+ ];
+ }
+}
diff --git a/packages/yoastseo/src/scoring/storePostsAndPages/cornerstone/contentAssessor.js b/packages/yoastseo/src/scoring/storePostsAndPages/cornerstone/contentAssessor.js
index 38a746c4beb..5d7188f87cb 100644
--- a/packages/yoastseo/src/scoring/storePostsAndPages/cornerstone/contentAssessor.js
+++ b/packages/yoastseo/src/scoring/storePostsAndPages/cornerstone/contentAssessor.js
@@ -1,6 +1,4 @@
-import { inherits } from "util";
-
-import { Assessor, ContentAssessor, assessments, helpers } from "yoastseo";
+import { ContentAssessor, assessments, helpers } from "yoastseo";
const { createAnchorOpeningTag } = helpers;
const {
@@ -27,53 +25,59 @@ const {
*
* @constructor
*/
-const StorePostsAndPagesCornerstoneContentAssessor = function( researcher, options = {} ) {
- Assessor.call( this, researcher, options );
- this.type = "storePostsAndPagesCornerstoneContentAssessor";
-
- this._assessments = [
+class StorePostsAndPagesCornerstoneContentAssessor extends ContentAssessor {
+ /**
+ * Creates a new assessor.
+ *
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} options The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
- new SubheadingDistributionTooLongAssessment( {
- parameters: {
- slightlyTooMany: 250,
- farTooMany: 300,
- recommendedMaximumLength: 250,
- },
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify68" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify69" ),
- cornerstoneContent: true,
- } ),
- new ParagraphTooLongAssessment( {
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify66" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify67" ),
- } ),
- new SentenceLengthInTextAssessment( {
- slightlyTooMany: 20,
- farTooMany: 25,
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify48" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify49" ),
- }, true ),
- new TransitionWordsAssessment( {
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify44" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify45" ),
- } ),
- new PassiveVoiceAssessment( {
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify42" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify43" ),
- } ),
- new TextPresenceAssessment( {
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify56" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify57" ),
- } ),
- new SentenceBeginningsAssessment( {
- urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify5" ),
- urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify65" ),
- } ),
- ];
-};
+ this.type = "storePostsAndPagesCornerstoneContentAssessor";
-inherits( StorePostsAndPagesCornerstoneContentAssessor, ContentAssessor );
+ this._assessments = [
+ new SubheadingDistributionTooLongAssessment( {
+ parameters: {
+ slightlyTooMany: 250,
+ farTooMany: 300,
+ recommendedMaximumLength: 250,
+ },
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify68" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify69" ),
+ cornerstoneContent: true,
+ } ),
+ new ParagraphTooLongAssessment( {
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify66" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify67" ),
+ } ),
+ new SentenceLengthInTextAssessment( {
+ slightlyTooMany: 20,
+ farTooMany: 25,
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify48" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify49" ),
+ }, true ),
+ new TransitionWordsAssessment( {
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify44" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify45" ),
+ } ),
+ new PassiveVoiceAssessment( {
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify42" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify43" ),
+ } ),
+ new TextPresenceAssessment( {
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify56" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify57" ),
+ } ),
+ new SentenceBeginningsAssessment( {
+ urlTitle: createAnchorOpeningTag( "https://yoa.st/shopify5" ),
+ urlCallToAction: createAnchorOpeningTag( "https://yoa.st/shopify65" ),
+ } ),
+ ];
+ }
+}
export default StorePostsAndPagesCornerstoneContentAssessor;
diff --git a/packages/yoastseo/src/scoring/taxonomyAssessor.js b/packages/yoastseo/src/scoring/taxonomyAssessor.js
index 8801a98728e..ec184305850 100644
--- a/packages/yoastseo/src/scoring/taxonomyAssessor.js
+++ b/packages/yoastseo/src/scoring/taxonomyAssessor.js
@@ -1,12 +1,10 @@
-import { inherits } from "util";
-
+import Assessor from "./assessor";
import IntroductionKeywordAssessment from "./assessments/seo/IntroductionKeywordAssessment";
import KeyphraseLengthAssessment from "./assessments/seo/KeyphraseLengthAssessment";
import KeyphraseDensityAssessment from "./assessments/seo/KeywordDensityAssessment";
import MetaDescriptionKeywordAssessment from "./assessments/seo/MetaDescriptionKeywordAssessment";
import KeyphraseInSEOTitleAssessment from "./assessments/seo/KeyphraseInSEOTitleAssessment";
import SlugKeywordAssessment from "./assessments/seo/UrlKeywordAssessment";
-import Assessor from "./assessor";
import MetaDescriptionLengthAssessment from "./assessments/seo/MetaDescriptionLengthAssessment";
import TextLengthAssessment from "./assessments/seo/TextLengthAssessment";
import PageTitleWidthAssessment from "./assessments/seo/PageTitleWidthAssessment";
@@ -19,7 +17,7 @@ import { createAnchorOpeningTag } from "../helpers";
*
* @returns {TextLengthAssessment} The text length assessment (with taxonomy configuration) to use.
*/
-export const getTextLengthAssessment = function() {
+export const getTextLengthAssessment = () => {
// Export so it can be used in tests.
return new TextLengthAssessment( {
recommendedMinimum: 30,
@@ -32,37 +30,36 @@ export const getTextLengthAssessment = function() {
};
/**
- * Creates the Assessor used for taxonomy pages.
- *
- * @param {Researcher} researcher The researcher used for the analysis.
- * @param {Object?} options The options for this assessor.
- * @constructor
+ * The TaxonomyAssessor is used for the assessment of terms.
*/
-const TaxonomyAssessor = function( researcher, options ) {
- Assessor.call( this, researcher, options );
- this.type = "taxonomyAssessor";
-
- this._assessments = [
- new IntroductionKeywordAssessment(),
- new KeyphraseLengthAssessment(),
- new KeyphraseDensityAssessment(),
- new MetaDescriptionKeywordAssessment(),
- new MetaDescriptionLengthAssessment(),
- getTextLengthAssessment(),
- new KeyphraseInSEOTitleAssessment(),
- new PageTitleWidthAssessment(
- {
- scores: {
- widthTooShort: 9,
- },
- }, true
- ),
- new SlugKeywordAssessment(),
- new FunctionWordsInKeyphrase(),
- new SingleH1Assessment(),
- ];
-};
-
-inherits( TaxonomyAssessor, Assessor );
+export default class TaxonomyAssessor extends Assessor {
+ /**
+ * Creates a new TaxonomyAssessor instance.
+ * @param {Researcher} researcher The researcher to use.
+ * @param {Object} [options] The assessor options.
+ */
+ constructor( researcher, options ) {
+ super( researcher, options );
+ this.type = "taxonomyAssessor";
-export default TaxonomyAssessor;
+ this._assessments = [
+ new IntroductionKeywordAssessment(),
+ new KeyphraseLengthAssessment(),
+ new KeyphraseDensityAssessment(),
+ new MetaDescriptionKeywordAssessment(),
+ new MetaDescriptionLengthAssessment(),
+ getTextLengthAssessment(),
+ new KeyphraseInSEOTitleAssessment(),
+ new PageTitleWidthAssessment(
+ {
+ scores: {
+ widthTooShort: 9,
+ },
+ }, true
+ ),
+ new SlugKeywordAssessment(),
+ new FunctionWordsInKeyphrase(),
+ new SingleH1Assessment(),
+ ];
+ }
+}
diff --git a/packages/yoastseo/src/values/AssessmentResult.js b/packages/yoastseo/src/values/AssessmentResult.js
index 07f394e66a5..d6332f6e896 100644
--- a/packages/yoastseo/src/values/AssessmentResult.js
+++ b/packages/yoastseo/src/values/AssessmentResult.js
@@ -7,308 +7,309 @@ import Mark from "./Mark";
*
* @returns {Array} A list of empty marks.
*/
-var emptyMarker = function() {
- return [];
-};
+const emptyMarker = () => [];
/**
- * Construct the AssessmentResult value object.
- *
- * @param {Object} [values] The values for this assessment result.
- *
- * @constructor
+ * Represents the assessment result.
*/
-var AssessmentResult = function( values ) {
- this._hasScore = false;
- this._identifier = "";
- this._hasMarks = false;
- this._hasJumps = false;
- this._hasEditFieldName = false;
- this._marker = emptyMarker;
- this._hasBetaBadge = false;
- this.score = 0;
- this.text = "";
- this.marks = [];
- this.editFieldName = "";
-
- if ( isUndefined( values ) ) {
- values = {};
+class AssessmentResult {
+ /**
+ * Constructs the AssessmentResult value object.
+ *
+ * @param {Object} [values] The values for this assessment result.
+ */
+ constructor( values ) {
+ this._hasScore = false;
+ this._identifier = "";
+ this._hasMarks = false;
+ this._hasJumps = false;
+ this._hasEditFieldName = false;
+ this._marker = emptyMarker;
+ this._hasBetaBadge = false;
+ this.score = 0;
+ this.text = "";
+ this.marks = [];
+ this.editFieldName = "";
+
+ if ( isUndefined( values ) ) {
+ values = {};
+ }
+
+ if ( ! isUndefined( values.score ) ) {
+ this.setScore( values.score );
+ }
+
+ if ( ! isUndefined( values.text ) ) {
+ this.setText( values.text );
+ }
+
+ if ( ! isUndefined( values.marks ) ) {
+ this.setMarks( values.marks );
+ }
+
+ if ( ! isUndefined( values._hasBetaBadge ) ) {
+ this.setHasBetaBadge( values._hasBetaBadge );
+ }
+
+ if ( ! isUndefined( values._hasJumps ) ) {
+ this.setHasJumps( values._hasJumps );
+ }
+
+ if ( ! isUndefined( values.editFieldName ) ) {
+ this.setEditFieldName( values.editFieldName );
+ }
}
- if ( ! isUndefined( values.score ) ) {
- this.setScore( values.score );
+ /**
+ * Checks if a score is available.
+ * @returns {boolean} Whether or not a score is available.
+ */
+ hasScore() {
+ return this._hasScore;
}
- if ( ! isUndefined( values.text ) ) {
- this.setText( values.text );
+ /**
+ * Gets the available score
+ * @returns {number} The score associated with the AssessmentResult.
+ */
+ getScore() {
+ return this.score;
}
- if ( ! isUndefined( values.marks ) ) {
- this.setMarks( values.marks );
+ /**
+ * Sets the score for the assessment.
+ * @param {number} score The score to be used for the score property
+ * @returns {void}
+ */
+ setScore( score ) {
+ if ( isNumber( score ) ) {
+ this.score = score;
+ this._hasScore = true;
+ }
}
- if ( ! isUndefined( values._hasBetaBadge ) ) {
- this.setHasBetaBadge( values._hasBetaBadge );
+ /**
+ * Checks if a text is available.
+ * @returns {boolean} Whether or not a text is available.
+ */
+ hasText() {
+ return this.text !== "";
}
- if ( ! isUndefined( values._hasJumps ) ) {
- this.setHasJumps( values._hasJumps );
+ /**
+ * Gets the available text
+ * @returns {string} The text associated with the AssessmentResult.
+ */
+ getText() {
+ return this.text;
}
- if ( ! isUndefined( values.editFieldName ) ) {
- this.setEditFieldName( values.editFieldName );
+ /**
+ * Sets the text for the assessment.
+ * @param {string} text The text to be used for the text property
+ * @returns {void}
+ */
+ setText( text ) {
+ if ( isUndefined( text ) ) {
+ text = "";
+ }
+
+ this.text = text;
}
-};
-
-/**
- * Check if a score is available.
- * @returns {boolean} Whether or not a score is available.
- */
-AssessmentResult.prototype.hasScore = function() {
- return this._hasScore;
-};
-/**
- * Get the available score
- * @returns {number} The score associated with the AssessmentResult.
- */
-AssessmentResult.prototype.getScore = function() {
- return this.score;
-};
-
-/**
- * Set the score for the assessment.
- * @param {number} score The score to be used for the score property
- * @returns {void}
- */
-AssessmentResult.prototype.setScore = function( score ) {
- if ( isNumber( score ) ) {
- this.score = score;
- this._hasScore = true;
+ /**
+ * Gets the available marks.
+ *
+ * @returns {array} The marks associated with the AssessmentResult.
+ */
+ getMarks() {
+ return this.marks;
}
-};
-
-/**
- * Check if a text is available.
- * @returns {boolean} Whether or not a text is available.
- */
-AssessmentResult.prototype.hasText = function() {
- return this.text !== "";
-};
-
-/**
- * Get the available text
- * @returns {string} The text associated with the AssessmentResult.
- */
-AssessmentResult.prototype.getText = function() {
- return this.text;
-};
-/**
- * Set the text for the assessment.
- * @param {string} text The text to be used for the text property
- * @returns {void}
- */
-AssessmentResult.prototype.setText = function( text ) {
- if ( isUndefined( text ) ) {
- text = "";
+ /**
+ * Sets the marks for the assessment.
+ *
+ * @param {array} marks The marks to be used for the marks property
+ *
+ * @returns {void}
+ */
+ setMarks( marks ) {
+ if ( isArray( marks ) ) {
+ this.marks = marks;
+ this._hasMarks = marks.length > 0;
+ }
}
- this.text = text;
-};
-
-/**
- * Gets the available marks.
- *
- * @returns {array} The marks associated with the AssessmentResult.
- */
-AssessmentResult.prototype.getMarks = function() {
- return this.marks;
-};
-
-/**
- * Sets the marks for the assessment.
- *
- * @param {array} marks The marks to be used for the marks property
- *
- * @returns {void}
- */
-AssessmentResult.prototype.setMarks = function( marks ) {
- if ( isArray( marks ) ) {
- this.marks = marks;
- this._hasMarks = marks.length > 0;
+ /**
+ * Sets the identifier
+ *
+ * @param {string} identifier An alphanumeric identifier for this result.
+ * @returns {void}
+ */
+ setIdentifier( identifier ) {
+ this._identifier = identifier;
}
-};
-/**
- * Sets the identifier
- *
- * @param {string} identifier An alphanumeric identifier for this result.
- * @returns {void}
- */
-AssessmentResult.prototype.setIdentifier = function( identifier ) {
- this._identifier = identifier;
-};
-
-/**
- * Gets the identifier
- *
- * @returns {string} An alphanumeric identifier for this result.
- */
-AssessmentResult.prototype.getIdentifier = function() {
- return this._identifier;
-};
+ /**
+ * Gets the identifier
+ *
+ * @returns {string} An alphanumeric identifier for this result.
+ */
+ getIdentifier() {
+ return this._identifier;
+ }
-/**
- * Sets the marker, a pure function that can return the marks for a given Paper
- *
- * @param {Function} marker The marker to set.
- * @returns {void}
- */
-AssessmentResult.prototype.setMarker = function( marker ) {
- this._marker = marker;
-};
+ /**
+ * Sets the marker, a pure function that can return the marks for a given Paper
+ *
+ * @param {Function} marker The marker to set.
+ * @returns {void}
+ */
+ setMarker( marker ) {
+ this._marker = marker;
+ }
-/**
- * Returns whether or not this result has a marker that can be used to mark for a given Paper
- *
- * @returns {boolean} Whether or this result has a marker.
- */
-AssessmentResult.prototype.hasMarker = function() {
- return this._hasMarks && this._marker !== this.emptyMarker;
-};
+ /**
+ * Returns whether this result has a marker that can be used to mark for a given Paper.
+ *
+ * @returns {boolean} Whether this result has a marker.
+ */
+ hasMarker() {
+ return this._hasMarks && this._marker !== emptyMarker;
+ }
-/**
- * Gets the marker, a pure function that can return the marks for a given Paper
- *
- * @returns {Function} The marker.
- */
-AssessmentResult.prototype.getMarker = function() {
- return this._marker;
-};
+ /**
+ * Gets the marker, a pure function that can return the marks for a given Paper
+ *
+ * @returns {Function} The marker.
+ */
+ getMarker() {
+ return this._marker;
+ }
-/**
- * Sets the value of _hasMarks to determine if there is something to mark.
- *
- * @param {boolean} hasMarks Is there something to mark.
- * @returns {void}
- */
-AssessmentResult.prototype.setHasMarks = function( hasMarks ) {
- this._hasMarks = hasMarks;
-};
+ /**
+ * Sets the value of _hasMarks to determine if there is something to mark.
+ *
+ * @param {boolean} hasMarks Is there something to mark.
+ * @returns {void}
+ */
+ setHasMarks( hasMarks ) {
+ this._hasMarks = hasMarks;
+ }
-/**
- * Returns the value of _hasMarks to determine if there is something to mark.
- *
- * @returns {boolean} Is there something to mark.
- */
-AssessmentResult.prototype.hasMarks = function() {
- return this._hasMarks;
-};
+ /**
+ * Returns the value of _hasMarks to determine if there is something to mark.
+ *
+ * @returns {boolean} Is there something to mark.
+ */
+ hasMarks() {
+ return this._hasMarks;
+ }
-/**
- * Sets the value of _hasBetaBadge to determine if the result has a beta badge.
- *
- * @param {boolean} hasBetaBadge Whether this result has a beta badge.
- * @returns {void}
- */
-AssessmentResult.prototype.setHasBetaBadge = function( hasBetaBadge ) {
- this._hasBetaBadge = hasBetaBadge;
-};
+ /**
+ * Sets the value of _hasBetaBadge to determine if the result has a beta badge.
+ *
+ * @param {boolean} hasBetaBadge Whether this result has a beta badge.
+ * @returns {void}
+ */
+ setHasBetaBadge( hasBetaBadge ) {
+ this._hasBetaBadge = hasBetaBadge;
+ }
-/**
- * Returns the value of _hasBetaBadge to determine if the result has a beta badge.
- *
- * @returns {bool} Whether this result has a beta badge.
- */
-AssessmentResult.prototype.hasBetaBadge = function() {
- return this._hasBetaBadge;
-};
+ /**
+ * Returns the value of _hasBetaBadge to determine if the result has a beta badge.
+ *
+ * @returns {bool} Whether this result has a beta badge.
+ */
+ hasBetaBadge() {
+ return this._hasBetaBadge;
+ }
-/**
- * Sets the value of _hasJumps to determine whether it's needed to jump to a different field.
- *
- * @param {boolean} hasJumps Whether this result causes a jump to a different field.
- * @returns {void}
- */
-AssessmentResult.prototype.setHasJumps = function( hasJumps ) {
- this._hasJumps = hasJumps;
-};
+ /**
+ * Sets the value of _hasJumps to determine whether it's needed to jump to a different field.
+ *
+ * @param {boolean} hasJumps Whether this result causes a jump to a different field.
+ * @returns {void}
+ */
+ setHasJumps( hasJumps ) {
+ this._hasJumps = hasJumps;
+ }
-/**
- * Returns the value of _hasJumps to determine whether it's needed to jump to a different field.
- *
- * @returns {bool} Whether this result causes a jump to a different field.
- */
-AssessmentResult.prototype.hasJumps = function() {
- return this._hasJumps;
-};
+ /**
+ * Returns the value of _hasJumps to determine whether it's needed to jump to a different field.
+ *
+ * @returns {bool} Whether this result causes a jump to a different field.
+ */
+ hasJumps() {
+ return this._hasJumps;
+ }
-/**
- * Check if an edit field name is available.
- * @returns {boolean} Whether or not an edit field name is available.
- */
-AssessmentResult.prototype.hasEditFieldName = function() {
- return this._hasEditFieldName;
-};
+ /**
+ * Check if an edit field name is available.
+ * @returns {boolean} Whether or not an edit field name is available.
+ */
+ hasEditFieldName() {
+ return this._hasEditFieldName;
+ }
-/**
- * Get the edit field name.
- * @returns {string} The edit field name associated with the AssessmentResult.
- */
-AssessmentResult.prototype.getEditFieldName = function() {
- return this.editFieldName;
-};
+ /**
+ * Gets the edit field name.
+ * @returns {string} The edit field name associated with the AssessmentResult.
+ */
+ getEditFieldName() {
+ return this.editFieldName;
+ }
-/**
- * Set the edit field name to be used to create the aria label for an edit button.
- * @param {string} editFieldName The string to be used for the string property
- * @returns {void}
- */
-AssessmentResult.prototype.setEditFieldName = function( editFieldName ) {
- if ( editFieldName !== "" ) {
- this.editFieldName = editFieldName;
- this._hasEditFieldName = true;
+ /**
+ * Sets the edit field name to be used to create the aria label for an edit button.
+ * @param {string} editFieldName The string to be used for the string property
+ * @returns {void}
+ */
+ setEditFieldName( editFieldName ) {
+ if ( editFieldName !== "" ) {
+ this.editFieldName = editFieldName;
+ this._hasEditFieldName = true;
+ }
}
-};
-/**
- * Serializes the AssessmentResult instance to an object.
- *
- * @returns {Object} The serialized AssessmentResult.
- */
-AssessmentResult.prototype.serialize = function() {
- return {
- _parseClass: "AssessmentResult",
- identifier: this._identifier,
- score: this.score,
- text: this.text,
- marks: this.marks.map( mark => mark.serialize() ),
- _hasBetaBadge: this._hasBetaBadge,
- _hasJumps: this._hasJumps,
- editFieldName: this.editFieldName,
- };
-};
+ /**
+ * Serializes the AssessmentResult instance to an object.
+ *
+ * @returns {Object} The serialized AssessmentResult.
+ */
+ serialize() {
+ return {
+ _parseClass: "AssessmentResult",
+ identifier: this._identifier,
+ score: this.score,
+ text: this.text,
+ marks: this.marks.map( mark => mark.serialize() ),
+ _hasBetaBadge: this._hasBetaBadge,
+ _hasJumps: this._hasJumps,
+ editFieldName: this.editFieldName,
+ };
+ }
-/**
- * Parses the object to an AssessmentResult.
- *
- * @param {Object} serialized The serialized object.
- *
- * @returns {AssessmentResult} The parsed AssessmentResult.
- */
-AssessmentResult.parse = function( serialized ) {
- const result = new AssessmentResult( {
- text: serialized.text,
- score: serialized.score,
- marks: serialized.marks.map( mark => Mark.parse( mark ) ),
- _hasBetaBadge: serialized._hasBetaBadge,
- _hasJumps: serialized._hasJumps,
- editFieldName: serialized.editFieldName,
- } );
- result.setIdentifier( serialized.identifier );
-
- return result;
-};
+ /**
+ * Parses the object to an AssessmentResult.
+ *
+ * @param {Object} serialized The serialized object.
+ *
+ * @returns {AssessmentResult} The parsed AssessmentResult.
+ */
+ static parse( serialized ) {
+ const result = new AssessmentResult( {
+ text: serialized.text,
+ score: serialized.score,
+ marks: serialized.marks.map( mark => Mark.parse( mark ) ),
+ _hasBetaBadge: serialized._hasBetaBadge,
+ _hasJumps: serialized._hasJumps,
+ editFieldName: serialized.editFieldName,
+ } );
+ result.setIdentifier( serialized.identifier );
+
+ return result;
+ }
+}
export default AssessmentResult;
diff --git a/packages/yoastseo/src/values/Mark.js b/packages/yoastseo/src/values/Mark.js
index 332ec3393a4..e07eece97d2 100644
--- a/packages/yoastseo/src/values/Mark.js
+++ b/packages/yoastseo/src/values/Mark.js
@@ -1,264 +1,269 @@
import { defaults, isUndefined } from "lodash";
-/**
- * Represents a place where highlighting should be applied.
- * We allow both replacement-based highlighting (through providing `original`, `marked`, and potentially `fieldsToMark`) and
- * position-based highlighting (through providing a `position`).
- *
- * @param {Object} properties The properties of this Mark.
- *
- * @param {string?} properties.original The original text that should be marked.
- * @param {string?} properties.marked The new text including marks.
- * @param {array?} properties.fieldsToMark The array that specifies which text section(s) to mark.
- *
- * @param {SourceCodeRange?} properties.position The position object: a range in the source code.
- *
- * @constructor
- */
-function Mark( properties ) {
- defaults( properties, { original: "", marked: "", fieldsToMark: [] } );
- this._properties = properties;
- this.isValid();
-}
+const defaultProperties = { original: "", marked: "", fieldsToMark: [] };
/**
- * Returns the original text.
- *
- * @returns {string} The original text.
- */
-Mark.prototype.getOriginal = function() {
- return this._properties.original;
-};
-
-/**
- * Returns the marked text.
- *
- * @returns {string} The replaced text.
+ * Represents a place where highlighting should be applied.
*/
-Mark.prototype.getMarked = function() {
- return this._properties.marked;
-};
+class Mark {
+ /**
+ * Represents a place where highlighting should be applied.
+ * We allow both replacement-based highlighting (through providing `original`, `marked`, and potentially `fieldsToMark`) and
+ * position-based highlighting (through providing a `position`).
+ *
+ * @param {Object} [properties] The properties of this Mark.
+ *
+ * @param {string?} properties.original The original text that should be marked.
+ * @param {string?} properties.marked The new text including marks.
+ * @param {array?} properties.fieldsToMark The array that specifies which text section(s) to mark.
+ *
+ * @param {SourceCodeRange?} properties.position The position object: a range in the source code.
+ */
+ constructor( properties ) {
+ properties = properties || {};
+ defaults( properties, defaultProperties );
+ this._properties = properties;
+ this.isValid();
+ }
-/**
- * Returns the fields to mark.
- *
- * @returns {array} The fields to mark.
- */
-Mark.prototype.getFieldsToMark = function() {
- return this._properties.fieldsToMark;
-};
+ /**
+ * Returns the original text.
+ *
+ * @returns {string} The original text.
+ */
+ getOriginal() {
+ return this._properties.original;
+ }
-/**
- * Returns the position information.
- *
- * @returns {number} The position information.
- */
-Mark.prototype.getPosition = function() {
- return this._properties.position;
-};
+ /**
+ * Returns the marked text.
+ *
+ * @returns {string} The replaced text.
+ */
+ getMarked() {
+ return this._properties.marked;
+ }
-/**
- * Returns the start position.
- *
- * @returns {number} The start position.
- */
-Mark.prototype.getPositionStart = function() {
- return this._properties.position && this._properties.position.startOffset;
-};
+ /**
+ * Returns the fields to mark.
+ *
+ * @returns {array} The fields to mark.
+ */
+ getFieldsToMark() {
+ return this._properties.fieldsToMark;
+ }
-/**
- * Returns the end position.
- *
- * @returns {number} The end position.
- */
-Mark.prototype.getPositionEnd = function() {
- return this._properties.position && this._properties.position.endOffset;
-};
+ /**
+ * Returns the position information.
+ *
+ * @returns {Object} The position information.
+ */
+ getPosition() {
+ return this._properties.position;
+ }
-/**
- * Sets the start position.
- *
- * @param {number} positionStart The new start position.
- *
- * @returns {void}
- */
-Mark.prototype.setPositionStart = function( positionStart ) {
- this._properties.position.startOffset = positionStart;
-};
+ /**
+ * Returns the start position.
+ *
+ * @returns {number} The start position.
+ */
+ getPositionStart() {
+ return this._properties.position && this._properties.position.startOffset;
+ }
-/**
- * Sets the end position.
- *
- * @param {number} positionEnd The new end position.
- *
- * @returns {void}
- */
-Mark.prototype.setPositionEnd = function( positionEnd ) {
- this._properties.position.endOffset = positionEnd;
-};
+ /**
+ * Returns the end position.
+ *
+ * @returns {number} The end position.
+ */
+ getPositionEnd() {
+ return this._properties.position && this._properties.position.endOffset;
+ }
-/**
- * Returns the start position of a block.
- *
- * @param {number} startOffsetBlock The block start offset.
- *
- * @returns {number} The start position of a block.
- */
-Mark.prototype.setBlockPositionStart = function( startOffsetBlock ) {
- this._properties.position.startOffsetBlock = startOffsetBlock;
-};
+ /**
+ * Sets the start position.
+ *
+ * @param {number} positionStart The new start position.
+ *
+ * @returns {void}
+ */
+ setPositionStart( positionStart ) {
+ this._properties.position.startOffset = positionStart;
+ }
-/**
- * Returns the end position of a block.
- *
- * @param {number} endOffsetBlock The block end offset.
- *
- * @returns {number} The end position of a block.
- */
-Mark.prototype.setBlockPositionEnd = function( endOffsetBlock ) {
- this._properties.position.endOffsetBlock = endOffsetBlock;
-};
+ /**
+ * Sets the end position.
+ *
+ * @param {number} positionEnd The new end position.
+ *
+ * @returns {void}
+ */
+ setPositionEnd( positionEnd ) {
+ this._properties.position.endOffset = positionEnd;
+ }
-/**
- * Gets the block client id.
- *
- * @returns {string} The block client id.
- */
-Mark.prototype.getBlockClientId = function() {
- return this._properties.position && this._properties.position.clientId;
-};
+ /**
+ * Returns the start position of a block.
+ *
+ * @param {number} startOffsetBlock The block start offset.
+ *
+ * @returns {number} The start position of a block.
+ */
+ setBlockPositionStart( startOffsetBlock ) {
+ this._properties.position.startOffsetBlock = startOffsetBlock;
+ }
-/**
- * Gets the block attribute id.
- *
- * @returns {string} The block attribute id.
- */
-Mark.prototype.getBlockAttributeId = function() {
- return this._properties.position && this._properties.position.attributeId;
-};
+ /**
+ * Returns the end position of a block.
+ *
+ * @param {number} endOffsetBlock The block end offset.
+ *
+ * @returns {number} The end position of a block.
+ */
+ setBlockPositionEnd( endOffsetBlock ) {
+ this._properties.position.endOffsetBlock = endOffsetBlock;
+ }
+ /**
+ * Gets the block client id.
+ *
+ * @returns {string} The block client id.
+ */
+ getBlockClientId() {
+ return this._properties.position && this._properties.position.clientId;
+ }
-/**
- * Checks if the mark object is intended for the first section of a Yoast sub-block.
- * This method will be used only for Yoast blocks where each block consists of sub-blocks
- * with two sections.
- *
- * @returns {boolean} Whether the mark object is intended for the first section of a Yoast sub-block.
- */
-Mark.prototype.isMarkForFirstBlockSection = function() {
- return this._properties.position && this._properties.position.isFirstSection;
-};
+ /**
+ * Gets the block attribute id.
+ *
+ * @returns {string} The block attribute id.
+ */
+ getBlockAttributeId() {
+ return this._properties.position && this._properties.position.attributeId;
+ }
-/**
- * Returns the start position inside block.
- *
- * @returns {number} The start position inside block if the mark position information, undefined otherwise.
- */
-Mark.prototype.getBlockPositionStart = function() {
- return this._properties.position && this._properties.position.startOffsetBlock;
-};
-/**
- * Returns the end position inside block if the mark has position information, undefined otherwise.
- *
- * @returns {number} The end position inside block.
- */
-Mark.prototype.getBlockPositionEnd = function() {
- return this._properties.position && this._properties.position.endOffsetBlock;
-};
+ /**
+ * Checks if the mark object is intended for the first section of a Yoast sub-block.
+ * This method will be used only for Yoast blocks where each block consists of sub-blocks
+ * with two sections.
+ *
+ * @returns {boolean} Whether the mark object is intended for the first section of a Yoast sub-block.
+ */
+ isMarkForFirstBlockSection() {
+ return this._properties.position && this._properties.position.isFirstSection;
+ }
-/**
- * Applies this mark to the given text with replacement-based highlighting.
- *
- * @param {string} text The original text without the mark applied.
- * @returns {string} A new text with the mark applied to it.
- */
-Mark.prototype.applyWithReplace = function( text ) {
- // (=^ ◡ ^=) Cute method to replace everything in a string without using regex.
- return text.split( this._properties.original ).join( this._properties.marked );
-};
+ /**
+ * Returns the start position inside block.
+ *
+ * @returns {number} The start position inside block if the mark position information, undefined otherwise.
+ */
+ getBlockPositionStart() {
+ return this._properties.position && this._properties.position.startOffsetBlock;
+ }
-/**
- * Applies this mark to the given text with position-based highlighting.
- *
- * @param {string} text The original text without the mark applied.
- * @returns {string} A new text with the mark applied to it.
- */
-Mark.prototype.applyWithPosition = function( text ) {
- const markStart = "";
- const markEnd = "";
+ /**
+ * Returns the end position inside block if the mark has position information, undefined otherwise.
+ *
+ * @returns {number} The end position inside block.
+ */
+ getBlockPositionEnd() {
+ return this._properties.position && this._properties.position.endOffsetBlock;
+ }
- const newPositionEnd = this.getPositionEnd() + markStart.length;
+ /**
+ * Applies this mark to the given text with replacement-based highlighting.
+ *
+ * @param {string} text The original text without the mark applied.
+ * @returns {string} A new text with the mark applied to it.
+ */
+ applyWithReplace( text ) {
+ // (=^ ◡ ^=) Cute method to replace everything in a string without using regex.
+ return text.split( this._properties.original ).join( this._properties.marked );
+ }
- text = text.substring( 0, this.getPositionStart() ) + markStart + text.substring( this.getPositionStart() );
- text = text.substring( 0, newPositionEnd ) + markEnd + text.substring( newPositionEnd );
+ /**
+ * Applies this mark to the given text with position-based highlighting.
+ *
+ * @param {string} text The original text without the mark applied.
+ * @returns {string} A new text with the mark applied to it.
+ */
+ applyWithPosition( text ) {
+ const markStart = "";
+ const markEnd = "";
- return text;
-};
+ const newPositionEnd = this.getPositionEnd() + markStart.length;
-/**
- * Serializes the Mark instance to an object.
- *
- * @returns {Object} The serialized Mark.
- */
-Mark.prototype.serialize = function() {
- return {
- _parseClass: "Mark",
- ...this._properties,
- };
-};
+ text = text.substring( 0, this.getPositionStart() ) + markStart + text.substring( this.getPositionStart() );
+ text = text.substring( 0, newPositionEnd ) + markEnd + text.substring( newPositionEnd );
-/**
- * Checks if the mark object is valid for position-based highlighting.
- * @returns {void}
- */
-// eslint-disable-next-line complexity
-Mark.prototype.isValid = function() {
- if ( ! isUndefined( this.getPositionStart() ) && this.getPositionStart() < 0 ) {
- throw new RangeError( "positionStart should be larger or equal than 0." );
+ return text;
}
- if ( ! isUndefined( this.getPositionEnd() ) && this.getPositionEnd() <= 0 ) {
- throw new RangeError( "positionEnd should be larger than 0." );
- }
- if ( ! isUndefined( this.getPositionStart() ) && ! isUndefined( this.getPositionEnd() ) &&
- this.getPositionStart() >= this.getPositionEnd() ) {
- throw new RangeError( "The positionStart should be smaller than the positionEnd." );
+
+ /**
+ * Serializes the Mark instance to an object.
+ *
+ * @returns {Object} The serialized Mark.
+ */
+ serialize() {
+ return {
+ _parseClass: "Mark",
+ ...this._properties,
+ };
}
- if ( isUndefined( this.getPositionStart() ) && ! isUndefined( this.getPositionEnd() ) ||
- isUndefined( this.getPositionEnd() ) && ! isUndefined( this.getPositionStart() ) ) {
- throw new Error( "A mark object should either have start and end defined or start and end undefined." );
+
+ /**
+ * Checks if the mark object is valid for position-based highlighting.
+ * @returns {void}
+ */
+ isValid() {
+ if ( ! isUndefined( this.getPositionStart() ) && this.getPositionStart() < 0 ) {
+ throw new RangeError( "positionStart should be larger or equal than 0." );
+ }
+ if ( ! isUndefined( this.getPositionEnd() ) && this.getPositionEnd() <= 0 ) {
+ throw new RangeError( "positionEnd should be larger than 0." );
+ }
+ if ( ! isUndefined( this.getPositionStart() ) && ! isUndefined( this.getPositionEnd() ) &&
+ this.getPositionStart() >= this.getPositionEnd() ) {
+ throw new RangeError( "The positionStart should be smaller than the positionEnd." );
+ }
+ if ( isUndefined( this.getPositionStart() ) && ! isUndefined( this.getPositionEnd() ) ||
+ isUndefined( this.getPositionEnd() ) && ! isUndefined( this.getPositionStart() ) ) {
+ throw new Error( "A mark object should either have start and end defined or start and end undefined." );
+ }
}
-};
-/**
- * Checks if a mark has position information available.
- * @returns {boolean} Returns true if the Mark object has position information, false otherwise.
- */
-Mark.prototype.hasPosition = function() {
- return ! isUndefined( this.getPositionStart() );
-};
+ /**
+ * Checks if a mark has position information available.
+ * @returns {boolean} Returns true if the Mark object has position information, false otherwise.
+ */
+ hasPosition() {
+ return ! isUndefined( this.getPositionStart() );
+ }
-/**
- * Checks if a mark has block position information available.
- * A block has position information if the block start offset is available.
- *
- * @returns {boolean} Returns true if the Mark object has block position information, false otherwise.
- */
-Mark.prototype.hasBlockPosition = function() {
- return ! isUndefined( this.getBlockPositionStart() );
-};
+ /**
+ * Checks if a mark has block position information available.
+ * A block has position information if the block start offset is available.
+ *
+ * @returns {boolean} Returns true if the Mark object has block position information, false otherwise.
+ */
+ hasBlockPosition() {
+ return ! isUndefined( this.getBlockPositionStart() );
+ }
-/**
- * Parses the object to a Mark.
- *
- * @param {Object} serialized The serialized object.
- *
- * @returns {Mark} The parsed Mark.
- */
-Mark.parse = function( serialized ) {
- delete serialized._parseClass;
- return new Mark( serialized );
-};
+ /**
+ * Parses the object to a Mark.
+ *
+ * @param {Object} serialized The serialized object.
+ *
+ * @returns {Mark} The parsed Mark.
+ */
+ static parse( serialized ) {
+ delete serialized._parseClass;
+ return new Mark( serialized );
+ }
+}
export default Mark;
diff --git a/packages/yoastseo/src/values/Paper.js b/packages/yoastseo/src/values/Paper.js
index 5430f6e2ee7..8aff77800a3 100644
--- a/packages/yoastseo/src/values/Paper.js
+++ b/packages/yoastseo/src/values/Paper.js
@@ -21,338 +21,341 @@ const defaultAttributes = {
};
/**
- * Constructs the Paper object and sets the keyword property.
- *
- * @param {string} text The text to use in the analysis.
- * @param {object} [attributes] The object containing all attributes.
- * @param {string} [attributes.keyword] The main keyword.
- * @param {string} [attributes.synonyms] The main keyword's synonyms.
- * @param {string} [attributes.description] The SEO description.
- * @param {string} [attributes.title] The SEO title.
- * @param {number} [attributes.titleWidth] The width of the title in pixels.
- * @param {string} [attributes.slug] The slug.
- * @param {string} [attributes.locale] The locale.
- * @param {string} [attributes.permalink] The base url + slug.
- * @param {string} [attributes.date] The date.
- * @param {Object} [attributes.wpBlocks] The text, encoded in WordPress block editor blocks.
- * @param {Object} [attributes.customData] Custom data.
- * @param {string} [attributes.textTitle] The title of the text.
- * @param {string} [attributes.writingDirection] The writing direction of the paper. Defaults to left to right (LTR).
- *
- * @constructor
- */
-function Paper( text, attributes ) {
- this._text = text || "";
-
- this._tree = null;
+ * Represents an object where the analysis data is stored.
+ */
+class Paper {
+ /**
+ * Constructs the Paper object and sets the keyword property.
+ *
+ * @param {string} text The text to use in the analysis.
+ * @param {object} [attributes] The object containing all attributes.
+ * @param {string} [attributes.keyword] The main keyword.
+ * @param {string} [attributes.synonyms] The main keyword's synonyms.
+ * @param {string} [attributes.description] The SEO description.
+ * @param {string} [attributes.title] The SEO title.
+ * @param {number} [attributes.titleWidth] The width of the title in pixels.
+ * @param {string} [attributes.slug] The slug.
+ * @param {string} [attributes.locale] The locale.
+ * @param {string} [attributes.permalink] The base url + slug.
+ * @param {string} [attributes.date] The date.
+ * @param {Object} [attributes.wpBlocks] The text, encoded in WordPress block editor blocks.
+ * @param {Object} [attributes.customData] Custom data.
+ * @param {string} [attributes.textTitle] The title of the text.
+ * @param {string} [attributes.writingDirection] The writing direction of the paper. Defaults to left to right (LTR).
+ */
+ constructor( text, attributes ) {
+ this._text = text || "";
+
+ this._tree = null;
+
+ attributes = attributes || {};
+ defaults( attributes, defaultAttributes );
+
+ if ( attributes.locale === "" ) {
+ attributes.locale = defaultAttributes.locale;
+ }
+
+ if ( attributes.hasOwnProperty( "url" ) ) {
+ // The 'url' attribute has been deprecated since version 18.8, refer to hasUrl and getUrl below.
+ console.warn( "The 'url' attribute is deprecated, use 'slug' instead." );
+ attributes.slug = attributes.url || attributes.slug;
+ }
+
+ const onlyLetters = attributes.keyword.replace( /[‘’“”"'.?!:;,¿¡«»&*@#±^%|~`[\](){}⟨⟩<>/\\–\-\u2014\u00d7\u002b\s]/g, "" );
+
+ if ( isEmpty( onlyLetters ) ) {
+ attributes.keyword = defaultAttributes.keyword;
+ }
+
+ this._attributes = attributes;
+ }
- attributes = attributes || {};
- defaults( attributes, defaultAttributes );
- if ( attributes.locale === "" ) {
- attributes.locale = defaultAttributes.locale;
+ /**
+ * Checks whether a keyword is available.
+ * @returns {boolean} Returns true if the Paper has a keyword.
+ */
+ hasKeyword() {
+ return this._attributes.keyword !== "";
}
- if ( attributes.hasOwnProperty( "url" ) ) {
- // The 'url' attribute has been deprecated since version 18.8, refer to hasUrl and getUrl below.
- console.warn( "The 'url' attribute is deprecated, use 'slug' instead." );
- attributes.slug = attributes.url || attributes.slug;
+ /**
+ * Returns the associated keyword or an empty string if no keyword is available.
+ * @returns {string} Returns Keyword
+ */
+ getKeyword() {
+ return this._attributes.keyword;
}
- const onlyLetters = attributes.keyword.replace( /[‘’“”"'.?!:;,¿¡«»&*@#±^%|~`[\](){}⟨⟩<>/\\–\-\u2014\u00d7\u002b\u0026\s]/g, "" );
-
- if ( isEmpty( onlyLetters ) ) {
- attributes.keyword = defaultAttributes.keyword;
+ /**
+ * Checks whether synonyms are available.
+ * @returns {boolean} Returns true if the Paper has synonyms.
+ */
+ hasSynonyms() {
+ return this._attributes.synonyms !== "";
}
- this._attributes = attributes;
-}
-
-
-/**
- * Checks whether a keyword is available.
- * @returns {boolean} Returns true if the Paper has a keyword.
- */
-Paper.prototype.hasKeyword = function() {
- return this._attributes.keyword !== "";
-};
-
-/**
- * Returns the associated keyword or an empty string if no keyword is available.
- * @returns {string} Returns Keyword
- */
-Paper.prototype.getKeyword = function() {
- return this._attributes.keyword;
-};
-
-/**
- * Checks whether synonyms are available.
- * @returns {boolean} Returns true if the Paper has synonyms.
- */
-Paper.prototype.hasSynonyms = function() {
- return this._attributes.synonyms !== "";
-};
-
-/**
- * Returns the associated synonyms or an empty string if no synonyms is available.
- * @returns {string} Returns synonyms.
- */
-Paper.prototype.getSynonyms = function() {
- return this._attributes.synonyms;
-};
-
-/**
- * Checks whether the text is available.
- * @returns {boolean} Returns true if the paper has a text.
- */
-Paper.prototype.hasText = function() {
- return this._text !== "";
-};
-
-/**
- * Returns the associated text or am empty string if no text is available.
- * @returns {string} Returns text
- */
-Paper.prototype.getText = function() {
- return this._text;
-};
+ /**
+ * Returns the associated synonyms or an empty string if no synonyms is available.
+ * @returns {string} Returns synonyms.
+ */
+ getSynonyms() {
+ return this._attributes.synonyms;
+ }
-/**
- * Sets the tree.
- *
- * @param {Node} tree The tree to set.
- *
- * @returns {void}
- */
-Paper.prototype.setTree = function( tree ) {
- this._tree = tree;
-};
+ /**
+ * Checks whether the text is available.
+ * @returns {boolean} Returns true if the paper has a text.
+ */
+ hasText() {
+ return this._text !== "";
+ }
-/**
- * Returns the tree.
- *
- * @returns {Node} The tree.
- */
-Paper.prototype.getTree = function() {
- return this._tree;
-};
+ /**
+ * Returns the associated text or am empty string if no text is available.
+ * @returns {string} Returns text
+ */
+ getText() {
+ return this._text;
+ }
-/**
- * Checks whether a description is available.
- * @returns {boolean} Returns true if the paper has a description.
- */
-Paper.prototype.hasDescription = function() {
- return this._attributes.description !== "";
-};
+ /**
+ * Sets the tree.
+ *
+ * @param {Node} tree The tree to set.
+ *
+ * @returns {void}
+ */
+ setTree( tree ) {
+ this._tree = tree;
+ }
-/**
- * Returns the description or an empty string if no description is available.
- * @returns {string} Returns the description.
- */
-Paper.prototype.getDescription = function() {
- return this._attributes.description;
-};
+ /**
+ * Returns the tree.
+ *
+ * @returns {Node} The tree.
+ */
+ getTree() {
+ return this._tree;
+ }
-/**
- * Checks whether a title is available
- * @returns {boolean} Returns true if the Paper has a title.
- */
-Paper.prototype.hasTitle = function() {
- return this._attributes.title !== "";
-};
+ /**
+ * Checks whether a description is available.
+ * @returns {boolean} Returns true if the paper has a description.
+ */
+ hasDescription() {
+ return this._attributes.description !== "";
+ }
-/**
- * Returns the title, or an empty string of no title is available.
- * @returns {string} Returns the title
- */
-Paper.prototype.getTitle = function() {
- return this._attributes.title;
-};
+ /**
+ * Returns the description or an empty string if no description is available.
+ * @returns {string} Returns the description.
+ */
+ getDescription() {
+ return this._attributes.description;
+ }
-/**
- * Checks whether a title width in pixels is available
- * @returns {boolean} Returns true if the Paper has a title.
- */
-Paper.prototype.hasTitleWidth = function() {
- return this._attributes.titleWidth !== 0;
-};
+ /**
+ * Checks whether a title is available
+ * @returns {boolean} Returns true if the Paper has a title.
+ */
+ hasTitle() {
+ return this._attributes.title !== "";
+ }
-/**
- * Returns the title width in pixels, or an empty string of no title width in pixels is available.
- * @returns {string} Returns the title
- */
-Paper.prototype.getTitleWidth = function() {
- return this._attributes.titleWidth;
-};
+ /**
+ * Returns the title, or an empty string of no title is available.
+ * @returns {string} Returns the title
+ */
+ getTitle() {
+ return this._attributes.title;
+ }
-/**
- * Checks whether a slug is available
- * @returns {boolean} Returns true if the Paper has a slug.
- */
-Paper.prototype.hasSlug = function() {
- return this._attributes.slug !== "";
-};
+ /**
+ * Checks whether a title width in pixels is available
+ * @returns {boolean} Returns true if the Paper has a title.
+ */
+ hasTitleWidth() {
+ return this._attributes.titleWidth !== 0;
+ }
-/**
- * Returns the slug, or an empty string of no slug is available.
- * @returns {string} Returns the url
- */
-Paper.prototype.getSlug = function() {
- return this._attributes.slug;
-};
+ /**
+ * Returns the title width in pixels, or an empty string of no title width in pixels is available.
+ * @returns {number} Returns the title
+ */
+ getTitleWidth() {
+ return this._attributes.titleWidth;
+ }
-/**
- * Checks whether an url is available
- * @deprecated Since version 18.7. Use hasSlug instead.
- * @returns {boolean} Returns true if the Paper has a slug.
- */
-Paper.prototype.hasUrl = function() {
- console.warn( "This function is deprecated, use hasSlug instead" );
- return this.hasSlug();
-};
+ /**
+ * Checks whether a slug is available
+ * @returns {boolean} Returns true if the Paper has a slug.
+ */
+ hasSlug() {
+ return this._attributes.slug !== "";
+ }
-/**
- * Returns the url, or an empty string if no url is available.
- * @deprecated Since version 18.8. Use getSlug instead.
- * @returns {string} Returns the url
- */
-Paper.prototype.getUrl = function() {
- console.warn( "This function is deprecated, use getSlug instead" );
- return this.getSlug();
-};
+ /**
+ * Returns the slug, or an empty string of no slug is available.
+ * @returns {string} Returns the url
+ */
+ getSlug() {
+ return this._attributes.slug;
+ }
-/**
- * Checks whether a locale is available
- * @returns {boolean} Returns true if the paper has a locale
- */
-Paper.prototype.hasLocale = function() {
- return this._attributes.locale !== "";
-};
+ /**
+ * Checks whether an url is available
+ * @deprecated Since version 18.7. Use hasSlug instead.
+ * @returns {boolean} Returns true if the Paper has a slug.
+ */
+ hasUrl() {
+ console.warn( "This function is deprecated, use hasSlug instead" );
+ return this.hasSlug();
+ }
-/**
- * Returns the locale or an empty string if no locale is available
- * @returns {string} Returns the locale
- */
-Paper.prototype.getLocale = function() {
- return this._attributes.locale;
-};
+ /**
+ * Returns the url, or an empty string if no url is available.
+ * @deprecated Since version 18.8. Use getSlug instead.
+ * @returns {string} Returns the url
+ */
+ getUrl() {
+ console.warn( "This function is deprecated, use getSlug instead" );
+ return this.getSlug();
+ }
-/**
- * Gets the information of the writing direction of the paper.
- * It returns "LTR" (left to right) if this attribute is not provided.
- *
- * @returns {string} Returns the information of the writing direction of the paper.
- */
-Paper.prototype.getWritingDirection = function() {
- return this._attributes.writingDirection;
-};
+ /**
+ * Checks whether a locale is available
+ * @returns {boolean} Returns true if the paper has a locale
+ */
+ hasLocale() {
+ return this._attributes.locale !== "";
+ }
-/**
- * Checks whether a permalink is available
- * @returns {boolean} Returns true if the Paper has a permalink.
- */
-Paper.prototype.hasPermalink = function() {
- return this._attributes.permalink !== "";
-};
+ /**
+ * Returns the locale or an empty string if no locale is available
+ * @returns {string} Returns the locale
+ */
+ getLocale() {
+ return this._attributes.locale;
+ }
-/**
- * Returns the permalink, or an empty string if no permalink is available.
- * @returns {string} Returns the permalink.
- */
-Paper.prototype.getPermalink = function() {
- return this._attributes.permalink;
-};
+ /**
+ * Gets the information of the writing direction of the paper.
+ * It returns "LTR" (left to right) if this attribute is not provided.
+ *
+ * @returns {string} Returns the information of the writing direction of the paper.
+ */
+ getWritingDirection() {
+ return this._attributes.writingDirection;
+ }
-/**
- * Checks whether a date is available.
- * @returns {boolean} Returns true if the Paper has a date.
- */
-Paper.prototype.hasDate = function() {
- return this._attributes.date !== "";
-};
+ /**
+ * Checks whether a permalink is available
+ * @returns {boolean} Returns true if the Paper has a permalink.
+ */
+ hasPermalink() {
+ return this._attributes.permalink !== "";
+ }
-/**
- * Returns the date, or an empty string if no date is available.
- * @returns {string} Returns the date.
- */
-Paper.prototype.getDate = function() {
- return this._attributes.date;
-};
+ /**
+ * Returns the permalink, or an empty string if no permalink is available.
+ * @returns {string} Returns the permalink.
+ */
+ getPermalink() {
+ return this._attributes.permalink;
+ }
-/**
- * Checks whether custom data is available.
- * @returns {boolean} Returns true if the Paper has custom data.
- */
-Paper.prototype.hasCustomData = function() {
- return ! isEmpty( this._attributes.customData );
-};
+ /**
+ * Checks whether a date is available.
+ * @returns {boolean} Returns true if the Paper has a date.
+ */
+ hasDate() {
+ return this._attributes.date !== "";
+ }
-/**
- * Returns the custom data, or an empty object if no data is available.
- * @returns {Object} Returns the custom data.
- */
-Paper.prototype.getCustomData = function() {
- return this._attributes.customData;
-};
+ /**
+ * Returns the date, or an empty string if no date is available.
+ * @returns {string} Returns the date.
+ */
+ getDate() {
+ return this._attributes.date;
+ }
-/**
- * Checks whether a text title is available.
- * @returns {boolean} Returns true if the Paper has a text title.
- */
-Paper.prototype.hasTextTitle = function() {
- return this._attributes.textTitle !== "" && ! isNil( this._attributes.textTitle );
-};
+ /**
+ * Checks whether custom data is available.
+ * @returns {boolean} Returns true if the Paper has custom data.
+ */
+ hasCustomData() {
+ return ! isEmpty( this._attributes.customData );
+ }
-/**
- * Returns the text title, or an empty string if no data is available.
- * @returns {string} Returns the text title.
- */
-Paper.prototype.getTextTitle = function() {
- return this._attributes.textTitle;
-};
+ /**
+ * Returns the custom data, or an empty object if no data is available.
+ * @returns {Object} Returns the custom data.
+ */
+ getCustomData() {
+ return this._attributes.customData;
+ }
-/**
- * Serializes the Paper instance to an object.
- *
- * @returns {Object} The serialized Paper.
- */
-Paper.prototype.serialize = function() {
- return {
- _parseClass: "Paper",
- text: this._text,
- ...this._attributes,
- };
-};
+ /**
+ * Checks whether a text title is available.
+ * @returns {boolean} Returns true if the Paper has a text title.
+ */
+ hasTextTitle() {
+ return this._attributes.textTitle !== "" && ! isNil( this._attributes.textTitle );
+ }
-/**
- * Checks whether the given paper has the same properties as this instance.
- *
- * @param {Paper} paper The paper to compare to.
- *
- * @returns {boolean} Whether the given paper is identical or not.
- */
-Paper.prototype.equals = function( paper ) {
- return this._text === paper.getText() && isEqual( this._attributes, paper._attributes );
-};
+ /**
+ * Returns the text title, or an empty string if no data is available.
+ * @returns {string} Returns the text title.
+ */
+ getTextTitle() {
+ return this._attributes.textTitle;
+ }
-/**
- * Parses the object to a Paper.
- *
- * @param {Object|Paper} serialized The serialized object or Paper instance.
- *
- * @returns {Paper} The parsed Paper.
- */
-Paper.parse = function( serialized ) {
- // For ease of use, check if it is not already a Paper instance.
- if ( serialized instanceof Paper ) {
- return serialized;
+ /**
+ * Serializes the Paper instance to an object.
+ *
+ * @returns {Object} The serialized Paper.
+ */
+ serialize() {
+ return {
+ _parseClass: "Paper",
+ text: this._text,
+ ...this._attributes,
+ };
}
- // _parseClass is taken here, so it doesn't end up in the attributes.
- // eslint-disable-next-line no-unused-vars
- const { text, _parseClass, ...attributes } = serialized;
+ /**
+ * Checks whether the given paper has the same properties as this instance.
+ *
+ * @param {Paper} paper The paper to compare to.
+ *
+ * @returns {boolean} Whether the given paper is identical or not.
+ */
+ equals( paper ) {
+ return this._text === paper.getText() && isEqual( this._attributes, paper._attributes );
+ }
- return new Paper( text, attributes );
-};
+ /**
+ * Parses the object to a Paper.
+ *
+ * @param {Object|Paper} serialized The serialized object or Paper instance.
+ *
+ * @returns {Paper} The parsed Paper.
+ */
+ static parse( serialized ) {
+ // For ease of use, check if it is not already a Paper instance.
+ if ( serialized instanceof Paper ) {
+ return serialized;
+ }
+
+ // _parseClass is taken here, so it doesn't end up in the attributes.
+ // eslint-disable-next-line no-unused-vars
+ const { text, _parseClass, ...attributes } = serialized;
+
+ return new Paper( text, attributes );
+ }
+}
export default Paper;
diff --git a/packages/yoastseo/src/worker/transporter/parse.js b/packages/yoastseo/src/worker/transporter/parse.js
index 7df330b8dc5..001b42576c3 100644
--- a/packages/yoastseo/src/worker/transporter/parse.js
+++ b/packages/yoastseo/src/worker/transporter/parse.js
@@ -31,9 +31,7 @@ export default function parse( thing ) {
const thingIsObject = isObject( thing );
if ( thingIsObject && thing._parseClass && PARSE_CLASSES[ thing._parseClass ] ) {
- return thing._parseClass === "Sentence" || thing._parseClass === "Clause"
- ? PARSE_CLASSES[ thing._parseClass ].prototype.parse( thing )
- : PARSE_CLASSES[ thing._parseClass ].parse( thing );
+ return PARSE_CLASSES[ thing._parseClass ].parse( thing );
}
if ( thingIsObject ) {