yoastseo-dep
Version:
Yoast clientside page analysis
334 lines (298 loc) • 9.83 kB
JavaScript
import { merge, isUndefined, isEmpty } from "lodash-es";
import InvalidTypeError from "../errors/invalidType";
import MissingArgument from "../errors/missingArgument";
// All researches in alphabetical order.
import altTagCount from "./researches/altTagCount.js";
import countSentencesFromText from "./researches/countSentencesFromText.js";
import findKeywordInFirstParagraph from "./researches/findKeywordInFirstParagraph.js";
import findKeyphraseInSEOTitle from "./researches/findKeyphraseInSEOTitle";
import findTransitionWords from "./researches/findTransitionWords";
import functionWordsInKeyphrase from "./researches/functionWordsInKeyphrase";
import getAnchorsWithKeyphrase from "./researches/getAnchorsWithKeyphrase";
import getFleschReadingScore from "./researches/getFleschReadingScore";
import getKeyphraseDensity, { getKeywordDensity } from "./researches/getKeywordDensity.js";
import getLinks from "./researches/getLinks.js";
import getLinkStatistics from "./researches/getLinkStatistics";
import getParagraphs from "./researches/getParagraphs";
import getParagraphLength from "./researches/getParagraphLength.js";
import getPassiveVoiceResult from "./researches/getPassiveVoiceResult";
import getProminentWordsForInsights from "./researches/getProminentWordsForInsights";
import getProminentWordsForInternalLinking from "./researches/getProminentWordsForInternalLinking";
import getSentenceBeginnings from "./researches/getSentenceBeginnings";
import getSubheadingTextLengths from "./researches/getSubheadingTextLengths.js";
import h1s from "./researches/h1s";
import imageCount from "./researches/imageCount.js";
import keyphraseLength from "./researches/keyphraseLength";
import getKeyphraseCount, { keywordCount } from "./researches/keywordCount";
import { keywordCountInSlug, keywordCountInUrl } from "./researches/keywordCountInUrl";
import matchKeywordInSubheadings from "./researches/matchKeywordInSubheadings";
import metaDescriptionKeyword from "./researches/metaDescriptionKeyword";
import metaDescriptionLength from "./researches/metaDescriptionLength.js";
import morphology from "./researches/getWordForms";
import pageTitleWidth from "./researches/pageTitleWidth.js";
import readingTime from "./researches/readingTime";
import sentences from "./researches/sentences";
import videoCount from "./researches/videoCount";
import wordCountInText from "./researches/wordCountInText.js";
// All helpers.
import memoizedTokenizer from "./helpers/sentence/memoizedSentenceTokenizer";
/**
* The researches contains all the researches
*/
export default class AbstractResearcher {
/**
* Constructor
* @param {Paper} paper The Paper object that is needed within the researches.
*
* @constructor
*/
constructor( paper ) {
this.paper = paper;
// We expose the deprecated keywordCountInUrl for backwards compatibility.
this.defaultResearches = {
altTagCount,
countSentencesFromText,
findKeywordInFirstParagraph,
findKeyphraseInSEOTitle,
findTransitionWords,
functionWordsInKeyphrase,
getAnchorsWithKeyphrase,
getFleschReadingScore,
getKeyphraseCount,
getKeyphraseDensity,
getKeywordDensity,
getLinks,
getLinkStatistics,
getParagraphs,
getParagraphLength,
getProminentWordsForInsights,
getProminentWordsForInternalLinking,
getSentenceBeginnings,
getSubheadingTextLengths,
h1s,
imageCount,
keyphraseLength,
keywordCount,
keywordCountInSlug,
keywordCountInUrl,
matchKeywordInSubheadings,
metaDescriptionKeyword,
metaDescriptionLength,
morphology,
pageTitleWidth,
readingTime,
sentences,
wordCountInText,
videoCount,
getPassiveVoiceResult,
};
this._data = {};
this.customResearches = {};
this.helpers = {
memoizedTokenizer,
};
this.config = {};
}
/**
* Set the Paper associated with the Researcher.
*
* @param {Paper} paper The Paper to use within the Researcher.
*
* @throws {InvalidTypeError} Parameter needs to be an instance of the Paper object.
*
* @returns {void}
*/
setPaper( paper ) {
this.paper = paper;
}
/**
* Add a custom research that will be available within the Researcher.
*
* @param {string} name A name to reference the research by.
* @param {function} research The function to be added to the Researcher.
*
* @throws {MissingArgument} Research name cannot be empty.
* @throws {InvalidTypeError} The research requires a valid Function callback.
*
* @returns {void}
*/
addResearch( name, research ) {
if ( isUndefined( name ) || isEmpty( name ) ) {
throw new MissingArgument( "Research name cannot be empty" );
}
if ( ! ( research instanceof Function ) ) {
throw new InvalidTypeError( "The research requires a Function callback." );
}
this.customResearches[ name ] = research;
}
/**
* Add a custom helper that will be available within the Researcher.
*
* @param {string} name A name to reference the helper by.
* @param {function} helper The function to be added to the Researcher.
*
* @throws {MissingArgument} Helper name cannot be empty.
* @throws {InvalidTypeError} The helper requires a valid Function callback.
*
* @returns {void}
*/
addHelper( name, helper ) {
if ( isUndefined( name ) || isEmpty( name ) ) {
throw new MissingArgument( "Helper name cannot be empty" );
}
if ( ! ( helper instanceof Function ) ) {
throw new InvalidTypeError( "The research requires a Function callback." );
}
this.helpers[ name ] = helper;
}
/**
* Add a custom configuration that will be available within the Researcher.
*
* @param {string} name A name to reference the helper by.
* @param {*} config The configuration to be added to the Researcher.
*
* @throws {MissingArgument} Configuration name and the configuration itself cannot be empty.
*
* @returns {void}
*/
addConfig( name, config ) {
if ( isUndefined( name ) || isEmpty( name ) ) {
throw new MissingArgument( "Failed to add the custom researcher config. Config name cannot be empty." );
}
if ( isUndefined( config ) || isEmpty( config ) ) {
throw new MissingArgument( "Failed to add the custom researcher config. Config cannot be empty." );
}
this.config[ name ] = config;
}
/**
* Check whether or not the research is known by the Researcher.
*
* @param {string} name The name to reference the research by.
*
* @returns {boolean} Whether or not the research is known by the Researcher.
*/
hasResearch( name ) {
return Object.keys( this.getAvailableResearches() ).filter(
function( research ) {
return research === name;
} ).length > 0;
}
/**
* Check whether or not the helper is known by the Researcher.
*
* @param {string} name The name to reference the helper by.
*
* @returns {boolean} Whether or not the helper is known by the Researcher.
*/
hasHelper( name ) {
return Object.keys( this.getAvailableHelpers() ).filter(
function( helper ) {
return helper === name;
} ).length > 0;
}
/**
* Check whether or not the config is known by the Researcher.
*
* @param {string} name The name to reference the config by.
*
* @returns {boolean} Whether or not the config is known by the Researcher.
*/
hasConfig( name ) {
return Object.keys( this.getAvailableConfig() ).filter(
function( config ) {
return config === name;
} ).length > 0;
}
/**
* Return all available researches.
*
* @returns {Object} An object containing all available researches.
*/
getAvailableResearches() {
return merge( this.defaultResearches, this.customResearches );
}
/**
* Return all available helpers.
*
* @returns {Object} An object containing all available helpers.
*/
getAvailableHelpers() {
return this.helpers;
}
/**
* Return all available configuration.
*
* @returns {Object} An object containing all available configuration.
*/
getAvailableConfig() {
return this.config;
}
/**
* Return the Research by name.
*
* @param {string} name The name to reference the research by.
*
* @returns {*} Returns the result of the research or false if research does not exist.
*
* @throws {MissingArgument} Research name cannot be empty.
*/
getResearch( name ) {
if ( isUndefined( name ) || isEmpty( name ) ) {
throw new MissingArgument( "Research name cannot be empty" );
}
if ( ! this.hasResearch( name ) ) {
return false;
}
return this.getAvailableResearches()[ name ]( this.paper, this );
}
/**
* Add research data to the researcher by the research name.
*
* @param {string} research The identifier of the research.
* @param {Object} data The data object.
*
* @returns {void}.
*/
addResearchData( research, data ) {
this._data[ research ] = data;
}
/**
* Return the research data from a research data provider by research name.
*
* @param {string} research The identifier of the research.
*
* @returns {*} The data provided by the provider, false if the data do not exist
*/
getData( research ) {
if ( this._data.hasOwnProperty( research ) ) {
return this._data[ research ];
}
return false;
}
/**
* Return language specific configuration by configuration name.
*
* @param {string} name The name of the configuration.
*
* @returns {*} The configuration, false if the configuration does not exist.
*/
getConfig( name ) {
if ( this.config.hasOwnProperty( name ) ) {
return this.config[ name ];
}
return false;
}
/**
* Return language specific helper by helper name.
*
* @param {string} name The name of the helper.
*
* @returns {*} The helper, false if the helper does not exist.
*/
getHelper( name ) {
if ( this.helpers.hasOwnProperty( name ) ) {
return this.helpers[ name ];
}
return false;
}
}