Skip to content

w3c/specberus

Repository files navigation

Build Status Coverage Status Dependency Status devDependency Status

Specberus

Specberus is a checker used at W3C to validate the compliance of Technical Reports with publication rules.

  1. Installation
  2. Running
  3. Testing
  4. JS API
  5. REST API
  6. Profiles
  7. Validation events
  8. Writing rules

1. Installation

Specberus is a Node.js application, distributed through npm. Alternatively, you can clone the repository and run:

$ npm install

In order to get all the dependencies installed. Naturally, this requires that you have a reasonably recent version of Node.js installed.

2. Running

Specberus runs as a web server, providing both HTML form UI and API endpoints.

Syntax and command-line parameters

$ npm start [PORT]

Meaning of positional parameters:

  1. PORT: where Specberus will be listening for HTTP connections. (Default 80.)

Examples:

$ npm start
$ npm start 3001

Note: npm start relies on JavaScript files, which must first be built via npm run build. This step is not necessary when running the live development server or tests (see below).

Auto reload when developing

Run npm run live [PORT] when developing. The app will automatically reload when changes happen.

Examples:

$ npm run live
$ npm run live 3001

Environment variables

DEBUG

Set the environment variable DEBUG to run in debug mode instead:

$ DEBUG=true npm run start

This modifies the behaviour of certain parts of the application to facilitate debugging. eg, CSS and JS resources will not be loaded in their minified/uglified forms (the web UI will load bootstrap.css, bootstrap.js and jquery.js instead of bootstrap.min.css, bootstrap.min.js and jquery.min.js).

BASE_URI

If Specberus is not going to be served from the root directory of a domain, or if it will be served through a proxy, set also BASE_URI pointing to the public root URI of Specberus; eg

$ BASE_URI=https://spec-store.com/check/ npm start
$ BASE_URI=/hostname/can/be/omitted/ npm start 88

GH_TOKEN

The GH_TOKEN environment variable allows specifying an access token to be used for GitHub API requests. Otherwise, GitHub rate-limits unauthenticated requests to 60 per hour.

GH_TOKEN=github_pat_... npm start

3. Testing

1. Simple test

Run:

$ npm test

from the root to run the test suite.

2. Run testserver

The testcase document server can run independently:

$ npm run testserver

3. Run certain test

Add process env before npm run test and describe.only() to run single test.

// test/rules.js
describe.only('Making sure Specberus is not broken...', () => {

The following example only run test for the http://localhost:8001/doc-views/TR/Recommendation/WD?rule=copyright&type=noCopyright document.

$ RULE=copyright TYPE=noCopyright PROFILE=WD npm run test

The following example run tests to all the documents, but limit to copyright rule and using the noCopyright data.

$ RULE=copyright TYPE=noCopyright npm run test

4. JS API

The interface you get when you import { Specberus } from "specberus" is that from lib/specberus. Specberus is a class configured for operation in the Node.js environment.

(See also the REST API.)

Creating a Specberus instance

import { Specberus } from 'specberus';
const specberus = new Specberus();
// specberus.validate(...)
// specberus.extractMetadata(...)

validate(options)

This method returns a Promise that resolves with errors, warnings, and informative messages resulting from relevant checks.

options is an object accepting the following fields:

  • url: URL of the content to check. One of url, source, or file must be specified and if several are they will be used in this order.
  • source: A String with the content to check.
  • file: A file system path to the content to check.
  • profile: A profile object which defines the validation. Required. See below.

extractMetadata(options)

This method returns a Promise that resolves with metadata inferred from the document.

The options accepted are equal to those in validate(), with the following differences:

  • Optional additionalMetadata property, which performs additional checks (e.g. errata URL)
  • No profile or validation properties (this method can be used to determine profile)

The resolved object's metadata property points to an object with up to 20 properties, described below:

  • profile
  • title: The (possible) title of the document
  • docDate: The date associated to the document
  • thisVersion: URL of this version of the document
  • latestVersion: URL of the latest version of the document
  • previousVersion: URL of the previous version of the document (the last one, if multiple are shown)
  • editorsDraft: URL of the latest editor's draft
  • delivererIDs: ID(s) of the deliverer(s); an Array of Numbers
  • editorIDs: ID(s) of the editor(s) responsible for the document; an Array of Numbers
  • informative: Whether the document in informative or not
  • process: The process rules link
  • sameWorkAs: The previous shortlink if any
  • implementationFeedbackDue: The implementation review date for CRs
  • prReviewsDue: The review date for PRs
  • implementationReport: Implementation report link for CRs, PRs and RECs
  • errata: The errata link of the document
  • substantiveChanges: Whether the document is a REC and has proposed amendments
  • newFeatures: Whether the document is a REC and has proposed additions
  • sotd: The section "Status of this Document"
  • abstract: The abstract of the document

If some of these pieces of metadata cannot be deduced, that key will not exist, or its value will not be defined.

The following is an example of the value of the metadata object after the execution of Specberus.extractMetadata():

{
    "profile": "WD",
    "title": "Title of the spec",
    "docDate": "2016-2-3",
    "thisVersion": "https://www.w3.org/TR/2016/WD-foobar-20160203/",
    "latestVersion": "https://www.w3.org/TR/foobar/",
    "previousVersion": "https://www.w3.org/TR/2015/WD-foobar-20150101/",
    "editorsDraft": "https://w3c.github.io/foobar/",
    "delivererIDs": [123, 456],
    "editorIDs": [12345],
    "informative": false,
    "process": "https://www.w3.org/2015/Process-20150901/"
}

5. REST API

Similar to the JS API, Specberus exposes a REST API via HTTP too.

The base path is <host>/api/. Use either url or file to pass along the document (source is not allowed).

Note: If you want to use the public W3C instance of Specberus, you can replace <host> with https://www.w3.org/pubrules.

The different endpoints are described below.

version (GET)

Returns the version string, eg 1.5.3.

metadata (GET and POST)

Extract all known metadata from a document; see below for information about the return value.

validate (GET and POST)

Check the document (syntax). Many of the options understood by the JS method validate are accepted.

The special profile auto is also available.

Examples

1. Get API version of Pubrules

curl https://www.w3.org/pubrules/api/version

2. Get metadata of one document.

# GET
curl "https://www.w3.org/pubrules/api/metadata?url=https://example.com/doc.html"

# POST
curl "https://www.w3.org/pubrules/api/metadata" -F "file=@/tmp/foo.html"

# GET with additional metadata
curl "https://www.w3.org/pubrules/api/metadata?url=https://example.com/doc.html&additionalMetadata=true"

Metadata is a bunch of data extracted from the document. It includes the type (profile) of the document, publish date, editors' names, Patent Policy version the document is under, etc...

e.g. https://www.w3.org/pubrules/api/metadata?url=https://www.w3.org/TR/2021/WD-i18n-glossary-20210708/

3. Validate the document using profile: auto

# GET
curl "https://www.w3.org/pubrules/api/validate?url=https://example.com/doc.html&profile=auto"

# POST
curl "https://www.w3.org/pubrules/api/validate" -F "file=@/tmp/foo.html" -F "profile=auto"

Note: The POST method will skip some checks requiring the document to be staged online such as checking if assets in the same folder.

auto profile is the easiest way to validate a document. The validation relies on the automatically extracted data.

The validation result contains both the metadata and the errors/warnings regarding the document.

e.g. https://www.w3.org/pubrules/api/validate?url=https://www.w3.org/TR/2021/WD-i18n-glossary-20210708/&profile=auto

4. Validate the document using manual configs

Pubrules supports advanced configs to make the validation more accurate:

  • validation=recursive - Recursively validates multipart documents
  • The following profile values extend their base counterparts to additionally check that the document is valid for automatic publication with Echidna:
    • DRY-Echidna
    • DNOTE-Echidna
    • NOTE-Echidna
    • WD-Echidna
    • CRD-Echidna
    • CR-Echidna
    • REC-Echidna

e.g. https://www.w3.org/pubrules/api/validate?url=https://example.com/doc.html&profile=WD-Echidna&validation=recursive

Return values

Methods metadata and validate return a JSON object with these properties:

  • success (boolean): whether the operation succeeded, or not.
  • errors (array): all errors found.
  • warnings (array): all warnings.
  • info (array): additional, informative messages.
  • metadata (object): extracted metadata; see structure here.

If there is an internal error, the document cannot be retrieved or is not recognised, or validation fails, both methods would return HTTP status code 400. Also, in the case of validate, success would be false and errors.length > 0.

This is an example of a successful validation of a document, with profile auto:

{
    "success": true,
    "errors": [],
    "warnings": [
        "headers.ol-toc",
        "links.linkchecker",
        "links.compound",
        "headers.dl"
    ],
    "info": [
        "structure.display-only",
        "structure.display-only",
        "structure.display-only",
        "validation.wcag"
    ],
    "metadata": {
        "profile": "WD",
        "title": "Character Model for the World Wide Web: String Matching and Searching",
        "docDate": "2016-4-7",
        "thisVersion": "https://www.w3.org/TR/2016/WD-charmod-norm-20160407/",
        "latestVersion": "https://www.w3.org/TR/charmod-norm/",
        "previousVersion": "https://www.w3.org/TR/2015/WD-charmod-norm-20151119/",
        "editorsDraft": "https://w3c.github.io/charmod-norm/",
        "delivererIDs": [32113],
        "editorIDs": [33573],
        "informative": false,
        "process": "https://www.w3.org/2015/Process-20150901/",
        "url": "https://www.w3.org/TR/2016/WD-charmod-norm-20160407/"
    }
}

When the profile is given by the user (instead of being set to auto), fewer items of metadata are returned.

metadata returns a similar structure, where all values are empty arrays, except for the key metadata which contains the metadata object.

6. Profiles

Profiles are simple objects that support the following API:

  • name: A String being the name of this profile.
  • rules: An Array of rule objects which are checked in this profile.

A profile is basically a configuration of what to check. You can load a specific profile from under lib/profiles or create your own.

Here follows the current hierarchy of profiles. Each profile inherits all rules from its parent profile. Profiles that are identical to its parent profile, ie that do not add any new rules, are marked too.

  • base
    • TR
      • WD
        • WD-Echidna
      • FPWD (identical)
      • PR
      • CR
        • CR-Echidna
      • CRD
        • CRD-Echidna
      • REC
      • REC-OBSOLETE
      • REC-RSCND
      • REC-SUPERSEDED
      • DNOTE
      • DNOTE-Echidna
      • NOTE
      • NOTE-Echidna
      • STMT
      • DRY
      • CRY
      • CRYD
      • RY
    • Submission
      • SUBM
      • MEM-SUBM

7. Validation events

When using the JS API, the Specberus instance will fire various events. The Specberus class extends EventEmitter, so listeners can be registered using the on API.

const specberus = new Specberus();
specberus.on('err', (rule, data) => {
    // ...
});

Events listed below are expressed with parameters to reflect what is passed to the event handler.

  • done(ruleName): Fired when a specific rule has finished processing, including its asynchronous tasks. This fires regardless of whether the rule passes, fails, or encounters an unexpected system error (exception).
  • err(rule, data): Fired when an error is detected. There can be multiple errors for each rule.
    • rule contains information on which rule failed validation; always includes a name string, and may also include rule and section strings
    • data contains further details; always includes key and detailMessage strings, and optionally includes an extra object with additional fields that vary by error
  • warning(rule, data): Fired for non-fatal problems with the document that may nevertheless require investigation. There can be multiple warnings for each rule. rule and data follow the same format as for err events.
  • info(rule, data): Fired for additional information items detected by the validator. rule and data follow the same format as for err and warning events.
  • exception({ message }): Fired when there is an unexpected system error, such as a File not found error. The event passes an object with a message property containing details about this error. All exceptions are displayed on the error console in addition to this event being fired.

8. Writing rules

Rules are simple modules that expose a check(context) method. They receive a context object, which they use to examine the document and fire validation events. They return a promise which resolves on completion (regardless of pass or fail) or rejects on unexpected system error (exception). Usually, they are written as async functions to automatically handle the resolve vs. reject distinction.

The context object includes the following APIs useful for validation:

Properties

  • source. The HTML source of the document being processed
  • url. The URL of the document being processed, only applicable if options.url was specified
  • version. The Specberus version.

Methods

  • error, warn, info. Methods for firing respective levels of events on the instance. All three methods accept the same arguments:
    • rule object: at minimum, an object with a name string. May also contain rule and section strings.
    • key string: specifies the precise occurrence within the particular rule
    • extra object (optional): any additional fields to include within the event
  • checkSelector(selector, ruleName). Some rules need to do nothing other than to check that a selector returns some content. This handles checking the selector, reporting an error if it is not found, or throwing an error if the selector is invalid.
  • norm(text). Returns a whitespace-normalized version of the text.
  • getDocumentDate(). Returns a Date object that matches the document's date as specified in the headers' stateElement (id="w3c-state").
  • getDocumentStateElement(). Returns the element that contains the document's date.

About

Checker used at W3C to validate the compliance of Technical Reports with publication rules

Resources

License

Code of conduct

Stars

91 stars

Watchers

27 watching

Forks

Packages

 
 
 

Contributors