yoastseo
Version:
Yoast client-side content analysis
164 lines (153 loc) • 8.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.StemOriginalPair = StemOriginalPair;
exports.buildStems = exports.TopicPhrase = void 0;
exports.collectStems = collectStems;
exports.primeLanguageSpecificData = void 0;
var _getWords = _interopRequireDefault(require("../word/getWords.js"));
var _quotes = require("../sanitize/quotes");
var _wordBoundariesWithoutPunctuation = require("../../../config/wordBoundariesWithoutPunctuation");
var _lodash = require("lodash");
var _isDoubleQuoted = _interopRequireDefault(require("../match/isDoubleQuoted"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* A TopicPhrase (i.e., a keyphrase or synonym) with stem-original pairs for the words in the topic phrase.
*/
class TopicPhrase {
/**
* Constructs a new TopicPhrase.
*
* @param {StemOriginalPair[]} stemOriginalPairs The stem-original pairs for the words in the topic phrase.
* @param {boolean} exactMatch Whether the topic phrase is an exact match.
*
* @constructor
*/
constructor(stemOriginalPairs = [], exactMatch = false) {
this.stemOriginalPairs = stemOriginalPairs;
this.exactMatch = exactMatch;
}
/**
* Returns all stems in the topic phrase.
*
* @returns {string[]|[]} The stems in the topic phrase or empty array if the topic phrase is exact match.
*/
getStems() {
// An exact match keyphrase doesn't have stems.
if (this.exactMatch) {
return [];
}
return this.stemOriginalPairs.map(stemOriginalPair => stemOriginalPair.stem);
}
}
/**
* A stem-original pair ƒor a word in a topic phrase.
*
* @param {string} stem The stem of the topic phrase word.
* @param {string} original The original word form the topic phrase (unsanitized)
*
* @constructor
*/
exports.TopicPhrase = TopicPhrase;
function StemOriginalPair(stem, original) {
this.stem = stem;
this.original = original;
}
/**
* Analyzes the focus keyword string or one synonym phrase.
* Checks if morphology is requested or if the user wants to match the exact string.
* If morphology is required, the module finds a stem for all words (if no function words list is available), or
* for all content words (i.e., excluding prepositions, articles, conjunctions, if the function words list is available).
*
* @param {string} keyphrase The keyphrase of the paper (or a synonym phrase) to get stem for.
* @param {function} stemmer The language-specific stemmer.
* @param {string[]} functionWords The language-specific function words.
* @param {boolean} areHyphensWordBoundaries Whether hyphens should be treated as word boundaries.
*
* @returns {TopicPhrase} Object with an array of StemOriginalPairs of all (content) words in the keyphrase or synonym
* phrase and information about whether the keyphrase/synonym should be matched exactly.
*/
const buildStems = function (keyphrase, stemmer, functionWords, areHyphensWordBoundaries) {
if ((0, _lodash.isUndefined)(keyphrase) || keyphrase === "") {
return new TopicPhrase();
}
// If the keyphrase is embedded in double quotation marks, return the keyphrase itself, without the outermost quotation marks.
if ((0, _isDoubleQuoted.default)(keyphrase)) {
keyphrase = keyphrase.substring(1, keyphrase.length - 1);
return new TopicPhrase([new StemOriginalPair((0, _lodash.escapeRegExp)(keyphrase), keyphrase)], true);
}
/*
* If hyphens should be treated as word boundaries, pass a custom word boundary regex string that includes whitespaces,
* hyphens (u002d), and en-dashes (u2013). Otherwise, pass a regex that includes only whitespaces and en-dashes.
*/
let keyphraseWords = areHyphensWordBoundaries ? (0, _getWords.default)(keyphrase, _wordBoundariesWithoutPunctuation.WORD_BOUNDARY_WITH_HYPHEN) : (0, _getWords.default)(keyphrase, _wordBoundariesWithoutPunctuation.WORD_BOUNDARY_WITHOUT_HYPHEN);
// Filter function words from the keyphrase. Don't filter if the keyphrase only consists of function words.
const wordsWithoutFunctionWords = keyphraseWords.filter(word => !functionWords.includes(word));
if (wordsWithoutFunctionWords.length > 0) {
keyphraseWords = wordsWithoutFunctionWords;
}
// Return a stem-original pair with a stem.
const stemOriginalPairs = keyphraseWords.map(word => {
return new StemOriginalPair(stemmer((0, _quotes.normalizeSingle)((0, _lodash.escapeRegExp)(word))), word);
});
return new TopicPhrase(stemOriginalPairs);
};
/**
* Builds stems of words of the keyphrase and of each synonym phrase.
*
* @param {string} keyphrase The paper's keyphrase.
* @param {string[]} synonyms The paper's synonyms.
* @param {function} stemmer The language-specific stemmer (if available).
* @param {string[]} functionWords The language-specific function words.
* @param {boolean} areHyphensWordBoundaries Whether hyphens should be treated as word boundaries.
*
* @returns {Object} Object with an array of stems of words in the keyphrase and an array of arrays of stems of words in the synonyms.
*/
exports.buildStems = buildStems;
const collectKeyphraseAndSynonymsStems = function (keyphrase, synonyms, stemmer, functionWords, areHyphensWordBoundaries) {
const keyphraseStems = buildStems(keyphrase, stemmer, functionWords, areHyphensWordBoundaries);
const synonymsStems = synonyms.map(synonym => buildStems(synonym, stemmer, functionWords, areHyphensWordBoundaries));
return {
keyphraseStems,
synonymsStems
};
};
/**
* Caches stems depending on the currently available stemmer and functionWords and (separately) keyphrase and synonyms.
* In this way, if the stemmer and functionWords remain the same in multiple calls of this function, the function
* that collects actual stems only needs to check if the keyphrase and synonyms also remain the
* same to return the cached result. The joining of keyphrase and synonyms for this function is needed,
* because by default memoize caches by the first key only, which in the current case would mean that the function would
* return the cached forms if the keyphrase has not changed (without checking if synonyms were changed).
*
* @param {function} stemmer The language-specific stemmer (if available).
* @param {string[]} functionWords The language-specific function words.
* @param {boolean} areHyphensWordBoundaries Whether hyphens should be treated as word boundaries.
*
* @returns {function} The function that collects the stems for a given set of keyphrase, synonyms, stemmer and functionWords.
*/
const primeLanguageSpecificData = exports.primeLanguageSpecificData = (0, _lodash.memoize)((stemmer, functionWords, areHyphensWordBoundaries) => {
return (0, _lodash.memoize)((keyphrase, synonyms) => {
return collectKeyphraseAndSynonymsStems(keyphrase, synonyms, stemmer, functionWords, areHyphensWordBoundaries);
}, (keyphrase, synonyms) => {
return keyphrase + "," + synonyms.join(",");
});
});
/**
* Retrieves stems of words of the keyphrase and of each synonym phrase using the function that caches
* the results of previous calls of this function.
*
* @param {string} keyphrase The paper's keyphrase.
* @param {string[]} synonyms The paper's synonyms.
* @param {function} stemmer The language-specific stemmer (if available).
* @param {string[]} functionWords The language-specific function words.
* @param {boolean} areHyphensWordBoundaries Whether hyphens should be treated as word boundaries.
*
* @returns {Object} Object with an array of stems of words in the keyphrase and an array of arrays of stems of words in the synonyms.
*/
function collectStems(keyphrase, synonyms, stemmer, functionWords, areHyphensWordBoundaries) {
const collectStemsWithLanguageSpecificData = primeLanguageSpecificData(stemmer, functionWords, areHyphensWordBoundaries);
return collectStemsWithLanguageSpecificData(keyphrase, synonyms);
}
//# sourceMappingURL=buildTopicStems.js.map