UNPKG

yoastseo-dep

Version:

Yoast clientside page analysis

86 lines (74 loc) 3.82 kB
import matchWords from "../helpers/match/matchTextWithArray"; import getSentences from "../helpers/sentence/getSentences"; /** * Replaces found keyword forms in the given description. * * @param {string} description The description to remove the matched keyword forms from. * @param {Object[]} matchedKeywordForms The matched keyword forms to remove from the description. * @param {Number} maxToRemove The maximum amount of matches of each individual keyword to remove. * * @returns {string} The description with the keywords removed. */ const replaceFoundKeywordForms = function( description, matchedKeywordForms, maxToRemove ) { // Replace matches so we do not match them for synonyms. matchedKeywordForms.forEach( keywordForm => keywordForm.matches.slice( 0, maxToRemove ).forEach( match => { description = description.replace( match, "" ); } ) ); return description; }; /** * Counts the number of full keyphrase matches in the given sentence. Takes synonyms into account. * A full keyphrase is when all keywords in the keyphrase match. * * @param {string} sentence The sentence that needs to be analyzed. * @param {Object} topicForms The keyphrase (and its optional synonyms') word forms. * @param {string} locale The current locale. * @param {function} matchWordCustomHelper The language-specific helper function to match word in text. * * @returns {Number} The number of matched keyphrases in the sentence. */ const matchPerSentence = function( sentence, topicForms, locale, matchWordCustomHelper ) { // Focus keyphrase matches. const matchesKeyphrase = topicForms.keyphraseForms.map( keywordForms => matchWords( sentence, keywordForms, locale, matchWordCustomHelper ) ); // Count the number of matches that contain every word in the entire keyphrase. const fullKeyphraseMatches = Math.min( ...matchesKeyphrase.map( match => match.count ) ); // Replace all full keyphrase matches so we do not match them for synonyms. sentence = replaceFoundKeywordForms( sentence, matchesKeyphrase, fullKeyphraseMatches ); // Keyphrase synonyms matches. const fullSynonymsMatches = topicForms.synonymsForms.map( synonymForms => { // Synonym keyphrase matches. const matches = synonymForms.map( keywordForms => matchWords( sentence, keywordForms, locale, matchWordCustomHelper ) ); // Count the number of matches that contain every word in the entire synonym keyphrase. const fullSynonymMatches = Math.min( ...matches.map( match => match.count ) ); // Replace all full matches so we do not match them for other synonyms. sentence = replaceFoundKeywordForms( sentence, matchesKeyphrase, fullSynonymMatches ); return fullSynonymMatches; } ); return [ fullKeyphraseMatches, ...fullSynonymsMatches ].reduce( ( sum, count ) => sum + count, 0 ); }; /** * Counts the number of full keyphrase matches in the description. * * @param {Paper} paper The paper object containing the description. * @param {Researcher} researcher The researcher object to gather researchers from. * * @returns {Number} The number of keyphrase matches for the entire description. */ export default function( paper, researcher ) { const description = paper.getDescription(); const locale = paper.getLocale(); const topicForms = researcher.getResearch( "morphology" ); const matchWordCustomHelper = researcher.getHelper( "matchWordCustomHelper" ); const memoizedTokenizer = researcher.getHelper( "memoizedTokenizer" ); const sentences = getSentences( description, memoizedTokenizer ); const sentenceMatches = sentences.map( sentence => matchPerSentence( sentence, topicForms, locale, matchWordCustomHelper ) ); return sentenceMatches.reduce( ( sum, count ) => sum + count, 0 ); }