# Bikeshed Documentation

## Living Standard, 19 December 2025

Defining a term is as easy as wrapping a `dfn` element around it. Most of the time, this is all you’ll need to do - the definition automatically gains an id, and is usually automatically exposed as an autolink target for local and cross-spec autolinks.

Autolinking is a special mechanism in the processor to let you link terms to their definitions without having to explicitly provide a url. Instead, the text of the link is matched against the text of the definitions, and if a match is found, the link’s `href` is set up to connect the two.

### 6.1. Conjugating/Pluralizing/etc the Linking Text

Bikeshed can automatically handle a wide range of English conjugations and pluralizations. For example, if you define the term "snap", you can link to it with "snapping" or "snapped" without having to manually add those variations to your `dfn` manually.

As such, it’s best to define your term in the "base" form, singular and present tense. Use `lt='...'` if necessary to set up the correct "base" linking text, if your visible text needs to be in a conjugated form due to the surrounding text.

These variations only work for the first or the last word in a phrase, so it can conjugate "activate the widget" into "activating the widget", "activate the widgets", or "activating the widgets". If you have a longer phrase where it’s a middle word that conjugates differently, you do still have to manually handle that, either by defining multiple linking texts on the `dfn`, or by manually specifying the linking text on the `a`.

In addition to English variations, these "conjugations" handle some IDL variations as well. For example, IDL terms that match an IDL keyword must be defined in IDL with a leading underscore, to avoid grammatical ambiguities, but actually define the term without the underscore. You can link to the term with either syntax.

Similarly, because methods and attributes technically live in the same namespace, it’s safe to link to a method without the parens after its name. (This is useful when linking to a method in the middle of prose, when you might be providing sample arguments that would interfere with linking, or linking to things in the arguments, which would interact badly with the arguments themselves being part of the method’s link text.)

### 6.2. Changing the Linking Text

Sometimes, the text of the definition isn’t exactly what you want it to be linked by, or you may want it to be linkable with more than one phrase. For example, an algorithm named "Check if three characters would start an identifier" may also want to be linkable from the phrase "starts with an identifier". To alter the linking text, simply add an `lt` attribute (for "Linking Text") to the definition; the linking text is used instead of the text content. You can separate multiple linking phrases by separating them with the pipe "|" character.

### 6.3. Defining Extra-Short "Local" Linking Texts

Sometimes you want to use an extra-short version of a term for within a spec, but don’t want to confuse things by exporting it globally. To achieve this, add a `local-lt` attribute with the terms you want to be only usable within the spec; the syntax is identical to that of the `lt` attribute, described above.

Using local linking text does not disturb the normal linking-text process; that still takes from either the element text or the `lt` attribute, as normal.

### 6.4. Definition Types

All definitions have a definition type. This allows for "namespacing" of the linking text, so you can define, for example, both a property and a term with the same linking text, such as "direction" or "color".

There are several types for CSS values:

- property

- descriptor (the things inside at-rules like @font-face)

- value (any value that goes inside of a property, at-rule, etc.)

- type (an abstract type for CSS grammars, like `<length>` or `<image>`)

- at-rule

- function (like `counter()` or `linear-gradient()`)

- selector

There are additional types for WebIDL definitions:

- interface

- constructor

- method

- argument

- attribute

- callback

- dictionary

- dict-member

- enum

- enum-value

- exception (for new DOMException names)

- const

- typedef

- stringifier

- serializer

- iterator

- maplike

- setlike

- extended-attribute (things like `[EnforceRange]`)

And for HTML/SVG/etc element definitions:

- element

- element-state (a spec concept, like `input` being in the "password state")

- element-attr

- attr-value

There are types for CDDL definitions:

- cddl-module (when spec needs to define multiple CDDL modules)

- cddl-type (things like actual types and groups)

- cddl-key (member names in type or group definitions)

- cddl-value (values in an enumeration)

- cddl-parameter (generic parameter names)

A special type for URL schemes, like "http" or "blob":

- scheme

A special type for HTTP headers:

- http-header

A special type just for definitions of operators used in grammar definitions, like `||` and similar:

- grammar

A special type for browser permissions:

- permission

And finally, some categories for "English" terms:

- abstract-op (for "English-language algorithms")

- dfn (for general terms and phrases, and a catch-all for anything else)

The processor will attempt to infer your definition type from the context and text content of the definition:

- Is it inside a propdef, descdef, or elementdef block? Then it’s a property, descriptor, or element.

- Is it inside an idl block (<pre class='idl'>)? Then it’s one of the IDL types, inferred by parsing the IDL.

- Is it inside a cddl block (<pre class='cddl'>)? Then it’s one of the CDDL types, inferred by parsing the CDDL.

- Do you have the Infer CSS Dfns metadata turned on? (It’s on by default for the SVG, CSSWG, FXTF, and Houdini Groups.) Then:

  - Does it start with `@`? Then it’s an at-rule.

  - Is it surrounded by `<>`? Then it’s a type.

  - Does it start with a `:`? Then it’s a selector.

  - Does it end with parentheses `()` (possibly containing arguments)? Then it’s a function.

  - Is it surrounded by double single quotes in the source, like `''foo''`? Then it’s a value.

- Otherwise, it’s a dfn.

(This auto-detection is obviously skewed towards CSS types; Bikeshed started as a CSS spec preprocessor, and the CSS types are easier to auto-detect syntactically than anything else.)

Note that this auto-detection is a last-resort operation. There are methods (defined below) to explicitly indicate what type a definition is, and those win over the auto-detection.

If your value doesn’t fit one of these categories, you’ll have to tag it manually. Just add the type as a boolean attribute to the definition, like

    attribute DOMString <dfn attribute for=Foo>name</dfn>;

Alternately, if you’ve got several definitions of the same type that share some container element (such as a `<pre>` or `<dl>`), just add a `dfn-type="type-goes-here"` attribute to the container. Anything which isn’t explicitly tagged otherwise will take that type by default.

(There are more methods to determine definition type, but they’re only meant for legacy content, and so are not documented here.)

### 6.5. Namespacing a Definition

Some types of definitions are defined relative to a higher construct, such as values for a particular property, or attributes of a particular IDL interface. This is useful, as it means these names don’t have to be globally unique, but that means your autolinks may have a hard time telling which name you intend to link to.

To fix this, the processor enforces that some types of definitions must define what they are for. This is specified with a `for` attribute on the definition.

Specifically:

- "attribute", "constructor", "method", "const", "event", "serializer", "stringifier", and "iterator" definitions must define what interface they’re relative to.

- "argument" definitions must define what method or constructor they’re relative to.

- "dict-member" definitions must define what dictionary they’re relative to.

- "enum-value" definitions must define what enum they’re relative to.

- "element-attr" and "element-state" definitions must define what element they’re relative to.

- "attr-value" definitions must define what element and attribute they’re relative to.

- "descriptor" definitions must define what at-rule they’re relative to. (This happens automatically if you add a "For" line to the descdef table.)

- "value" definitions must define what property, descriptor, at-rule, type, selector, or function they’re relative to. If a value definition is relative to a descriptor, the value must be of the form "@foo/bar", where "@foo" is the at-rule the "bar" descriptor is relative to.

- "cddl-key", "cddl-value", and "cddl-parameter" definitions must define what CDDL type they’re relative to.

Just like with the definition type, you can instead declare what several definitions are for by putting an attribute on a container. In this case, just add `dfn-for` to the container. This is especially useful for property/descriptor values, as they’re usually defined in a `dl`, or IDL definitions, as you can just put a `dfn-for` on the <pre class='idl'>.

If a single definition is "for" multiple things, you can provide a comma-separated list of values in the attribute.

### 6.6. Exporting Definitions

Most definitions are automatically "exported", which means they’re made available for other specs to autolink to. The only exceptions are "dfn" and "cddl" type definitions, which aren’t exported by default.

To force a link to be exported, add an `export` boolean attribute to it. To force a link not to be exported, add a `noexport` boolean attribute instead. Like the other attributes, you can instead add this to a container to have it be a default for the definitions inside.

### 6.7. Link Attributes On Ancestors

All of the dfn attributes can be specified on an ancestor of the dfn instead, if you have a group of dfns that all share a particular attribute.

They can be spelled out fully (like `data-dfn-type`), or without the `data-` prefix, like `dfn-type` or `dfn-for`. As there’s no overlap with a similar `data-link-*` attribute, `dfn-force` can omit `dfn-` as well, being spelled as merely `force` and `spec`.

A link will take the "closest" version of each attribute it can find, so specifying an attribute directly on the link will override anything coming from an ancestor.

### 6.8. Providing Custom Definitions

If you want to link to dfns in specs that aren’t yet part of the autolinking database, you can provide your own definition data that Bikeshed can use. Within a `<pre class='anchors'>` element, define the anchors you need in InfoTree format, with the following keys:

- text - the linking text for the definition. (Exactly 1 required.)

- type - the definition’s type (dfn, interface, etc) (Exactly 1 required.)

- urlPrefix and/or url - define the anchor’s url, as described below. (At least one of `urlPrefix` or `url` must be specified. 0+ `urlPrefix` entries allowed, 0 or 1 `url` entries allowed.)

- for - what the definition is for. (Any number allowed, including 0.)

- spec - Which spec the definition comes from. (optional)

To generate the url for the anchor, first all of the `urlPrefix` entries are concatenated. If a `url` is provided, it’s appended to the prefixes; otherwise, the `text` is url-ified and appended. (Lowercased, spaces converted to dashes, non-alphanumeric characters dropped.) If neither `urlPrefix` nor `url` had a "#" character in them, one is inserted between them.

The `spec` attribute is used only for index generation, and has no effect on URL generation.

Example:

    <pre class="anchors">
    urlPrefix: https://encoding.spec.whatwg.org/; type: dfn; spec: ENCODING
      text: ascii whitespace
      text: decoder
    url: http://www.unicode.org/reports/tr46/#ToASCII; type: dfn; text: toascii
    </pre>

    <a>ascii whitespace</a> links now!

Alternately, this data can be provided in a file named `anchors.bsdata`, in the same folder as the spec source, but this prevents you from using the web service.

### 6.9. Definitions data model

Bikeshed’s most important feature is its powerful cross-spec autolinking. This is possible due to each definition being annotated with a rich set of metadata, which is then exposed via custom attributes and picked up by specialized scrapers (such as Shepherd) that then compile a definition database that Bikeshed relies on.

If you’re writing a spec processor or related tool and would like to interoperate with the Bikeshed ecosystem, here’s the full definition data model and how to properly expose it.

1. The defining element MUST be a `dfn` or `h2`...`h6`. No other element is recognized as defining a term.

2. The element MUST have an `id` attribute.

3. The linking text defaults to the text content of the `dfn`/heading. If the desired text content isn’t suitable for linking text, or you wish to provide multiple linking texts, a `lt` attribute containing one or more pipe-separated linking texts will override the text content. See also § 6.3 Defining Extra-Short "Local" Linking Texts

4. `data-dfn-type` MUST be provided, and set one of the accepted values.

   (In an actual Bikeshed document, this can be omitted from `dfn` elements and it will be inferred from context, usually defaulting to "dfn" type. But non-Bikeshed documents must specify this, or else they’ll get their dfn type inferred heuristically, which may or may not be correct.)

5. Either `data-export` or `data-noexport` MAY be provided (both boolean attributes). If neither is provided, "dfn" type definitions default to noexport, while all others default to export. Unexported definitions aren’t linkable by default.

6. Several types of definitions are namespaced to another construct; for example, attribute names are namespaced to an interface. These definitions MUST contain a `data-dfn-for` attribute, containing a comma-separated list of one or more definitions they’re namespaced to.

If you have written a web spec and it conforms to this definition syntax, contact the project maintainer and ask them to register your spec in Shepherd, so its definitions will be available to everyone else.

## Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with `class="example"`, like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with `class="note"`, like this:

Note, this is an informative note.