0.2.1 • Published 5 years ago

html-seo-lint v0.2.1

Weekly downloads
1
License
MIT
Repository
github
Last release
5 years ago

html-seo-lint

npm code style: prettier JavaScript Style Guide Known Vulnerabilities Build Status Coverage Status

A fully pluggable tool for identifying and reporting on SEO defects in HTML files

Installation

npm install html-seo-lint

Example

1. CLI

html-seo-lint sample.html

Contents of .htmlseolintrc.json

[
  {
    "tag": "title",
    "type": "match"
  },
  {
    "tag": "h1",
    "type": "notMoreThan",
    "count": 1
  },
  {
    "tag": "img",
    "type": "missing",
    "where": [{ "key": "alt" }]
  }
]

To view the possible options, run

html-seo-lint --help

2. Require

Here is an example of reading from a file and printing the results of 3 rules to console via code

const htmlSeoLint = require('html-seo-lint');

const rules = [
  {
    tag: 'title',
    type: 'match',
    ancestor: 'head'
  },
  {
    tag: 'img',
    type: 'missing',
    where: [
      {
        key: 'alt'
      }
    ]
  },
  {
    tag: 'h1',
    type: 'notMoreThan',
    count: 1
  }
];

htmlSeoLint.lint('sample.html', rules).then(() => {
  console.log('Done');
}).catch(err => {
  console.log('Something went wrong');
})

Console

This HTML does not have <title> tags within <head> ancestor tag
This HTML has 1 <img> tags that do not have alt=... attribute(s)
This HTML has 2 <h1> tags, more than the specified limit of 1

Writing Rules

There are 3 types of rules available for usage

1. Match

A match rule checks if the given HTML contains an element that is of the correct tag (and optionally ancestor tag and attributes).

An error is displayed if the given HTML does not contain at least 1 element that fits the rule.

Below is the format of a single match rule

{
  tag: '<tag to look for>', // required
  ancestor: '<ancestor tag to look for ^ tag in its children>', // optional
  type: 'match', // required
  where: [{ // optional
    key: '<attribute key>', // required
    value: '<attribute value' // optional
  },{
    key: '<attribute key>'
  }]
}

Below is a sample match rule

{
  tag: 'title',
  type: 'match',
  ancestor: 'head'
}

In the example above, this match rule is looking for a title tag inside a head tag and displays an error if it cannot finds

2. Missing

A missing rule checks if the given html does not have any element that fits the given tag (and optionally if provided ancestor tag and attributes)

An error is displayed if there an element found in the HTML that fits the requirements

Below is the format of a missing rule

{
  tag: '<tag to look for>', // required
  ancestor: '<ancestor tag to look for ^ tag in its children>', // optional
  type: 'missing', // required
  where: [{ // optional
    key: '<attribute key>', // required
    value: '<attribute value' // optional
  },{
    key: '<attribute key>'
  }]
}

Below is an example of a missing rule

{
  tag: 'img',
  type: 'missing',
  where: [
    {
      key: 'alt'
    }
  ]
}

In the example above, this rule looks for any img tag in the HTML that does not have an alt attribute key and displays an error if it does find at least one

3. notMoreThan

A notMoreThan rule checks if the given HTML does not contain more than the specified number of elements that fit the given tag (and optionally ancestor tag and attributes)

An error is displayed if the number of elements that match exceeds the given limit

Below is the format for a notMoreThan rule

{
  tag: '<tag to look for>', // required
  ancestor: '<ancestor tag to look for ^ tag in its children>', // optional
  type: 'notMoreThan', // required
  count: '<integer>' // required, >= 1
  where: [{ // optional
    key: '<attribute key>', // required
    value: '<attribute value' // optional
  },{
    key: '<attribute key>'
  }]
}

Below is an example of a notMoreThan rule

{
  tag: 'h1',
  type: 'notMoreThan',
  count: 1
}

In the example above, this rule is looking for more than 1 h1 tag in given HTML and displays an error if there are more than 1 h1 tag found

API

This module exposes a single method lint(...)

lint(source, rules[, output, options])

  • source : String fileName or Readable stream
  • rules : Array of rules, refer to writing rules section above for more details on how to write rules
  • output : optional String fileName or Writable stream. If absent, prints to console (error)
  • options : optional object with debug property { debug: true } to print debug statements to console

Returns a promise

Test

Running test

npm test

Running test with coverage

npm run test:coverage

Running test with debugging

npm run test:debug

Running test while watching for file changes

npm run test:watch

Refer to package.json for other test-related scripts like inspecting during test running

Good-to-have

  1. Ancestor tag taking in a multiple ancestor tags (children/ancestor) and filtering by class/attributes
  2. Improve error clarity, especially for rules-based validation
  3. More tests for failure scenarios (e.g. passing a writable stream that has already closed)