madsonic / char-seo

Search engine can smell your website from miles away like a good piece of char siew

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SEO rules checking in natural language style.

Getting Started

npm install
npm run build
<!DOCTYPE html>
<head>
  <meta charset='UTF-8'>
</head>
const CharSeo = require('lib/index');

const doc = CharSeo(html1)
doc.hasTag('head')
    .hasChild('meta')
    .hasAttribute({name: 'keywords'})
    .does.not.exist(); // true
// prints: <head>, <meta name=keywords> do not exists

Design approach

CharSeo API has been inspired by Chai and tries to mimic the natural language as much as possible. The grammar words can be broadly grouped in to 3 categories; subject, connective and action.

Subjects are built as a tree path, specifying the relative relationship between DOM nodes.

Constructor

CharSeo(filePath: string, isStrict: ?boolean, print: ?boolean)

isStrict: specify if attribute values are check. default to true

print: will print check result

Subject

hasTag(tag: HtmlTag)

Sets the root DOM node to check for.

.hasTag('div')

hasChild(tag: HtmlTag)

Similar to hasTag but appends the child to the existing path

.hasTag('div').hasChild('div') // will look for nested div tag

hasChildren(tags: HtmlTag[])

Similar to hasChild.

// These 2 statements are equivalent
.hasChildren(['div', 'div'])
.hasChild('div').hasChild('div')

hasAttribute

Specify attribute for last added tag. A subset check rather than a equivalent set check is performed

// <div style='color:black'>
.hasTag('div').hasAttribute({style: 'color:black'})

hasNoAttribute

Specify attribute that should not be present for last added tag. A null intersection check rather than a equivalent set check is performed

// any <div> without style='color:black'
.hasTag('div').hasNoAttribute({style: 'color:black'})

not

Flips the result of checking

Connective

  • appear
  • does

The only purpose of connectives is to allow the constructor statement to be read like a natural language. It has not impact on the outcome of the check.

// will yield same result
.hasTag('div').exist()
.hasTag('div').to.exist()
.hasTag('div').to.appear.to.exist()

Note: Ungrammatical sentence are not forbidden

Action

Action does all the heavy lifting and check for the subjects that have been specified.

Note action words are terminal words; no other words should come after them.

exist()

Checks if the subjects specified in the order exists

moreThan(times: number)

Check if the subjects specified in the order appear more than given number of times

Know Limitations

Currently only relative ordering is supported, i.e. immediate children relationship cannot be specified.

<div>
    <p></p>
    <div></div>
</div>
.hasTag('div').hasChild('div').exist() // will yield true for the given HTML

However, it can be easily extended to support such a relationship by adding more words such as .hasImmediateChild and specify the check routine.

Testing

Use Chai to assert for the outcomes. New tests should be named with *.test.js e.g. foo.test.js

// run the tests with
npm test

About

Search engine can smell your website from miles away like a good piece of char siew

License:MIT License


Languages

Language:JavaScript 96.4%Language:HTML 3.6%