axyseo 2.1.55 → 2.1.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,12 @@ var _isChineseText = _interopRequireDefault(require("../helpers/language/isChine
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
13
  /** @module analyses/findKeywordInFirstParagraph */
14
14
 
15
+ // Matches common UI-marker class names (label, eyebrow, kicker, etc.) used for
16
+ // short text placed above a heading. Anchored to the start, with a boundary so
17
+ // `header-label` or `tagline` don't match.
18
+ const LABEL_LIKE_CLASS_REGEX = /^(label|eyebrow|kicker|overline|pretitle|subtitle|badge|tag|chip|meta|category|breadcrumb)(\b|[-_])/i;
19
+ const MIN_INTRO_WORDS = 5;
20
+
15
21
  /**
16
22
  * Checks if the introductory paragraph contains keyphrase or synonyms.
17
23
  * First splits the first paragraph by sentences. Finds the first paragraph which contains sentences e.g., not an image).
@@ -42,6 +48,21 @@ function _default(paper, researcher) {
42
48
  paragraphs = paragraphs.filter(paragraph => {
43
49
  return !(paragraph.childNodes && paragraph.childNodes[0] && (0, _helpers.createShortcodeTagsRegex)(['caption']).test(paragraph.childNodes[0].value));
44
50
  });
51
+ // Filter UI label/eyebrow/kicker paragraphs that sit before the heading
52
+ // (e.g., <p class="label">CATEGORY</p>). These are visual markers, not real
53
+ // intro paragraphs, and would cause false negatives on keyword-in-intro checks.
54
+ paragraphs = paragraphs.filter(paragraph => {
55
+ const classSet = paragraph.attributes && paragraph.attributes.class;
56
+ if (classSet instanceof Set) {
57
+ for (const cls of classSet) {
58
+ if (LABEL_LIKE_CLASS_REGEX.test(cls)) {
59
+ return false;
60
+ }
61
+ }
62
+ }
63
+ const wordCount = (paragraph.innerText() || '').trim().split(/\s+/).filter(Boolean).length;
64
+ return wordCount >= MIN_INTRO_WORDS;
65
+ });
45
66
  const firstParagraph = paragraphs[0];
46
67
  const topicForms = researcher.getResearch('morphology');
47
68
  let matchWordCustomHelper = researcher.getHelper('matchWordCustomHelper');
@@ -1 +1 @@
1
- {"version":3,"file":"findKeywordInFirstParagraph.js","names":["_lodash","require","_findKeywordFormsInString","_getSentencesFromTree","_helpers","_isChineseText","_interopRequireDefault","e","__esModule","default","_default","paper","researcher","paragraphs","getResearch","filter","paragraph","parentNode","getParentNode","isImplicit","name","childNodes","createShortcodeTagsRegex","test","value","firstParagraph","topicForms","matchWordCustomHelper","getHelper","locale","getLocale","isChineseText","getKeyword","innerText","text","word","textToSearch","matches","lowerText","toLowerCase","lowerWord","startIndex","index","indexOf","push","length","startOffset","sourceCodeLocation","mappedBlocks","_attributes","wpBlocks","filteredIntroductionBlock","block","inRange","endOffset","result","foundInOneSentence","foundInParagraph","keyphraseOrSynonym","introduction","parentBlock","isEmpty","sentences","map","sentence","useSynonyms","firstResultSentence","findTopicFormsInString","find","resultSentence","percentWordMatches","resultParagraph"],"sources":["../../../../src/languageProcessing/researches/findKeywordInFirstParagraph.js"],"sourcesContent":["/** @module analyses/findKeywordInFirstParagraph */\nimport {inRange, isEmpty} from 'lodash';\n\nimport {findTopicFormsInString} from '../helpers/match/findKeywordFormsInString.js';\nimport {getParentNode} from '../helpers/sentence/getSentencesFromTree';\nimport {createShortcodeTagsRegex} from '../helpers';\nimport isChineseText from '../helpers/language/isChineseText';\n\n/**\n * Checks if the introductory paragraph contains keyphrase or synonyms.\n * First splits the first paragraph by sentences. Finds the first paragraph which contains sentences e.g., not an image).\n * (1) Tries to find all (content) words from the keyphrase or a synonym phrase within one sentence.\n * If found all words within one sentence, returns an object with foundInOneSentence = true and keyphraseOrSynonym = \"keyphrase\"\n * or \"synonym\".\n * If it did not find all words within one sentence, goes ahead with matching the keyphrase with the entire first paragraph.\n * (2) Tries to find all (content) words from the keyphrase or a synonym phrase within the paragraph.\n * If found all words within the paragraph, returns an object with foundInOneSentence = false, foundInParagraph = true,\n * and keyphraseOrSynonym = \"keyphrase\" or \"synonym\".\n * If found not all words within the paragraph of nothing at all, returns an object with foundInOneSentence = false,\n * foundInParagraph = false, and keyphraseOrSynonym = \"\".\n *\n * @param {Paper} paper The text to check for paragraphs.\n * @param {Researcher} researcher The researcher to use for analysis.\n *\n * @returns {Object} Whether the keyphrase words were found in one sentence, whether the keyphrase words were found in\n * the paragraph, whether a keyphrase or a synonym phrase was matched.\n */\nexport default function(paper, researcher) {\n let paragraphs = researcher.getResearch('getParagraphs');\n // Filter captions from non-Classic editors.\n paragraphs = paragraphs.filter(paragraph => {\n const parentNode = getParentNode(paper, paragraph);\n return !(paragraph.isImplicit && parentNode && parentNode.name === 'figcaption');\n });\n // Filter captions from Classic editor and from classic block inside Block editor.\n paragraphs = paragraphs.filter(paragraph => {\n return !(\n paragraph.childNodes &&\n paragraph.childNodes[0] &&\n createShortcodeTagsRegex(['caption']).test(paragraph.childNodes[0].value)\n );\n });\n const firstParagraph = paragraphs[0];\n\n const topicForms = researcher.getResearch('morphology');\n let matchWordCustomHelper = researcher.getHelper('matchWordCustomHelper');\n const locale = paper.getLocale();\n\n // Auto-detect Chinese and use Chinese helper if not already available\n if (\n !matchWordCustomHelper &&\n isChineseText(paper.getKeyword() + ' ' + (firstParagraph ? firstParagraph.innerText() : ''))\n ) {\n // Use Chinese word matching for Chinese text\n matchWordCustomHelper = function(text, word) {\n const textToSearch = typeof text === 'string' ? text : text.text || text;\n const matches = [];\n\n if (!textToSearch || !word) {\n return matches;\n }\n\n const lowerText = textToSearch.toLowerCase();\n const lowerWord = word.toLowerCase();\n\n let startIndex = 0;\n let index;\n\n while ((index = lowerText.indexOf(lowerWord, startIndex)) !== -1) {\n matches.push(word);\n startIndex = index + lowerWord.length;\n }\n\n return matches;\n };\n }\n const startOffset = firstParagraph && firstParagraph.sourceCodeLocation.startOffset;\n\n const mappedBlocks = paper._attributes.wpBlocks;\n const filteredIntroductionBlock =\n mappedBlocks &&\n mappedBlocks.filter(block => inRange(startOffset, block.startOffset, block.endOffset))[0];\n const result = {\n foundInOneSentence: false,\n foundInParagraph: false,\n keyphraseOrSynonym: '',\n introduction: firstParagraph,\n parentBlock: filteredIntroductionBlock || null\n };\n\n if (isEmpty(firstParagraph)) {\n return result;\n }\n\n const sentences = firstParagraph.sentences.map(sentence => sentence.text);\n // Use both keyphrase and synonyms to match topic words in the first paragraph.\n const useSynonyms = true;\n\n if (!isEmpty(sentences)) {\n const firstResultSentence = sentences\n .map(sentence =>\n findTopicFormsInString(topicForms, sentence, useSynonyms, locale, matchWordCustomHelper)\n )\n .find(resultSentence => resultSentence.percentWordMatches === 100);\n\n if (firstResultSentence) {\n result.foundInOneSentence = true;\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = firstResultSentence.keyphraseOrSynonym;\n return result;\n }\n\n const resultParagraph = findTopicFormsInString(\n topicForms,\n firstParagraph.innerText(),\n useSynonyms,\n locale,\n matchWordCustomHelper\n );\n if (resultParagraph.percentWordMatches === 100) {\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = resultParagraph.keyphraseOrSynonym;\n return result;\n }\n }\n\n return result;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"findKeywordInFirstParagraph.js","names":["_lodash","require","_findKeywordFormsInString","_getSentencesFromTree","_helpers","_isChineseText","_interopRequireDefault","e","__esModule","default","LABEL_LIKE_CLASS_REGEX","MIN_INTRO_WORDS","_default","paper","researcher","paragraphs","getResearch","filter","paragraph","parentNode","getParentNode","isImplicit","name","childNodes","createShortcodeTagsRegex","test","value","classSet","attributes","class","Set","cls","wordCount","innerText","trim","split","Boolean","length","firstParagraph","topicForms","matchWordCustomHelper","getHelper","locale","getLocale","isChineseText","getKeyword","text","word","textToSearch","matches","lowerText","toLowerCase","lowerWord","startIndex","index","indexOf","push","startOffset","sourceCodeLocation","mappedBlocks","_attributes","wpBlocks","filteredIntroductionBlock","block","inRange","endOffset","result","foundInOneSentence","foundInParagraph","keyphraseOrSynonym","introduction","parentBlock","isEmpty","sentences","map","sentence","useSynonyms","firstResultSentence","findTopicFormsInString","find","resultSentence","percentWordMatches","resultParagraph"],"sources":["../../../../src/languageProcessing/researches/findKeywordInFirstParagraph.js"],"sourcesContent":["/** @module analyses/findKeywordInFirstParagraph */\nimport {inRange, isEmpty} from 'lodash';\n\nimport {findTopicFormsInString} from '../helpers/match/findKeywordFormsInString.js';\nimport {getParentNode} from '../helpers/sentence/getSentencesFromTree';\nimport {createShortcodeTagsRegex} from '../helpers';\nimport isChineseText from '../helpers/language/isChineseText';\n\n// Matches common UI-marker class names (label, eyebrow, kicker, etc.) used for\n// short text placed above a heading. Anchored to the start, with a boundary so\n// `header-label` or `tagline` don't match.\nconst LABEL_LIKE_CLASS_REGEX = /^(label|eyebrow|kicker|overline|pretitle|subtitle|badge|tag|chip|meta|category|breadcrumb)(\\b|[-_])/i;\nconst MIN_INTRO_WORDS = 5;\n\n/**\n * Checks if the introductory paragraph contains keyphrase or synonyms.\n * First splits the first paragraph by sentences. Finds the first paragraph which contains sentences e.g., not an image).\n * (1) Tries to find all (content) words from the keyphrase or a synonym phrase within one sentence.\n * If found all words within one sentence, returns an object with foundInOneSentence = true and keyphraseOrSynonym = \"keyphrase\"\n * or \"synonym\".\n * If it did not find all words within one sentence, goes ahead with matching the keyphrase with the entire first paragraph.\n * (2) Tries to find all (content) words from the keyphrase or a synonym phrase within the paragraph.\n * If found all words within the paragraph, returns an object with foundInOneSentence = false, foundInParagraph = true,\n * and keyphraseOrSynonym = \"keyphrase\" or \"synonym\".\n * If found not all words within the paragraph of nothing at all, returns an object with foundInOneSentence = false,\n * foundInParagraph = false, and keyphraseOrSynonym = \"\".\n *\n * @param {Paper} paper The text to check for paragraphs.\n * @param {Researcher} researcher The researcher to use for analysis.\n *\n * @returns {Object} Whether the keyphrase words were found in one sentence, whether the keyphrase words were found in\n * the paragraph, whether a keyphrase or a synonym phrase was matched.\n */\nexport default function(paper, researcher) {\n let paragraphs = researcher.getResearch('getParagraphs');\n // Filter captions from non-Classic editors.\n paragraphs = paragraphs.filter(paragraph => {\n const parentNode = getParentNode(paper, paragraph);\n return !(paragraph.isImplicit && parentNode && parentNode.name === 'figcaption');\n });\n // Filter captions from Classic editor and from classic block inside Block editor.\n paragraphs = paragraphs.filter(paragraph => {\n return !(\n paragraph.childNodes &&\n paragraph.childNodes[0] &&\n createShortcodeTagsRegex(['caption']).test(paragraph.childNodes[0].value)\n );\n });\n // Filter UI label/eyebrow/kicker paragraphs that sit before the heading\n // (e.g., <p class=\"label\">CATEGORY</p>). These are visual markers, not real\n // intro paragraphs, and would cause false negatives on keyword-in-intro checks.\n paragraphs = paragraphs.filter(paragraph => {\n const classSet = paragraph.attributes && paragraph.attributes.class;\n if (classSet instanceof Set) {\n for (const cls of classSet) {\n if (LABEL_LIKE_CLASS_REGEX.test(cls)) {\n return false;\n }\n }\n }\n const wordCount = (paragraph.innerText() || '')\n .trim()\n .split(/\\s+/)\n .filter(Boolean).length;\n return wordCount >= MIN_INTRO_WORDS;\n });\n const firstParagraph = paragraphs[0];\n\n const topicForms = researcher.getResearch('morphology');\n let matchWordCustomHelper = researcher.getHelper('matchWordCustomHelper');\n const locale = paper.getLocale();\n\n // Auto-detect Chinese and use Chinese helper if not already available\n if (\n !matchWordCustomHelper &&\n isChineseText(paper.getKeyword() + ' ' + (firstParagraph ? firstParagraph.innerText() : ''))\n ) {\n // Use Chinese word matching for Chinese text\n matchWordCustomHelper = function(text, word) {\n const textToSearch = typeof text === 'string' ? text : text.text || text;\n const matches = [];\n\n if (!textToSearch || !word) {\n return matches;\n }\n\n const lowerText = textToSearch.toLowerCase();\n const lowerWord = word.toLowerCase();\n\n let startIndex = 0;\n let index;\n\n while ((index = lowerText.indexOf(lowerWord, startIndex)) !== -1) {\n matches.push(word);\n startIndex = index + lowerWord.length;\n }\n\n return matches;\n };\n }\n const startOffset = firstParagraph && firstParagraph.sourceCodeLocation.startOffset;\n\n const mappedBlocks = paper._attributes.wpBlocks;\n const filteredIntroductionBlock =\n mappedBlocks &&\n mappedBlocks.filter(block => inRange(startOffset, block.startOffset, block.endOffset))[0];\n const result = {\n foundInOneSentence: false,\n foundInParagraph: false,\n keyphraseOrSynonym: '',\n introduction: firstParagraph,\n parentBlock: filteredIntroductionBlock || null\n };\n\n if (isEmpty(firstParagraph)) {\n return result;\n }\n\n const sentences = firstParagraph.sentences.map(sentence => sentence.text);\n // Use both keyphrase and synonyms to match topic words in the first paragraph.\n const useSynonyms = true;\n\n if (!isEmpty(sentences)) {\n const firstResultSentence = sentences\n .map(sentence =>\n findTopicFormsInString(topicForms, sentence, useSynonyms, locale, matchWordCustomHelper)\n )\n .find(resultSentence => resultSentence.percentWordMatches === 100);\n\n if (firstResultSentence) {\n result.foundInOneSentence = true;\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = firstResultSentence.keyphraseOrSynonym;\n return result;\n }\n\n const resultParagraph = findTopicFormsInString(\n topicForms,\n firstParagraph.innerText(),\n useSynonyms,\n locale,\n matchWordCustomHelper\n );\n if (resultParagraph.percentWordMatches === 100) {\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = resultParagraph.keyphraseOrSynonym;\n return result;\n }\n }\n\n return result;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -52,7 +52,6 @@ class RelatedKeywordsDensityAssessment extends _assessment.default {
52
52
  } = relatedKeywords;
53
53
  let status = 'good';
54
54
  const totalWords = Object.values(words).filter(word => word.percentage === 0);
55
- console.log("Related keyword density check: ", !hasDescription, (0, _lodash.isEmpty)(words), totalWords.length > 0);
56
55
  if (!hasDescription || (0, _lodash.isEmpty)(words) || totalWords.length > 0) {
57
56
  status = 'bad';
58
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RelatedKeywordsDensityAssessment.js","names":["_lodash","require","_AssessmentResult","_interopRequireDefault","_assessment","_analysis","e","__esModule","default","RelatedKeywordsDensityAssessment","Assessment","constructor","config","defaultConfig","id","RELATED_KEYWORDS_DENSITY_ID","fixPosition","ctaType","docUrl","priority","title","content","good","bad","improve","identifier","_config","merge","calculateResult","data","relatedKeywords","hasDescription","words","status","totalWords","Object","values","filter","word","percentage","console","log","isEmpty","length","score","getScore","MAIN_CONTENT_POINTS","getResult","paper","researcher","getResearch","getData","result","assessmentResult","AssessmentResult","setScore","setStatus","setData","isApplicable","exports"],"sources":["../../../../../src/scoring/assessments/seo/RelatedKeywordsDensityAssessment.js"],"sourcesContent":["import {isEmpty, merge} from 'lodash';\nimport AssessmentResult from '../../../values/AssessmentResult';\nimport Assessment from '../assessment';\nimport {MAIN_CONTENT_POINTS, RELATED_KEYWORDS_DENSITY_ID} from '@axyseo/const/analysis';\n\n/**\n * Represents the assessment that checks whether there are enough transition words in the text.\n */\nexport default class RelatedKeywordsDensityAssessment extends Assessment {\n /**\n * Sets the identifier and the config.\n *\n * @param {object} config The configuration to use.\n *\n * @returns {void}\n */\n constructor(config = {}) {\n super();\n\n const defaultConfig = {\n id: RELATED_KEYWORDS_DENSITY_ID,\n fixPosition: 'description',\n ctaType: 'fix',\n docUrl:\n 'https://docs.avada.io/seo-suite-help-center/seo-audit/on-page-seo/checklist#related-keywords',\n priority: 'high',\n title: 'Related keywords density',\n content: {\n good: 'Related keywords density optimized',\n bad:\n 'Use each secondary keyword from 0.5% to 1%. Place where it reads naturally.',\n improve: ''\n }\n };\n\n this.identifier = RELATED_KEYWORDS_DENSITY_ID;\n this._config = merge(defaultConfig, config);\n }\n\n /**\n *\n * @param data\n * @param relatedKeywords\n * @param hasDescription\n * @returns {{score: number, status: string, words}}\n */\n calculateResult(data, relatedKeywords, hasDescription) {\n const {words} = relatedKeywords;\n let status = 'good';\n const totalWords = Object.values(words).filter(word => word.percentage === 0);\n console.log(\"Related keyword density check: \", !hasDescription, isEmpty(words), totalWords.length > 0);\n if(!hasDescription || isEmpty(words) || totalWords.length > 0){\n status = 'bad';\n }\n const score = this.getScore(MAIN_CONTENT_POINTS, status);\n\n return {\n score,\n status,\n words\n };\n }\n\n /**\n *\n * @param paper\n * @param researcher\n * @returns {AssessmentResult}\n */\n getResult({paper, researcher}) {\n const relatedKeywords = researcher.getResearch('checkRelatedKeywords');\n const data = paper.getData();\n const hasDescription = paper.hasDescription();\n const result = this.calculateResult(data, relatedKeywords, hasDescription);\n const assessmentResult = new AssessmentResult({config: this._config});\n\n assessmentResult.setScore(result.score);\n assessmentResult.setStatus(result.status);\n assessmentResult.setData(result.words);\n\n return assessmentResult;\n }\n\n /**\n * Checks if the transition words assessment is applicable to the paper. Language-specific length requirements and methods of counting text length\n * may apply (e.g. for Japanese, the text should be counted in characters instead of words, which also makes the minimum required length higher).\n *\n * @param {Paper} paper The paper to check.\n * @param {Researcher} researcher The researcher object.\n *\n * @returns {boolean} Returns true if the language is available, the paper is not empty and the text is longer than the minimum required length.\n */\n isApplicable(paper, researcher) {\n return true;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"RelatedKeywordsDensityAssessment.js","names":["_lodash","require","_AssessmentResult","_interopRequireDefault","_assessment","_analysis","e","__esModule","default","RelatedKeywordsDensityAssessment","Assessment","constructor","config","defaultConfig","id","RELATED_KEYWORDS_DENSITY_ID","fixPosition","ctaType","docUrl","priority","title","content","good","bad","improve","identifier","_config","merge","calculateResult","data","relatedKeywords","hasDescription","words","status","totalWords","Object","values","filter","word","percentage","isEmpty","length","score","getScore","MAIN_CONTENT_POINTS","getResult","paper","researcher","getResearch","getData","result","assessmentResult","AssessmentResult","setScore","setStatus","setData","isApplicable","exports"],"sources":["../../../../../src/scoring/assessments/seo/RelatedKeywordsDensityAssessment.js"],"sourcesContent":["import {isEmpty, merge} from 'lodash';\nimport AssessmentResult from '../../../values/AssessmentResult';\nimport Assessment from '../assessment';\nimport {MAIN_CONTENT_POINTS, RELATED_KEYWORDS_DENSITY_ID} from '@axyseo/const/analysis';\n\n/**\n * Represents the assessment that checks whether there are enough transition words in the text.\n */\nexport default class RelatedKeywordsDensityAssessment extends Assessment {\n /**\n * Sets the identifier and the config.\n *\n * @param {object} config The configuration to use.\n *\n * @returns {void}\n */\n constructor(config = {}) {\n super();\n\n const defaultConfig = {\n id: RELATED_KEYWORDS_DENSITY_ID,\n fixPosition: 'description',\n ctaType: 'fix',\n docUrl:\n 'https://docs.avada.io/seo-suite-help-center/seo-audit/on-page-seo/checklist#related-keywords',\n priority: 'high',\n title: 'Related keywords density',\n content: {\n good: 'Related keywords density optimized',\n bad:\n 'Use each secondary keyword from 0.5% to 1%. Place where it reads naturally.',\n improve: ''\n }\n };\n\n this.identifier = RELATED_KEYWORDS_DENSITY_ID;\n this._config = merge(defaultConfig, config);\n }\n\n /**\n *\n * @param data\n * @param relatedKeywords\n * @param hasDescription\n * @returns {{score: number, status: string, words}}\n */\n calculateResult(data, relatedKeywords, hasDescription) {\n const {words} = relatedKeywords;\n let status = 'good';\n const totalWords = Object.values(words).filter(word => word.percentage === 0);\n if(!hasDescription || isEmpty(words) || totalWords.length > 0){\n status = 'bad';\n }\n const score = this.getScore(MAIN_CONTENT_POINTS, status);\n\n return {\n score,\n status,\n words\n };\n }\n\n /**\n *\n * @param paper\n * @param researcher\n * @returns {AssessmentResult}\n */\n getResult({paper, researcher}) {\n const relatedKeywords = researcher.getResearch('checkRelatedKeywords');\n const data = paper.getData();\n const hasDescription = paper.hasDescription();\n const result = this.calculateResult(data, relatedKeywords, hasDescription);\n const assessmentResult = new AssessmentResult({config: this._config});\n\n assessmentResult.setScore(result.score);\n assessmentResult.setStatus(result.status);\n assessmentResult.setData(result.words);\n\n return assessmentResult;\n }\n\n /**\n * Checks if the transition words assessment is applicable to the paper. Language-specific length requirements and methods of counting text length\n * may apply (e.g. for Japanese, the text should be counted in characters instead of words, which also makes the minimum required length higher).\n *\n * @param {Paper} paper The paper to check.\n * @param {Researcher} researcher The researcher object.\n *\n * @returns {boolean} Returns true if the language is available, the paper is not empty and the text is longer than the minimum required length.\n */\n isApplicable(paper, researcher) {\n return true;\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AACA,IAAAC,iBAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,WAAA,GAAAD,sBAAA,CAAAF,OAAA;AACA,IAAAI,SAAA,GAAAJ,OAAA;AAAwF,SAAAE,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAExF;AACA;AACA;AACe,MAAMG,gCAAgC,SAASC,mBAAU,CAAC;EACvE;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,WAAWA,CAACC,MAAM,GAAG,CAAC,CAAC,EAAE;IACvB,KAAK,CAAC,CAAC;IAEP,MAAMC,aAAa,GAAG;MACpBC,EAAE,EAAEC,qCAA2B;MAC/BC,WAAW,EAAE,aAAa;MAC1BC,OAAO,EAAE,KAAK;MACdC,MAAM,EACJ,8FAA8F;MAChGC,QAAQ,EAAE,MAAM;MAChBC,KAAK,EAAE,0BAA0B;MACjCC,OAAO,EAAE;QACPC,IAAI,EAAE,oCAAoC;QAC1CC,GAAG,EACD,6EAA6E;QAC/EC,OAAO,EAAE;MACX;IACF,CAAC;IAED,IAAI,CAACC,UAAU,GAAGV,qCAA2B;IAC7C,IAAI,CAACW,OAAO,GAAG,IAAAC,aAAK,EAACd,aAAa,EAAED,MAAM,CAAC;EAC7C;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACEgB,eAAeA,CAACC,IAAI,EAAEC,eAAe,EAAEC,cAAc,EAAE;IACrD,MAAM;MAACC;IAAK,CAAC,GAAGF,eAAe;IAC/B,IAAIG,MAAM,GAAG,MAAM;IACnB,MAAMC,UAAU,GAAGC,MAAM,CAACC,MAAM,CAACJ,KAAK,CAAC,CAACK,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACC,UAAU,KAAK,CAAC,CAAC;IAC7E,IAAG,CAACR,cAAc,IAAI,IAAAS,eAAO,EAACR,KAAK,CAAC,IAAIE,UAAU,CAACO,MAAM,GAAG,CAAC,EAAC;MAC5DR,MAAM,GAAG,KAAK;IAChB;IACA,MAAMS,KAAK,GAAG,IAAI,CAACC,QAAQ,CAACC,6BAAmB,EAAEX,MAAM,CAAC;IAExD,OAAO;MACLS,KAAK;MACLT,MAAM;MACND;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEa,SAASA,CAAC;IAACC,KAAK;IAAEC;EAAU,CAAC,EAAE;IAC7B,MAAMjB,eAAe,GAAGiB,UAAU,CAACC,WAAW,CAAC,sBAAsB,CAAC;IACtE,MAAMnB,IAAI,GAAGiB,KAAK,CAACG,OAAO,CAAC,CAAC;IAC5B,MAAMlB,cAAc,GAAGe,KAAK,CAACf,cAAc,CAAC,CAAC;IAC7C,MAAMmB,MAAM,GAAG,IAAI,CAACtB,eAAe,CAACC,IAAI,EAAEC,eAAe,EAAEC,cAAc,CAAC;IAC1E,MAAMoB,gBAAgB,GAAG,IAAIC,yBAAgB,CAAC;MAACxC,MAAM,EAAE,IAAI,CAACc;IAAO,CAAC,CAAC;IAErEyB,gBAAgB,CAACE,QAAQ,CAACH,MAAM,CAACR,KAAK,CAAC;IACvCS,gBAAgB,CAACG,SAAS,CAACJ,MAAM,CAACjB,MAAM,CAAC;IACzCkB,gBAAgB,CAACI,OAAO,CAACL,MAAM,CAAClB,KAAK,CAAC;IAEtC,OAAOmB,gBAAgB;EACzB;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEK,YAAYA,CAACV,KAAK,EAAEC,UAAU,EAAE;IAC9B,OAAO,IAAI;EACb;AACF;AAACU,OAAA,CAAAjD,OAAA,GAAAC,gCAAA","ignoreList":[]}
@@ -5,6 +5,12 @@ import { getParentNode } from "../helpers/sentence/getSentencesFromTree";
5
5
  import { createShortcodeTagsRegex } from "../helpers";
6
6
  import isChineseText from "../helpers/language/isChineseText";
7
7
 
8
+ // Matches common UI-marker class names (label, eyebrow, kicker, etc.) used for
9
+ // short text placed above a heading. Anchored to the start, with a boundary so
10
+ // `header-label` or `tagline` don't match.
11
+ const LABEL_LIKE_CLASS_REGEX = /^(label|eyebrow|kicker|overline|pretitle|subtitle|badge|tag|chip|meta|category|breadcrumb)(\b|[-_])/i;
12
+ const MIN_INTRO_WORDS = 5;
13
+
8
14
  /**
9
15
  * Checks if the introductory paragraph contains keyphrase or synonyms.
10
16
  * First splits the first paragraph by sentences. Finds the first paragraph which contains sentences e.g., not an image).
@@ -35,6 +41,21 @@ export default function (paper, researcher) {
35
41
  paragraphs = paragraphs.filter(paragraph => {
36
42
  return !(paragraph.childNodes && paragraph.childNodes[0] && createShortcodeTagsRegex(['caption']).test(paragraph.childNodes[0].value));
37
43
  });
44
+ // Filter UI label/eyebrow/kicker paragraphs that sit before the heading
45
+ // (e.g., <p class="label">CATEGORY</p>). These are visual markers, not real
46
+ // intro paragraphs, and would cause false negatives on keyword-in-intro checks.
47
+ paragraphs = paragraphs.filter(paragraph => {
48
+ const classSet = paragraph.attributes && paragraph.attributes.class;
49
+ if (classSet instanceof Set) {
50
+ for (const cls of classSet) {
51
+ if (LABEL_LIKE_CLASS_REGEX.test(cls)) {
52
+ return false;
53
+ }
54
+ }
55
+ }
56
+ const wordCount = (paragraph.innerText() || '').trim().split(/\s+/).filter(Boolean).length;
57
+ return wordCount >= MIN_INTRO_WORDS;
58
+ });
38
59
  const firstParagraph = paragraphs[0];
39
60
  const topicForms = researcher.getResearch('morphology');
40
61
  let matchWordCustomHelper = researcher.getHelper('matchWordCustomHelper');
@@ -1 +1 @@
1
- {"version":3,"file":"findKeywordInFirstParagraph.js","names":["inRange","isEmpty","findTopicFormsInString","getParentNode","createShortcodeTagsRegex","isChineseText","paper","researcher","paragraphs","getResearch","filter","paragraph","parentNode","isImplicit","name","childNodes","test","value","firstParagraph","topicForms","matchWordCustomHelper","getHelper","locale","getLocale","getKeyword","innerText","text","word","textToSearch","matches","lowerText","toLowerCase","lowerWord","startIndex","index","indexOf","push","length","startOffset","sourceCodeLocation","mappedBlocks","_attributes","wpBlocks","filteredIntroductionBlock","block","endOffset","result","foundInOneSentence","foundInParagraph","keyphraseOrSynonym","introduction","parentBlock","sentences","map","sentence","useSynonyms","firstResultSentence","find","resultSentence","percentWordMatches","resultParagraph"],"sources":["../../../../src/languageProcessing/researches/findKeywordInFirstParagraph.js"],"sourcesContent":["/** @module analyses/findKeywordInFirstParagraph */\nimport {inRange, isEmpty} from 'lodash';\n\nimport {findTopicFormsInString} from '../helpers/match/findKeywordFormsInString.js';\nimport {getParentNode} from '../helpers/sentence/getSentencesFromTree';\nimport {createShortcodeTagsRegex} from '../helpers';\nimport isChineseText from '../helpers/language/isChineseText';\n\n/**\n * Checks if the introductory paragraph contains keyphrase or synonyms.\n * First splits the first paragraph by sentences. Finds the first paragraph which contains sentences e.g., not an image).\n * (1) Tries to find all (content) words from the keyphrase or a synonym phrase within one sentence.\n * If found all words within one sentence, returns an object with foundInOneSentence = true and keyphraseOrSynonym = \"keyphrase\"\n * or \"synonym\".\n * If it did not find all words within one sentence, goes ahead with matching the keyphrase with the entire first paragraph.\n * (2) Tries to find all (content) words from the keyphrase or a synonym phrase within the paragraph.\n * If found all words within the paragraph, returns an object with foundInOneSentence = false, foundInParagraph = true,\n * and keyphraseOrSynonym = \"keyphrase\" or \"synonym\".\n * If found not all words within the paragraph of nothing at all, returns an object with foundInOneSentence = false,\n * foundInParagraph = false, and keyphraseOrSynonym = \"\".\n *\n * @param {Paper} paper The text to check for paragraphs.\n * @param {Researcher} researcher The researcher to use for analysis.\n *\n * @returns {Object} Whether the keyphrase words were found in one sentence, whether the keyphrase words were found in\n * the paragraph, whether a keyphrase or a synonym phrase was matched.\n */\nexport default function(paper, researcher) {\n let paragraphs = researcher.getResearch('getParagraphs');\n // Filter captions from non-Classic editors.\n paragraphs = paragraphs.filter(paragraph => {\n const parentNode = getParentNode(paper, paragraph);\n return !(paragraph.isImplicit && parentNode && parentNode.name === 'figcaption');\n });\n // Filter captions from Classic editor and from classic block inside Block editor.\n paragraphs = paragraphs.filter(paragraph => {\n return !(\n paragraph.childNodes &&\n paragraph.childNodes[0] &&\n createShortcodeTagsRegex(['caption']).test(paragraph.childNodes[0].value)\n );\n });\n const firstParagraph = paragraphs[0];\n\n const topicForms = researcher.getResearch('morphology');\n let matchWordCustomHelper = researcher.getHelper('matchWordCustomHelper');\n const locale = paper.getLocale();\n\n // Auto-detect Chinese and use Chinese helper if not already available\n if (\n !matchWordCustomHelper &&\n isChineseText(paper.getKeyword() + ' ' + (firstParagraph ? firstParagraph.innerText() : ''))\n ) {\n // Use Chinese word matching for Chinese text\n matchWordCustomHelper = function(text, word) {\n const textToSearch = typeof text === 'string' ? text : text.text || text;\n const matches = [];\n\n if (!textToSearch || !word) {\n return matches;\n }\n\n const lowerText = textToSearch.toLowerCase();\n const lowerWord = word.toLowerCase();\n\n let startIndex = 0;\n let index;\n\n while ((index = lowerText.indexOf(lowerWord, startIndex)) !== -1) {\n matches.push(word);\n startIndex = index + lowerWord.length;\n }\n\n return matches;\n };\n }\n const startOffset = firstParagraph && firstParagraph.sourceCodeLocation.startOffset;\n\n const mappedBlocks = paper._attributes.wpBlocks;\n const filteredIntroductionBlock =\n mappedBlocks &&\n mappedBlocks.filter(block => inRange(startOffset, block.startOffset, block.endOffset))[0];\n const result = {\n foundInOneSentence: false,\n foundInParagraph: false,\n keyphraseOrSynonym: '',\n introduction: firstParagraph,\n parentBlock: filteredIntroductionBlock || null\n };\n\n if (isEmpty(firstParagraph)) {\n return result;\n }\n\n const sentences = firstParagraph.sentences.map(sentence => sentence.text);\n // Use both keyphrase and synonyms to match topic words in the first paragraph.\n const useSynonyms = true;\n\n if (!isEmpty(sentences)) {\n const firstResultSentence = sentences\n .map(sentence =>\n findTopicFormsInString(topicForms, sentence, useSynonyms, locale, matchWordCustomHelper)\n )\n .find(resultSentence => resultSentence.percentWordMatches === 100);\n\n if (firstResultSentence) {\n result.foundInOneSentence = true;\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = firstResultSentence.keyphraseOrSynonym;\n return result;\n }\n\n const resultParagraph = findTopicFormsInString(\n topicForms,\n firstParagraph.innerText(),\n useSynonyms,\n locale,\n matchWordCustomHelper\n );\n if (resultParagraph.percentWordMatches === 100) {\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = resultParagraph.keyphraseOrSynonym;\n return result;\n }\n }\n\n return result;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"findKeywordInFirstParagraph.js","names":["inRange","isEmpty","findTopicFormsInString","getParentNode","createShortcodeTagsRegex","isChineseText","LABEL_LIKE_CLASS_REGEX","MIN_INTRO_WORDS","paper","researcher","paragraphs","getResearch","filter","paragraph","parentNode","isImplicit","name","childNodes","test","value","classSet","attributes","class","Set","cls","wordCount","innerText","trim","split","Boolean","length","firstParagraph","topicForms","matchWordCustomHelper","getHelper","locale","getLocale","getKeyword","text","word","textToSearch","matches","lowerText","toLowerCase","lowerWord","startIndex","index","indexOf","push","startOffset","sourceCodeLocation","mappedBlocks","_attributes","wpBlocks","filteredIntroductionBlock","block","endOffset","result","foundInOneSentence","foundInParagraph","keyphraseOrSynonym","introduction","parentBlock","sentences","map","sentence","useSynonyms","firstResultSentence","find","resultSentence","percentWordMatches","resultParagraph"],"sources":["../../../../src/languageProcessing/researches/findKeywordInFirstParagraph.js"],"sourcesContent":["/** @module analyses/findKeywordInFirstParagraph */\nimport {inRange, isEmpty} from 'lodash';\n\nimport {findTopicFormsInString} from '../helpers/match/findKeywordFormsInString.js';\nimport {getParentNode} from '../helpers/sentence/getSentencesFromTree';\nimport {createShortcodeTagsRegex} from '../helpers';\nimport isChineseText from '../helpers/language/isChineseText';\n\n// Matches common UI-marker class names (label, eyebrow, kicker, etc.) used for\n// short text placed above a heading. Anchored to the start, with a boundary so\n// `header-label` or `tagline` don't match.\nconst LABEL_LIKE_CLASS_REGEX = /^(label|eyebrow|kicker|overline|pretitle|subtitle|badge|tag|chip|meta|category|breadcrumb)(\\b|[-_])/i;\nconst MIN_INTRO_WORDS = 5;\n\n/**\n * Checks if the introductory paragraph contains keyphrase or synonyms.\n * First splits the first paragraph by sentences. Finds the first paragraph which contains sentences e.g., not an image).\n * (1) Tries to find all (content) words from the keyphrase or a synonym phrase within one sentence.\n * If found all words within one sentence, returns an object with foundInOneSentence = true and keyphraseOrSynonym = \"keyphrase\"\n * or \"synonym\".\n * If it did not find all words within one sentence, goes ahead with matching the keyphrase with the entire first paragraph.\n * (2) Tries to find all (content) words from the keyphrase or a synonym phrase within the paragraph.\n * If found all words within the paragraph, returns an object with foundInOneSentence = false, foundInParagraph = true,\n * and keyphraseOrSynonym = \"keyphrase\" or \"synonym\".\n * If found not all words within the paragraph of nothing at all, returns an object with foundInOneSentence = false,\n * foundInParagraph = false, and keyphraseOrSynonym = \"\".\n *\n * @param {Paper} paper The text to check for paragraphs.\n * @param {Researcher} researcher The researcher to use for analysis.\n *\n * @returns {Object} Whether the keyphrase words were found in one sentence, whether the keyphrase words were found in\n * the paragraph, whether a keyphrase or a synonym phrase was matched.\n */\nexport default function(paper, researcher) {\n let paragraphs = researcher.getResearch('getParagraphs');\n // Filter captions from non-Classic editors.\n paragraphs = paragraphs.filter(paragraph => {\n const parentNode = getParentNode(paper, paragraph);\n return !(paragraph.isImplicit && parentNode && parentNode.name === 'figcaption');\n });\n // Filter captions from Classic editor and from classic block inside Block editor.\n paragraphs = paragraphs.filter(paragraph => {\n return !(\n paragraph.childNodes &&\n paragraph.childNodes[0] &&\n createShortcodeTagsRegex(['caption']).test(paragraph.childNodes[0].value)\n );\n });\n // Filter UI label/eyebrow/kicker paragraphs that sit before the heading\n // (e.g., <p class=\"label\">CATEGORY</p>). These are visual markers, not real\n // intro paragraphs, and would cause false negatives on keyword-in-intro checks.\n paragraphs = paragraphs.filter(paragraph => {\n const classSet = paragraph.attributes && paragraph.attributes.class;\n if (classSet instanceof Set) {\n for (const cls of classSet) {\n if (LABEL_LIKE_CLASS_REGEX.test(cls)) {\n return false;\n }\n }\n }\n const wordCount = (paragraph.innerText() || '')\n .trim()\n .split(/\\s+/)\n .filter(Boolean).length;\n return wordCount >= MIN_INTRO_WORDS;\n });\n const firstParagraph = paragraphs[0];\n\n const topicForms = researcher.getResearch('morphology');\n let matchWordCustomHelper = researcher.getHelper('matchWordCustomHelper');\n const locale = paper.getLocale();\n\n // Auto-detect Chinese and use Chinese helper if not already available\n if (\n !matchWordCustomHelper &&\n isChineseText(paper.getKeyword() + ' ' + (firstParagraph ? firstParagraph.innerText() : ''))\n ) {\n // Use Chinese word matching for Chinese text\n matchWordCustomHelper = function(text, word) {\n const textToSearch = typeof text === 'string' ? text : text.text || text;\n const matches = [];\n\n if (!textToSearch || !word) {\n return matches;\n }\n\n const lowerText = textToSearch.toLowerCase();\n const lowerWord = word.toLowerCase();\n\n let startIndex = 0;\n let index;\n\n while ((index = lowerText.indexOf(lowerWord, startIndex)) !== -1) {\n matches.push(word);\n startIndex = index + lowerWord.length;\n }\n\n return matches;\n };\n }\n const startOffset = firstParagraph && firstParagraph.sourceCodeLocation.startOffset;\n\n const mappedBlocks = paper._attributes.wpBlocks;\n const filteredIntroductionBlock =\n mappedBlocks &&\n mappedBlocks.filter(block => inRange(startOffset, block.startOffset, block.endOffset))[0];\n const result = {\n foundInOneSentence: false,\n foundInParagraph: false,\n keyphraseOrSynonym: '',\n introduction: firstParagraph,\n parentBlock: filteredIntroductionBlock || null\n };\n\n if (isEmpty(firstParagraph)) {\n return result;\n }\n\n const sentences = firstParagraph.sentences.map(sentence => sentence.text);\n // Use both keyphrase and synonyms to match topic words in the first paragraph.\n const useSynonyms = true;\n\n if (!isEmpty(sentences)) {\n const firstResultSentence = sentences\n .map(sentence =>\n findTopicFormsInString(topicForms, sentence, useSynonyms, locale, matchWordCustomHelper)\n )\n .find(resultSentence => resultSentence.percentWordMatches === 100);\n\n if (firstResultSentence) {\n result.foundInOneSentence = true;\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = firstResultSentence.keyphraseOrSynonym;\n return result;\n }\n\n const resultParagraph = findTopicFormsInString(\n topicForms,\n firstParagraph.innerText(),\n useSynonyms,\n locale,\n matchWordCustomHelper\n );\n if (resultParagraph.percentWordMatches === 100) {\n result.foundInParagraph = true;\n result.keyphraseOrSynonym = resultParagraph.keyphraseOrSynonym;\n return result;\n }\n }\n\n return result;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -46,7 +46,6 @@ export default class RelatedKeywordsDensityAssessment extends Assessment {
46
46
  } = relatedKeywords;
47
47
  let status = 'good';
48
48
  const totalWords = Object.values(words).filter(word => word.percentage === 0);
49
- console.log("Related keyword density check: ", !hasDescription, isEmpty(words), totalWords.length > 0);
50
49
  if (!hasDescription || isEmpty(words) || totalWords.length > 0) {
51
50
  status = 'bad';
52
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RelatedKeywordsDensityAssessment.js","names":["isEmpty","merge","AssessmentResult","Assessment","MAIN_CONTENT_POINTS","RELATED_KEYWORDS_DENSITY_ID","RelatedKeywordsDensityAssessment","constructor","config","defaultConfig","id","fixPosition","ctaType","docUrl","priority","title","content","good","bad","improve","identifier","_config","calculateResult","data","relatedKeywords","hasDescription","words","status","totalWords","Object","values","filter","word","percentage","console","log","length","score","getScore","getResult","paper","researcher","getResearch","getData","result","assessmentResult","setScore","setStatus","setData","isApplicable"],"sources":["../../../../../src/scoring/assessments/seo/RelatedKeywordsDensityAssessment.js"],"sourcesContent":["import {isEmpty, merge} from 'lodash';\nimport AssessmentResult from '../../../values/AssessmentResult';\nimport Assessment from '../assessment';\nimport {MAIN_CONTENT_POINTS, RELATED_KEYWORDS_DENSITY_ID} from '@axyseo/const/analysis';\n\n/**\n * Represents the assessment that checks whether there are enough transition words in the text.\n */\nexport default class RelatedKeywordsDensityAssessment extends Assessment {\n /**\n * Sets the identifier and the config.\n *\n * @param {object} config The configuration to use.\n *\n * @returns {void}\n */\n constructor(config = {}) {\n super();\n\n const defaultConfig = {\n id: RELATED_KEYWORDS_DENSITY_ID,\n fixPosition: 'description',\n ctaType: 'fix',\n docUrl:\n 'https://docs.avada.io/seo-suite-help-center/seo-audit/on-page-seo/checklist#related-keywords',\n priority: 'high',\n title: 'Related keywords density',\n content: {\n good: 'Related keywords density optimized',\n bad:\n 'Use each secondary keyword from 0.5% to 1%. Place where it reads naturally.',\n improve: ''\n }\n };\n\n this.identifier = RELATED_KEYWORDS_DENSITY_ID;\n this._config = merge(defaultConfig, config);\n }\n\n /**\n *\n * @param data\n * @param relatedKeywords\n * @param hasDescription\n * @returns {{score: number, status: string, words}}\n */\n calculateResult(data, relatedKeywords, hasDescription) {\n const {words} = relatedKeywords;\n let status = 'good';\n const totalWords = Object.values(words).filter(word => word.percentage === 0);\n console.log(\"Related keyword density check: \", !hasDescription, isEmpty(words), totalWords.length > 0);\n if(!hasDescription || isEmpty(words) || totalWords.length > 0){\n status = 'bad';\n }\n const score = this.getScore(MAIN_CONTENT_POINTS, status);\n\n return {\n score,\n status,\n words\n };\n }\n\n /**\n *\n * @param paper\n * @param researcher\n * @returns {AssessmentResult}\n */\n getResult({paper, researcher}) {\n const relatedKeywords = researcher.getResearch('checkRelatedKeywords');\n const data = paper.getData();\n const hasDescription = paper.hasDescription();\n const result = this.calculateResult(data, relatedKeywords, hasDescription);\n const assessmentResult = new AssessmentResult({config: this._config});\n\n assessmentResult.setScore(result.score);\n assessmentResult.setStatus(result.status);\n assessmentResult.setData(result.words);\n\n return assessmentResult;\n }\n\n /**\n * Checks if the transition words assessment is applicable to the paper. Language-specific length requirements and methods of counting text length\n * may apply (e.g. for Japanese, the text should be counted in characters instead of words, which also makes the minimum required length higher).\n *\n * @param {Paper} paper The paper to check.\n * @param {Researcher} researcher The researcher object.\n *\n * @returns {boolean} Returns true if the language is available, the paper is not empty and the text is longer than the minimum required length.\n */\n isApplicable(paper, researcher) {\n return true;\n }\n}\n"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,KAAK,QAAO,QAAQ;AACrC,OAAOC,gBAAgB;AACvB,OAAOC,UAAU;AACjB,SAAQC,mBAAmB,EAAEC,2BAA2B;;AAExD;AACA;AACA;AACA,eAAe,MAAMC,gCAAgC,SAASH,UAAU,CAAC;EACvE;AACF;AACA;AACA;AACA;AACA;AACA;EACEI,WAAWA,CAACC,MAAM,GAAG,CAAC,CAAC,EAAE;IACvB,KAAK,CAAC,CAAC;IAEP,MAAMC,aAAa,GAAG;MACpBC,EAAE,EAAEL,2BAA2B;MAC/BM,WAAW,EAAE,aAAa;MAC1BC,OAAO,EAAE,KAAK;MACdC,MAAM,EACJ,8FAA8F;MAChGC,QAAQ,EAAE,MAAM;MAChBC,KAAK,EAAE,0BAA0B;MACjCC,OAAO,EAAE;QACPC,IAAI,EAAE,oCAAoC;QAC1CC,GAAG,EACD,6EAA6E;QAC/EC,OAAO,EAAE;MACX;IACF,CAAC;IAED,IAAI,CAACC,UAAU,GAAGf,2BAA2B;IAC7C,IAAI,CAACgB,OAAO,GAAGpB,KAAK,CAACQ,aAAa,EAAED,MAAM,CAAC;EAC7C;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACEc,eAAeA,CAACC,IAAI,EAAEC,eAAe,EAAEC,cAAc,EAAE;IACrD,MAAM;MAACC;IAAK,CAAC,GAAGF,eAAe;IAC/B,IAAIG,MAAM,GAAG,MAAM;IACnB,MAAMC,UAAU,GAAGC,MAAM,CAACC,MAAM,CAACJ,KAAK,CAAC,CAACK,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACC,UAAU,KAAK,CAAC,CAAC;IAC7EC,OAAO,CAACC,GAAG,CAAC,iCAAiC,EAAE,CAACV,cAAc,EAAEzB,OAAO,CAAC0B,KAAK,CAAC,EAAEE,UAAU,CAACQ,MAAM,GAAG,CAAC,CAAC;IACtG,IAAG,CAACX,cAAc,IAAIzB,OAAO,CAAC0B,KAAK,CAAC,IAAIE,UAAU,CAACQ,MAAM,GAAG,CAAC,EAAC;MAC5DT,MAAM,GAAG,KAAK;IAChB;IACA,MAAMU,KAAK,GAAG,IAAI,CAACC,QAAQ,CAAClC,mBAAmB,EAAEuB,MAAM,CAAC;IAExD,OAAO;MACLU,KAAK;MACLV,MAAM;MACND;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEa,SAASA,CAAC;IAACC,KAAK;IAAEC;EAAU,CAAC,EAAE;IAC7B,MAAMjB,eAAe,GAAGiB,UAAU,CAACC,WAAW,CAAC,sBAAsB,CAAC;IACtE,MAAMnB,IAAI,GAAGiB,KAAK,CAACG,OAAO,CAAC,CAAC;IAC5B,MAAMlB,cAAc,GAAGe,KAAK,CAACf,cAAc,CAAC,CAAC;IAC7C,MAAMmB,MAAM,GAAG,IAAI,CAACtB,eAAe,CAACC,IAAI,EAAEC,eAAe,EAAEC,cAAc,CAAC;IAC1E,MAAMoB,gBAAgB,GAAG,IAAI3C,gBAAgB,CAAC;MAACM,MAAM,EAAE,IAAI,CAACa;IAAO,CAAC,CAAC;IAErEwB,gBAAgB,CAACC,QAAQ,CAACF,MAAM,CAACP,KAAK,CAAC;IACvCQ,gBAAgB,CAACE,SAAS,CAACH,MAAM,CAACjB,MAAM,CAAC;IACzCkB,gBAAgB,CAACG,OAAO,CAACJ,MAAM,CAAClB,KAAK,CAAC;IAEtC,OAAOmB,gBAAgB;EACzB;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEI,YAAYA,CAACT,KAAK,EAAEC,UAAU,EAAE;IAC9B,OAAO,IAAI;EACb;AACF","ignoreList":[]}
1
+ {"version":3,"file":"RelatedKeywordsDensityAssessment.js","names":["isEmpty","merge","AssessmentResult","Assessment","MAIN_CONTENT_POINTS","RELATED_KEYWORDS_DENSITY_ID","RelatedKeywordsDensityAssessment","constructor","config","defaultConfig","id","fixPosition","ctaType","docUrl","priority","title","content","good","bad","improve","identifier","_config","calculateResult","data","relatedKeywords","hasDescription","words","status","totalWords","Object","values","filter","word","percentage","length","score","getScore","getResult","paper","researcher","getResearch","getData","result","assessmentResult","setScore","setStatus","setData","isApplicable"],"sources":["../../../../../src/scoring/assessments/seo/RelatedKeywordsDensityAssessment.js"],"sourcesContent":["import {isEmpty, merge} from 'lodash';\nimport AssessmentResult from '../../../values/AssessmentResult';\nimport Assessment from '../assessment';\nimport {MAIN_CONTENT_POINTS, RELATED_KEYWORDS_DENSITY_ID} from '@axyseo/const/analysis';\n\n/**\n * Represents the assessment that checks whether there are enough transition words in the text.\n */\nexport default class RelatedKeywordsDensityAssessment extends Assessment {\n /**\n * Sets the identifier and the config.\n *\n * @param {object} config The configuration to use.\n *\n * @returns {void}\n */\n constructor(config = {}) {\n super();\n\n const defaultConfig = {\n id: RELATED_KEYWORDS_DENSITY_ID,\n fixPosition: 'description',\n ctaType: 'fix',\n docUrl:\n 'https://docs.avada.io/seo-suite-help-center/seo-audit/on-page-seo/checklist#related-keywords',\n priority: 'high',\n title: 'Related keywords density',\n content: {\n good: 'Related keywords density optimized',\n bad:\n 'Use each secondary keyword from 0.5% to 1%. Place where it reads naturally.',\n improve: ''\n }\n };\n\n this.identifier = RELATED_KEYWORDS_DENSITY_ID;\n this._config = merge(defaultConfig, config);\n }\n\n /**\n *\n * @param data\n * @param relatedKeywords\n * @param hasDescription\n * @returns {{score: number, status: string, words}}\n */\n calculateResult(data, relatedKeywords, hasDescription) {\n const {words} = relatedKeywords;\n let status = 'good';\n const totalWords = Object.values(words).filter(word => word.percentage === 0);\n if(!hasDescription || isEmpty(words) || totalWords.length > 0){\n status = 'bad';\n }\n const score = this.getScore(MAIN_CONTENT_POINTS, status);\n\n return {\n score,\n status,\n words\n };\n }\n\n /**\n *\n * @param paper\n * @param researcher\n * @returns {AssessmentResult}\n */\n getResult({paper, researcher}) {\n const relatedKeywords = researcher.getResearch('checkRelatedKeywords');\n const data = paper.getData();\n const hasDescription = paper.hasDescription();\n const result = this.calculateResult(data, relatedKeywords, hasDescription);\n const assessmentResult = new AssessmentResult({config: this._config});\n\n assessmentResult.setScore(result.score);\n assessmentResult.setStatus(result.status);\n assessmentResult.setData(result.words);\n\n return assessmentResult;\n }\n\n /**\n * Checks if the transition words assessment is applicable to the paper. Language-specific length requirements and methods of counting text length\n * may apply (e.g. for Japanese, the text should be counted in characters instead of words, which also makes the minimum required length higher).\n *\n * @param {Paper} paper The paper to check.\n * @param {Researcher} researcher The researcher object.\n *\n * @returns {boolean} Returns true if the language is available, the paper is not empty and the text is longer than the minimum required length.\n */\n isApplicable(paper, researcher) {\n return true;\n }\n}\n"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,KAAK,QAAO,QAAQ;AACrC,OAAOC,gBAAgB;AACvB,OAAOC,UAAU;AACjB,SAAQC,mBAAmB,EAAEC,2BAA2B;;AAExD;AACA;AACA;AACA,eAAe,MAAMC,gCAAgC,SAASH,UAAU,CAAC;EACvE;AACF;AACA;AACA;AACA;AACA;AACA;EACEI,WAAWA,CAACC,MAAM,GAAG,CAAC,CAAC,EAAE;IACvB,KAAK,CAAC,CAAC;IAEP,MAAMC,aAAa,GAAG;MACpBC,EAAE,EAAEL,2BAA2B;MAC/BM,WAAW,EAAE,aAAa;MAC1BC,OAAO,EAAE,KAAK;MACdC,MAAM,EACJ,8FAA8F;MAChGC,QAAQ,EAAE,MAAM;MAChBC,KAAK,EAAE,0BAA0B;MACjCC,OAAO,EAAE;QACPC,IAAI,EAAE,oCAAoC;QAC1CC,GAAG,EACD,6EAA6E;QAC/EC,OAAO,EAAE;MACX;IACF,CAAC;IAED,IAAI,CAACC,UAAU,GAAGf,2BAA2B;IAC7C,IAAI,CAACgB,OAAO,GAAGpB,KAAK,CAACQ,aAAa,EAAED,MAAM,CAAC;EAC7C;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACEc,eAAeA,CAACC,IAAI,EAAEC,eAAe,EAAEC,cAAc,EAAE;IACrD,MAAM;MAACC;IAAK,CAAC,GAAGF,eAAe;IAC/B,IAAIG,MAAM,GAAG,MAAM;IACnB,MAAMC,UAAU,GAAGC,MAAM,CAACC,MAAM,CAACJ,KAAK,CAAC,CAACK,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACC,UAAU,KAAK,CAAC,CAAC;IAC7E,IAAG,CAACR,cAAc,IAAIzB,OAAO,CAAC0B,KAAK,CAAC,IAAIE,UAAU,CAACM,MAAM,GAAG,CAAC,EAAC;MAC5DP,MAAM,GAAG,KAAK;IAChB;IACA,MAAMQ,KAAK,GAAG,IAAI,CAACC,QAAQ,CAAChC,mBAAmB,EAAEuB,MAAM,CAAC;IAExD,OAAO;MACLQ,KAAK;MACLR,MAAM;MACND;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEW,SAASA,CAAC;IAACC,KAAK;IAAEC;EAAU,CAAC,EAAE;IAC7B,MAAMf,eAAe,GAAGe,UAAU,CAACC,WAAW,CAAC,sBAAsB,CAAC;IACtE,MAAMjB,IAAI,GAAGe,KAAK,CAACG,OAAO,CAAC,CAAC;IAC5B,MAAMhB,cAAc,GAAGa,KAAK,CAACb,cAAc,CAAC,CAAC;IAC7C,MAAMiB,MAAM,GAAG,IAAI,CAACpB,eAAe,CAACC,IAAI,EAAEC,eAAe,EAAEC,cAAc,CAAC;IAC1E,MAAMkB,gBAAgB,GAAG,IAAIzC,gBAAgB,CAAC;MAACM,MAAM,EAAE,IAAI,CAACa;IAAO,CAAC,CAAC;IAErEsB,gBAAgB,CAACC,QAAQ,CAACF,MAAM,CAACP,KAAK,CAAC;IACvCQ,gBAAgB,CAACE,SAAS,CAACH,MAAM,CAACf,MAAM,CAAC;IACzCgB,gBAAgB,CAACG,OAAO,CAACJ,MAAM,CAAChB,KAAK,CAAC;IAEtC,OAAOiB,gBAAgB;EACzB;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEI,YAAYA,CAACT,KAAK,EAAEC,UAAU,EAAE;IAC9B,OAAO,IAAI;EACb;AACF","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axyseo",
3
- "version": "2.1.55",
3
+ "version": "2.1.56",
4
4
  "main": "build/cjs/index.js",
5
5
  "module": "build/esm/index.js",
6
6
  "exports": {