Develop a hint
Contributor guide
- Getting started
- Guides
- How to
Develop a hint
A hint
is a group of related checks webhint
will validate. The API should
be flexible enough to allow you to implement anything you want easily, e.g.:
- Validate that all links are
HTTPS
. - Integrate with a third party service.
- Inject JavaScript to execute in the context of the page.
- etc.
If there is something you want to do and you can’t, or it is not clear how to do it, please open an issue.
Using the CLI
to create a hint
The easiest way to create a new hint is via the create-hint
package:
npm init hint |
This command will start a wizard that will ask you a series of questions related to this new hint. A complete list of the questions is shown below:
- What’s the name of this new hint?
- Please select the category of this new hint:
- accessibility
- development
- compatibility
- performance
- pwa
- pitfalls
- security
- What’s the description of this new hint?
- Please select the category of use case:
- DOM
- What DOM element does the hint need access to?
- Resource Request
- Third Party Service
- JS injection
- DOM
Answer these questions and you will end up with a template hint file. Events determined to be relevant to this use case will be subscribed to automatically in the script.
How hints work
The following is a basic template for a hint (import
s might change
depending on the hint type):
import { Category } from '@hint/utils-types';
import { FetchEnd, IHint, HintMetadata } from 'hint/dist/src/lib/types';
import { HintContext } from 'hint/dist/src/lib/hint-context';
export default class MyNewHint implements IHint {
public static readonly meta: HintMetadata = {}
public constructor(context: HintContext) {
// Your code here.
const validateFetchEnd = (fetchEnd: FetchEnd) => {
// Code to validate the hint on the event fetch::end.
};
const validateElement = (element: ElementFound) => {
// Code to validate the hint on the event element::element-type.
};
context.on('element', validateElement);
context.on('fetch::end::*', validateFetchEnd);
// As many events as you need
}
} |
Hints are executed via events. There are several
events exposed by the connectors. The way to indicate which ones the hint cares
about is via the method create
. This method returns an objects whose keys
are the names of the events and the values the event handlers:
{
"eventName1": "eventHandler1",
"eventName2": "eventHandler2"
} |
There is no limit to the number of events a hint can listen to, but you want to keep it as simple as possible.
Hint constructors receive a context
object that makes it easier to interact
with the website and report errors.
To report an error, the hint has to do the following:
context.report(resource, message, { element: elementToReport }); |
resource
is the URL of what is being analyzed (HTML, JS, CSS, manifest, etc.)message
is the text to show to the user about the problem.options
is an (optional) object that can contain the following:element
is an optionalHTMLElement
where the issue was found (used to get aProblemLocation
if one was not provided). For example, if an image is missing analt
attribute, this can be theimg
element.codeSnippet
is a string of source code to display (defaults to theouterHTML
ofelement
).content
is a string of text withinelement
where the issue was found (used to refine aProblemLocation
).;location
is an explicitProblemLocation
({col: number, line: number}
) where the issue was found. If used withelement
, it represents an offset from the start of that element’s content (e.g. for inline CSS in HTML).severity
overrides the defaultSeverity
for the hint to determine how the issue will be reported (e.g.Severity.error
).
On top or reporting errors, the context
object exposes more information
to enable more complex scenarios. Some of the following sections describe them.
The meta
property
Hints have an object meta
that defines several properties:
{
"docs": {
"category": "Category",
"description": "string"
},
"id": "hint-id",
"recommended": "boolean", // If the hint is part of the recommended options
"schema": ["json schema"], // An array of valid JSON schemas
"worksWithLocalFiles": "boolean" // If the hint works with `file://`
} |
One of the most useful properties is schema
. This property specifies
if the hint allows the user to configure it (other than the severity).
By default it should be an empty array if it doesn’t, or an array of
valid JSON schemas. These schemas will be used when
validating a .hintrc
file. As long as there is one of the schemas
that passes, the configuration will be valid. This allows writting
simpler templates.
The hint can access the custom configuration via context.hintOptions
.