UNPKG

@sector-labs/seo-slip

Version:

Catches SEO regressions by sampling and checking a website against a set of rules

63 lines (53 loc) 2.09 kB
const xpath = require('xpath-html'); const { isHtmlDocument, tryGetContentByXPath } = require('../html'); const { newMessage, newEmptyItemResult } = require('../reporting'); module.exports = (canonicalRules) => { const name = 'canonicalChecker'; const getCanonicalUrl = (responseBody) => { const body = xpath.fromPageSource(responseBody); const hrefAttributeValue = tryGetContentByXPath( body, `//link[@rel="canonical"]/@href` ).join(' '); return hrefAttributeValue; }; return { analysis: (queueItem, responseBody, response) => { const isHtmlDoc = isHtmlDocument(responseBody, response); return { url: queueItem.url, isHtmlDocument: isHtmlDoc, canonicalUrl: isHtmlDoc ? getCanonicalUrl(responseBody) : '', }; }, report: (analysis) => { return { canonicalUrl: analysis.canonicalUrl, }; }, check: (analysis) => { const result = newEmptyItemResult(); const canonicalRule = (canonicalRules || []).find((canonicalRule) => analysis.url.match(canonicalRule.url) ); if (analysis.isHtmlDocument && canonicalRule) { const match = analysis.url.match(canonicalRule.url); let expectedUrl = canonicalRule.expected; for (let i = 1; i < match.length; i++) { expectedUrl = expectedUrl.replace(`(\$${i})`, match[i] || ''); } if (analysis.canonicalUrl !== expectedUrl) { result.passed = false; result.messages.push( newMessage( analysis.url, name, `Expected canonicalUrl=${expectedUrl}, actual=${analysis.canonicalUrl}` ) ); } } return result; }, }; };