UNPKG

yoastseo

Version:

Yoast client-side content analysis

185 lines (177 loc) 8.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _lodash = require("lodash"); var _assessment = _interopRequireDefault(require("../assessment")); var _AssessmentResult = _interopRequireDefault(require("../../../values/AssessmentResult")); var _helpers = require("../../../helpers"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * Represents the assessment checks whether the product has a SKU. */ class ProductSKUAssessment extends _assessment.default { /** * Constructs a product SKU assessment. * * @param {Object} config Potential additional config for the assessment. * @param {Object} [config.scores] The scores to use for the assessment. * @param {number} [config.scores.good] The score to return if the product has a SKU. * @param {number} [config.scores.ok] The score to return if the product doesn't have a SKU. * @param {string} [config.urlTitle] The URL to the article about this assessment. * @param {string} [config.urlCallToAction] The URL to the help article for this assessment. * @param {boolean} [config.assessVariants] Whether to assess variants. * @param {boolean} [config.shouldShowEditButton] Whether to show edit button. * @param {string} [config.editFieldName] The name of the field to edit. * @param {object} [config.callbacks] The callbacks to use for the assessment. * @param {function} [config.callbacks.getResultTexts] The function that returns the result texts. * * @returns {void} */ constructor(config = {}) { super(); const defaultConfig = { scores: { good: 9, ok: 6 }, urlTitle: "https://yoa.st/4lw", urlCallToAction: "https://yoa.st/4lx", assessVariants: false, shouldShowEditButton: false, editFieldName: "SKU", callbacks: {} }; this.identifier = "productSKU"; this._config = (0, _lodash.merge)(defaultConfig, config); } /** * Executes the assessment and returns a result based on the research. * * @param {Paper} paper The paper to use for the assessment. * * @returns {AssessmentResult} An assessment result with the score and formatted text. */ getResult(paper) { const productSKUData = paper.getCustomData(); const result = this.scoreProductSKU(productSKUData, this._config); const assessmentResult = new _AssessmentResult.default(); if (result) { assessmentResult.setScore(result.score); assessmentResult.setText(result.text); } if (assessmentResult.getScore() < 9 && this._config.shouldShowEditButton) { assessmentResult.setHasJumps(true); // Provide `this._config.editFieldName` when initialize this assessment with the value "SKU". We recommend to provide the string as a translation string. assessmentResult.setEditFieldName(this._config.editFieldName); } return assessmentResult; } /** * Checks whether the assessment is applicable. * It is not applicable when the product has variants, and we don't want to assess variants (this is the case for Shopify * since we cannot at the moment easily access variant data in Shopify). * It is also not applicable when we cannot retrieve the SKU (this can be the case if other plugins remove/change the SKU * input field in such as way that we cannot detect it). * * @param {Paper} paper The paper to check. * * @returns {Boolean} Whether the assessment is applicable. */ isApplicable(paper) { const customData = paper.getCustomData(); /* * If the global SKU cannot be retrieved, the assessment shouldn't be applicable if the product is a simple * or external product, or doesn't have variants. Even though in reality a simple or external product doesn't have variants, * this double check is added because the hasVariants variable doesn't always update correctly when changing product type. */ if (customData.canRetrieveGlobalSku === false && (["simple", "external"].includes(customData.productType) || customData.hasVariants === false)) { return false; } // If variant identifiers cannot be retrieved for a variable product with variants, the assessment shouldn't be applicable. if (customData.canRetrieveVariantSkus === false && customData.hasVariants === true && customData.productType === "variable") { return false; } // Assessment is not applicable if we don't want to assess variants and the product has variants. return !(this._config.assessVariants === false && customData.hasVariants); } /** * Returns a score based on whether the product (variants) have a SKU. * * @param {Object} productSKUData Whether product has variants, global SKU, and variant SKU. * @param {Object} config The configuration to use. * * @returns {{score: number, text: string} | {}} The result object with score and text * or empty object if no score should be returned. */ scoreProductSKU(productSKUData, config) { const { good, okay } = this.getFeedbackStrings(); // Apply the following scoring conditions to products without variants. if (["simple", "external", "grouped"].includes(productSKUData.productType) || productSKUData.productType === "variable" && !productSKUData.hasVariants) { if (!productSKUData.hasGlobalSKU) { return { score: config.scores.ok, text: okay.withoutVariants }; } return { score: config.scores.good, text: good.withoutVariants }; } else if (productSKUData.productType === "variable" && productSKUData.hasVariants) { // If we want to assess variants, if product has variants and not all variants have a SKU, return orange bullet. // If all variants have a SKU, return green bullet. if (!productSKUData.doAllVariantsHaveSKU) { return { score: config.scores.ok, text: okay.withVariants }; } return { score: config.scores.good, text: good.withVariants }; } return {}; } /** * Gets the feedback strings for the assessment. * If you want to override the feedback strings, you can do so by providing a custom callback in the config: `this._config.callbacks.getResultTexts`. * The callback function should return an object with the following properties: * - good: {withoutVariants: string, withVariants: string} * - okay: {withoutVariants: string, withVariants: string} * * @returns {{good: {withoutVariants: string, withVariants: string}, okay: {withoutVariants: string, withVariants: string}}} The feedback strings. */ getFeedbackStrings() { // `urlTitleAnchorOpeningTag` represents the anchor opening tag with the URL to the article about this assessment. const urlTitleAnchorOpeningTag = (0, _helpers.createAnchorOpeningTag)(this._config.urlTitle); // `urlActionAnchorOpeningTag` represents the anchor opening tag with the URL for the call to action. const urlActionAnchorOpeningTag = (0, _helpers.createAnchorOpeningTag)(this._config.urlCallToAction); if (!this._config.callbacks.getResultTexts) { const defaultResultTexts = { good: { withoutVariants: "%1$sSKU%3$s: Your product has a SKU. Good job!", withVariants: "%1$sSKU%3$s: All your product variants have a SKU. Good job!" }, okay: { withoutVariants: "%1$sSKU%3$s: Your product is missing a SKU. %2$sInclude it if you can, as it will help search engines to better understand your content.%3$s", withVariants: "%1$sSKU%3$s: Not all your product variants have a SKU. %2$sInclude it if you can, as it will help search engines to better understand your content.%3$s" } }; defaultResultTexts.good = (0, _lodash.mapValues)(defaultResultTexts.good, resultText => this.formatResultText(resultText, urlTitleAnchorOpeningTag, urlActionAnchorOpeningTag)); defaultResultTexts.okay = (0, _lodash.mapValues)(defaultResultTexts.okay, resultText => this.formatResultText(resultText, urlTitleAnchorOpeningTag, urlActionAnchorOpeningTag)); return defaultResultTexts; } return this._config.callbacks.getResultTexts({ urlTitleAnchorOpeningTag, urlActionAnchorOpeningTag }); } } exports.default = ProductSKUAssessment; //# sourceMappingURL=ProductSKUAssessment.js.map