UNPKG

@passmarked/seo

Version:

Rules related to checking for any SEO issues on the page given

185 lines (122 loc) 4.02 kB
// load in the required modules const cheerio = require('cheerio') const url = require('url') const S = require('string') const _ = require('underscore') // expose the items module.exports = exports = function(payload, fn) { // get the url var data = payload.getData(); // get the page content payload.getPageContent(function(err, content) { // did we get a error ? if(err) { // debug payload.error('Got a error trying to get the page content', err) // done return fn(null) } // should not be empty if(S(content).isEmpty() === true) { // debug payload.warning('Content was blank skipping'); // done return fn(null); } // load up cheerio var $ = cheerio.load(content); // get the count of tags var headCount = $('meta[name=description]').length || 0; // check for title tags if(headCount === 0) { // no titles defined ... payload.addRule({ type: 'error', key: 'description.missing', message: 'No document description tag was found in the head of the page' }, { display: 'url', message: 'Missing description meta tag on $', idenfitiers: [ data.url ] }) // finish return fn(null); } // keep track of the last line var lastLine = -1; // the list of known titles var knownTitleElements = []; // parse the lines var lines = content.split('\n'); // loop all the title tags in the head $('meta[name=description]').each(function(index, elem) { // local reference var parentTag = ((($(elem).parent() || {})['0'] || {}).name || '').toLowerCase(); var value = $(elem).attr('content') || ''; // build the code var build = payload.getSnippetManager().build(lines, lastLine, function(line) { return line.toLowerCase().indexOf('<meta') != -1 && line.toLowerCase().indexOf('description') != -1; }); // must find the build if(!build) return; // set to subject lastLine = build.subject; // check if there are more than 1 if(headCount > 1) { // add the line payload.addRule({ type: 'error', key: 'description.multiple', message: 'Multiple document descriptions were found on the page' }, { display: 'code', code: build, message: S(value).trim().s }); } // check if under head if(parentTag != 'head') { // add the line payload.addRule({ type: 'error', key: 'description.location', message: 'Document description must be in the <head> section' }, { display: 'code', code: build, message: S(value).trim().s }); } // check if empty if(S(value || '').trim().isEmpty() === true) { // the build must be defined if(!build) return; // add a error ... payload.addRule({ type: 'error', key: 'description.empty', message: 'Document description was empty' }, { display: 'code', code: build, message: 'Empty description on line #' + build.subject }); } else if(S(value || '').trim().s.length > 160) { // add a error ... payload.addRule({ type: 'warning', key: 'description.length', message: 'Document description will be truncated' }, { display: 'code', code: build, message: 'Description $, was $ characters long but will be truncated at $ for most search engines', identifiers: [ S(value).trim().s, S(value).trim().s.length, 160 ] }); } }); // done ... ? fn(null) }); };