UNPKG

hint

Version:

The linting tool for the web

155 lines (122 loc) 5.33 kB
# 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][new issue]. ## Using the `CLI` to create a hint The easiest way to create a new hint is via the `create-hint` package: ```bash 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 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): ```ts 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][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: ```json { "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: ```ts 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 optional `HTMLElement` where the issue was found (used to get a `ProblemLocation` if one was not provided). For example, if an image is missing an `alt` attribute, this can be the `img` element. * `codeSnippet` is a string of source code to display (defaults to the `outerHTML` of `element`). * `content` is a string of text within `element` where the issue was found (used to refine a `ProblemLocation`).; * `location` is an explicit `ProblemLocation` (`{col: number, line: number}`) where the issue was found. If used with `element`, it represents an offset from the start of that element's content (e.g. for inline CSS in HTML). * `severity` overrides the default `Severity` 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: ```json { "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][json schema]. 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`. <!-- Link labels: --> [custom hint]: ../guides/create-custom-hint.md [events]: ../getting-started/events.md [json schema]: http://json-schema.org/ [new issue]: https://github.com/webhintio/hint/issues/new [npx issue]: https://github.com/npm/npm/issues/17869