Bikeshed Documentation

Living Standard,


5. Markup Shortcuts

Bikeshed’s source format is roughly HTML, but it allows you to omit or shorten several verbose/annoying parts of the language, reducing the amount of format noise in the spec source, making it easier to read and write.

5.1. Markdown

Bikeshed uses a Markdown variant called Bikeshed-flavored Markdown (BSMD). By default, it recognizes all of the "block-level" Markdown constructs defined by CommonMark, except for indented code blocks:

Because it doesn’t have to handle indented code blocks, BSMD’s HTML handling is generally superior to other Markdown implementations. You can freely switch back and forth between Markdown and HTML as needed, and indent properly. (In fact, you should properly indent everything; if you don’t, you can sometimes get confusing errors!)

If the Markup Shorthands: markdown yes metadata is specified, it also recognizes several of the Markdown "inline elements":

It does not recognize "autolinks" (surrounded by <> characters), images, or "hard line breaks"; use HTML for these. It also does not recognize "link references" (defining the link location elsewhere, and referring to it by reference instead).

In addition to standard (CommonMark) Markdown, Bikeshed also recognizes definition lists, with the following format:

Here's the dl syntax:

: key
:: val
: key 1
: key 2
:: more vals

For all three list formats, on the rare occasions you need to add a class or attribute to the list, you can wrap it in the appropriate list container, like:

<ol class=foo>
  1. first
  2. second
</ol>

Bikeshed will use the container you provided, rather than generating a fresh one like it does by default.

Bikeshed also supports adding IDs to headings, via the Markdown Extra syntax:

Header 1 {#header1}
========

### Header 2 ### {#header2}

More of Markdown will be supported in the future, as I get closer to adhering to the CommonMark specification.

5.2. Bikeshed-Specific Character References

In addition to the standard HTML character reference syntaxes (named refs like &copy; or numeric refs like &#1234; or &#x1a2b;), Bikeshed supports a few custom character references to address some common needs. All of these look like &bs...;:

"bs" + any single ASCII punctuation character

This is an escape for that punctuation character. For example, &bs[; is an escape for the [ character, allowing you to escape an autolink without having to remember the codepoint of the character: &bs[;=foo=].

(Yes, semicolon works too, and still needs to be ended by a semicolon: &bs;; to produce ;.)

&bs<<;
&bs>>;
&bs->;

These are escapes for the [INFRA] syntax for lists and maps: «1, 2, 3» or «a→b, c→d ».

More of these will likely be added in the future.

5.3. Text Macros

Bikeshed supports the ability to use "text macros", spelled like [FOO] (a single uppercase word, surrounded by square brackets), which expand into other text.

Macros can be used in several places, which dictate how they’re parsed:

Macros are not substituted, by default, in the "link data" portion of autolinks, but this can be allowed by setting Markup Shorthands: macros-in-autolinks yes. With this, you can define a common long term in a macro, then use it in an autolink like [=[LONGTERM]=]. (Alternately, you can just put the autolink itself into a macro, like Text Macro: FOO [=foo=], and then [FOO] will expand to the autolink without having to adjust Markup Shorthands.)

Macros are also not substituted, by default, in the contents of style, script, xmp, or datablocks, as CSS/JS/etc are too likely to contain things that accidentally look like the macro syntax, and mixing another escaping syntax into those languages is more trouble than it’s worth. You can turn on macro substitution on an element-by-element basis by adding the bs-macros attribute, like <style bs-macros>html::before { content: "[TITLE]"; }</style>. This will substitute them as unparsed plain text, so beware if there is any markup in the macro.

Macros can contain more macros, which are substituted recursively, even when the macros aren’t otherwise parsed (like in attribute values).

It’s normally a fatal error to use a macro that isn’t defined, but you can loosen that restriction by putting a ? at the end, like [UNKNOWN?], which will cause the macro to substitute with the empty string if it’s not defined.

Macros can be escaped in several ways, if you need to write something that looks like [FOO] in your source:

5.3.1. Custom Macro Names

You can define your own macros via the Text Macros metadata, if you have some long term you’d like to avoid having to repeatedly type.

Macros are one of the possible tests you can use for § 13.2 Conditional Inclusion, so defining a custom text macro can be useful even if it doesn’t have a meaningful value.

5.3.2. Predefined Macro Names

Additionally, Bikeshed supports a number of macros automatically, computed from your spec’s metadata. Mostly, these are just used by your boilerplate file and won’t be seen in the actual document source.

As these are substituted at the text level, not the higher HTML level, you can use them anywhere, including in attribute values.

You can mark a macro as "optional" by appending a ? to its name, like [DATE?]. This will cause Bikeshed to just remove it (replace it with the empty string) if it can’t find a definition, rather than throwing an error.

Like most other markup shorthands, text macros can be "escaped" by prepending a backslash, like \[TITLE]. When Bikeshed sees this, it will remove the slash and leave the text alone. This is sometimes necessary when code examples in your doc (such as a regex) accidentally look like text macros.

5.4. Notes, Issues, Examples, Advisements

The Markdown processor specially recognizes paragraphs starting with "Issue: ", "Advisement: ", "Assertion: ", "Note: ", or "Note, ", and will add a matching class to the paragraph automatically. These classes default to .issue, .advisement, .assertion, and .note, but can be customized with the metadatas Issue Class, Advisement Class, Assertion Class, and Note Class. (However, the default classes receive styling from the default stylesheet, so make sure you provide your own styling if you change them.)

The default styling of these blocks includes a generated-content "header" containing the word "NOTE:", etc. Elements with the .example class will also be given a generated-content "header" in the format EXAMPLE n with an auto-incrementing number, and have self-links created to allow linking directly to the example.

If you’d like to provide your own custom header, write out the container element yourself (rather than using the Markdown shorthand, just create any element with the appropriate class), and add a heading="YOUR TEXT HERE" attribute to the container. It will automatically have "NOTE: "/etc prepended to it. (This is used by § 5.13 Remote Issues to put the GitHub issue title on the issue containers.)

Alternately, if you want full control over the contents of the heading, write out the container element and create a <div class=marker> element containing the text you want as its first child. (This is what the heading="" attribute does; it just automatically prepends "Note:"/etc to the text to keep it visually in line with other notes/etc by default.)

5.5. Typography Fixes

Bikeshed will automatically handle a few typographic niceties for you, ones that it can reliably detect:

5.6. Datablocks

Bikeshed supports embedding a number of custom DSLs into your document, known as datablocks. These are done by including a <pre> (or <xmp> or <script>) with a particular class. These are used for several types of definition tables, railroad diagrams, file includes, and bikeshed data sources.

Datablocks are specially parsed: initially, the parser just jumps straight to the closing tag without interpreting anything inside of them, so there’s no risk of Bikeshed-isms or inline Markdown accidentally being parsed. (Within a <pre> datablock, standard HTML is still parsed, so use <xmp> or <script> if you want to include < and & without escaping.) Even text macros aren’t parsed by default; put a bs-macros boolean attribute on the start tag if you want them.

The DSL will handle the actual parsing of the datablock contents, and might invoke Bikeshed’s full parser on parts of that text where it makes sense. It will also determine what to replace the datablock with; data sources simply disappear, while railroad diagrams become svgs, and definition tables become tables.

There are several autolink shortcuts that make autolinks much shorter to write, such as 'foo' to link to a CSS property or descriptor, or {{foo}} to link to an IDL construct. These are documented in § 7 Autolinking.

Other types of linking shorthand also exist, such as [[#foo]] to link to sections of a spec (documented in § 7.9 Section Links), or [[FOO]] to link to generate and link to bibliography entries (documented in § 8 Bibliography).

5.7.1. Autolink Shortcuts That Work Anywhere: the l element

The autolink shorthands don’t work in elements like pre, because it’s too easy for code constructs to look like autolinks. You can still manually write out your autolink as an a element, but that can be much more verbose than the terse syntax that the shorthands provide. (For example, {{Foo/bar()}} vs <a method for=Foo>bar()</a>.)

You can avoid this by using the l element, and putting an autolink shorthand inside of it, like <l>{{Foo/bar()}}</l>. This will autolink exactly the same as normal, but works anywhere in your document. Extra bonus: it will recognize all the autolinking syntaxes, even if you have some turned off with the Markup Shorthands metadata.

The l element itself is removed from the document and replaced by the autolink, but if you specify any attributes on the l, they’ll be transferred to the generated a. This is especially useful for autolinking attributes that can’t be specified in the autolink shorthand, like the spec to search for when disambiguating a one-off term: <l spec=foo>[=term that exists in multiple specs=]</l>. Without this, you’d have to convert the autolink fully to HTML, like <a dfn data-dfn-spec=foo>term that exists in multiple specs</a>

5.8. var and Algorithms

The var element (or its shorthand equivalent, |foo|) is often used to mark up "arguments" to a prose algorithm. Bikeshed explicitly recognizes this, and has several features related to this.

Algorithms can be explicitly indicated in your markup by putting the algorithm attribute on a container element or a heading. All vars within an algorithm are "scoped" to that algorithm.

Note: Algorithms need to have a name. By default, it’ll infer one if there’s only a single dfn inside the algorithm container, but if there’s zero or multiple dfns, or you just want to give a clearer name, you can supply it as the value of the algorithm attribute, like algorithm="to foo a bar".

Generally, vars are used at least twice in an algorithm: once to define them, and at least once to actually use them for something. If you use a var only once, there’s a good chance it’s actually a typo. Bikeshed will emit a warning if it finds any vars used only once in an algorithm. If this singular usage is correct, you can instruct Bikeshed to ignore the error by adding an ignore attribute to the var itself. (There’s no way to do this with the |foo| syntax; you have to convert it back to an actual var element.)

5.9. Code Blocks (pre, etc)

Bikeshed has several nice features related to "code blocks"—​pre, xmp, and sometimes code.

5.9.1. pre whitespace stripping

Using a pre element in HTML is unsatisfying, because it forces you to break your indentation strategy, pulling the content back to the margin edge (or else employing silly hacks with comments and explicit newlines). The preprocessor fixes this.

Whenever a pre element is encountered, the processor records how much whitespace precedes the first line, and then strips that much whitespace from it and all following lines.

Additionally, if the closing </pre> is on its own line, the processor automatically pulls it up onto the end of the previous line, so there’s no final blank line in the content.

In other words, you can now write:

<div class='example'>
  <p>
    An example:

  <pre>
    &lt;ul>
      &lt;li>one
      &lt;li>two
    &lt;/ul>
  </pre>
</div>

The preprocessor will automatically convert it into:

<div class='example'>
  <p>
    An example:

  <pre>
&lt;ul>
  &lt;li>one
  &lt;li>two
&lt;/ul></pre>
</div>

5.9.2. xmp To Avoid Escaping Markup

The xmp element is an old HTML element that’s now deprecated (but still required to be supported). It was intended for markup examples (thus the name), and has magical parsing properties, where its contents (everything until the </xmp> closing tag) are treated as literal text, and not interpreted as HTML. In particular, this means that within an xmp you don’t need to escape your < or & characters.

Bikeshed supports using xmp anywhere a pre can be used; it converts it into a properly-escaped pre in the output to avoid validation errors. For example, the two markup examples in the previous section are using xmp in this document’s source.

Use of xmp is particularly useful for IDL blocks, as IDL uses <foo> syntax for higher-order types (like sequence<DOMString>). If you’re using a pre and don’t remember to escape this, you’ll end up with confusingly-broken IDL, as the <DOMString> part is interpreted as an opening HTML tag. If you use xmp instead, there’s no need to remember to escape anything; you can write or copy raw WebIDL into the block and it’ll be interpreted correctly.

5.9.3. Syntax Highlighting

You can syntax-highlight code blocks. Just add either a highlight="foo" attribute or a lang-foo class to the element, or set a Default Highlight metadata, and the element will automatically be syntax-highlighted according to the "foo" language rules. (Setting no-highlight closer will turn if off for an element; it looks for the closest ancestor with one of the attributes.)

The syntax highlighter uses Pygments, which supports a large set of languages. See http://pygments.org/docs/lexers/ for the full list. (Use one of the "short names" of the language for the "foo" value.)

Bikeshed comes with a default color scheme based loosely on that of Prism.js. If you would like to use your own color scheme, turn off the automatic styles with a Boilerplate: style-syntax-highlighting off metadata, then supply your own.

Note: If you use highlight=html, script and style elements are automatically highlighted with JS and CSS rules. Normative WebIDL blocks (class=idl) and CDDL blocks (class=cddl) are automatically highlighted, but you can use highlight=idl and highlight=cddl to highlight non-normative ones.

Note: If your code block already has markup in it, this feature will safely "merge" the highlighting into your existing markup.

5.9.4. Line Numbers

You can automatically generate line numbers for code blocks by adding a line-numbers attribute to the element or an ancestor, or setting the Line Numbers metadata to affect all elements. (Setting no-line-numbers closer will turn it off for an element; it looks for the closest ancestor with one of the attributes). The numbers are added to each line via CSS generated content, so they’ll always stay in sync and won’t get copied when you highlight a chunk of text.

Haikus are easy:five-seven-five syllables,spread over three lines.

The lines default to starting at 1; to change that, set the line-start attribute on the element to your desired starting value.

If you would like to produce your own line-numbering CSS, turn off the automatic styles with a Boilerplate: style-line-numbers off metadata, then supply your own.

Note: Similar to syntax highlighting, this feature will safely "merge" the line-numbers markup into your existing markup. The only complication is if the original markup has elements that span more than one line; in this case, the "line" element will expand to cover all the lines spanned by your original markup. It will still put a line marker on the first and last line of this span, so the effect isn’t too noticeable if the original markup only spans two lines.

5.9.5. Highlighting Particular Lines

If you want to bring attention to particular lines in your code snippet, but need to show more surrounding code for context, you can highlight the important ones with a line-highlight attribute.

Another haiku.This is the important line.Ignore what's down here.

The syntax of line-highlight is a comma-separated sequence of either integers (like 5), or integer ranges (like 2-4). For example, line-highlight="2-4, 6" will highlight lines 2, 3, 4, and 6.

Like line-numbers (above), this defaults to considering the first line of the snippet as line 1, but the numbering can be changed with the line-start attribute.

If you would like to produce your own line-highlighting CSS, turn off the automatic styles with a Boilerplate: style-line-highlighting off metadata, then supply your own.

Note: This feature has the same restriction on line-spanning elements as the line-numbers feature does. In particular, if any line being wrapped in a multi-line "line" element is highlighted, the entire "line" element gets highlighted.

5.10. Automatic ID Generation

If any heading, issue, or dfn element doesn’t have an id attribute, one will be automatically generated by the processor, to ensure it’s usable as a link target.

Heading IDs are generated directly from the text contents of the element, cleaning up the characters to be a valid id. This often isn’t the best for complex heading texts, so it’s not recommended to rely on this. (Bikeshed will warn you that it’s generating IDs, and suggest you supply one manually.)

If a heading changed significantly, so that you want to change the ID, but you want links to the old heading ID to still work, put the old ID in an oldids="" attribute on the heading element. If there are multiple, comma-separate them.

Issues (elements with class="issue") will generate IDs of the form "issue-###", where "###" is substring of a hash of the issue’s contents. This means that an issue’s ID will be stable against changes elsewhere in the document, including adding or removing issues above it in the source, but will change if you change the contents of the issue.

Definition IDs are also generated directly from the text contents of the element. Most definitions additionally get a prefix, such as "propdef-", to avoid clashes with other definitions.

If an automatically-generated ID would collide with any other ID, it’s automatically de-duped by appending a number to the end. This isn’t very pretty, so if you want to avoid it, supply an ID yourself.

5.11. Assertions

Bikeshed provides the ability to mark "assertions" that tests can refer to. The assertion can either be added with the fake element <assert> or by adding an assert attribute to a div. (e.g. <div assert>).

For the <assert> tag, it will be replaced by a <span> tag in the generated source. The <div> tag will pass through but the assert attribute is removed.

In both cases a unique ID is generated from the tags contents of the form "assert-###", where "###" is a substring of a hash of the assertions contents. This ensures that you have a unique ID that won’t change arbitrarily, but will change when the contents of the assertion change, making it easier to tell when a test might no longer be testing the assertion it points to (because it’s no longer pointing to a valid target at all!).

Giving IDs to important things in your document, like headings and definitions, is great, but of little use if people don’t know they can link to them. Bikeshed will automatically generate a "self-link" in the margin next to certain linkable elements which just links to the element, so people can click on the link and then just copy the URL from their address bar to get a link straight to what they care about.

Self-links are currently auto-generated for headings, definitions, and issues, and notes, examples, <li>s, and <dt>s that have been given IDs.

5.13. Remote Issues

There are a few ways to easily link to issues in your source repository.

If Markup Shorthands is set to repository-links yes (which it is by default), you can also use inline repository links of the form <#123> or <org/repo#123>. This’ll generate an HTML link pointing to the issue, with appropriate text like issue #1532.

If you’re using Issue: paragraphs (as described in § 5.4 Notes, Issues, Examples, Advisements), you can instead write Issue(###):, where the ### is some identifying value for the issue.

By default, it’s assumed this is a GitHub issue, of the form 123, #123, or org/repo#123. Plain numbers will refer to the "local" repository (either specified by the Repository metadata, or auto-detected from the source folder), while the more explicit form refers to the specified repository.

This will generate a link to the specified issue at the end of the issue paragraph, like this. [Issue #1532]

If no repository is detected, or the identifier doesn’t look like the above patterns, Bikeshed will check for an Issue Tracker Template metadata to format the issue link instead. This only applies to Issue(): paragraphs, not inline repository links.

Inline GitHub Issues also affects these Issue(): paragraphs.

5.14. Including Other Files

Sometimes a spec is too large to easily work with in one file. Sometimes there’s lots of repetitive markup that only changes in a few standard ways. For whatever reason, Bikeshed has the ability to include additional files directly into your spec with a <pre class=include> block:

<pre class=include>
path: relative/to/spec/location
</pre>

The included document is parsed just like if it were written in locally, except that metadata blocks aren’t processed. (For various reasons, they have to be parsed before any other processing occurs). This means that the include file can use markdown, data blocks of various kinds (<pre class=anchors>, <pre class=railroad>, etc), and both provide definitions for the outer document and refer to ones defined by the outer document.

Note: All include paths are processed relative to the outermost spec document’s location. If you’re including a document in another folder, and it includes a document itself, take care that your paths are correctly relative to the outermost spec, not to the included file.

If you’re including a block of repetitive markup multiple times, and want to vary how it’s displayed, you can pass additional "local" text macros in the block, which are valid only inside the included file:

<pre class=include>
path: template.md
macros:
  foo: bar
  baz: qux qux qux
</pre>

With the above code, you can use [FOO] and [BAZ] macros inside the include file, and they’ll be substituted with "bar" and "qux qux qux", respectively. (Remember that you can mark text macros as optional by appending a ?, like [FOO?], in which case they’ll be replaced with the empty string if Bikeshed can’t find a definition.)

5.14.1. Including Code Files

While it’s easy to include short code snippets in your document inline with an ordinary <pre> block (particularly with a highlight attribute so it’s formatted nicely), you sometimes want to instead include snippets of a larger external file. (For example, so you can keep that file up-to-date easily, without having to go in and fiddle with all the chunks you’ve inlined into your document.)

Normal includes don’t work for this, as they include the whole file and assume that it’s more Bikeshed code; instead, use <pre class=include-code> to include part (or all) of a file and have it rendered as highlightable source code.

<pre class=include-code>
path: bigFile.cpp
highlight: c++
show: 100-120
</pre>

This snippet will create a nicely highlighted code block containing lines 100-120 of the file bigFile.cpp.

You can additionally include any of the more advanced highlighting options (§ 5.9.4 Line Numbers, § 5.9.5 Highlighting Particular Lines), using the same names and value syntax as you would use when specifying them as attributes:

<pre class=include-code>
path: someFile.cpp
highlight: c++
line-numbers:
line-highlight: 2-5, 10, 12
</pre>

If any of your options cause line-numbers to show up (using line-numbers or line-highlight), and you’re showing a snippet of the larger file with show, the numbering will default to using the numbering of the original file (so if you said show: 6-10, the first visible line will be numbered "6"). You can override this with line-start, as usual.

Note that, unlike <pre class=include>, there is no macros option.

5.14.2. Including Non-Bikeshed HTML/SVG/etc

<pre class=include> lets you insert chunks of Bikeshed source code into a larger outer document. But what if you want to include some markup that isn’t formatted as Bikeshed code? For example, SVG outputted by a design tool might not conform to Bikeshed’s syntax—​it might not indent properly, or it might use markup that will get messed up if parsed as Markdown, etc.

To avoid this, you can use <pre class=include-raw>. Just like <pre class=include>, it takes a single path line:

<pre class=include-raw>
path: myDiagram.svg
</pre>

…and replaces itself with that markup directly, without doing any additional Bikeshed syntax processing.

Note: Unlike <pre class=include>, there are no local macros, as macro substitution is part of Bikeshed’s syntax processing, which is skipped here.

Note: Most parts of later Bikeshed processing do work, such as linking to definitions, etc., because inclusions are processed very early in Bikeshed’s transformation pipeline. However, if you’re writing something that’s intended to use Bikeshed’s features, you should really write Bikeshed source code and use <pre class=include>, in case some things move to being part of syntax processing. For example, inline autolinking shorthands currently aren’t, and so will work in include-raw substitutions, but that will change in the future.

5.15. Tracking Vectors

A tracking vector can be annotated with the tracking-vector attribute on the enclosing element. This will result in a link containing an image being prepended to the element.

<p tracking-vector>This is an example of an element annotated with that attribute.

There is a tracking vector here. This is an example of an element annotated with that attribute.

The various "Tracking Vector *" metadata keys can be used to customize the appearance of this annotation, though it’s encouraged to leave those in their default state for a consistent appearance across standards.

5.16. Image Size Detection

If an img element has a neither a width nor a height attribute, Bikeshed will automatically detect these dimensions from the image file and insert both attributes into the resulting markup.

Given this markup:
<img alt="…" src="img.jpg">
if the img.jpg file is 300 pixels wide and 100 pixels tall, bikeshed will generate the following output:
<img alt="…" src="img.jpg" width="300" height="100">

Bikeshed will also detect and insert the dimensions of the image if the element has no src attribute but does have a srcset attribute. In that case, it accepts a narrow subset of the srcset syntax: a single image source URL followed by a single pixel density descriptor, limited to integers. Since the src attribute is mandatory in HTML, bikeshed will also add it to the output.

In order to specify high resolution images, use the following syntax:
<img alt="…" srcset="highDPI.jpg 2x">
If the highDPI.jpg file is 600 pixels wide and 200 pixels tall, bikeshed will generate the following output:
<img alt="…" src="highDPI.jpg" srcset="highDPI.jpg 2x" width="300" height="100">

Note: Bikeshed will only successfully detect the size of local images, and will not attempt to fetch resources over the network, as there is no way for Bikeshed to know whether the size it would get is stable. Using local images is generally preferred, but if you need to use a remote one, consider setting the width and height manually.

If either of the width and height attributes is already set (or both are), or if both the src and srcset attributes are set, Bikeshed will assume you know what you’re doing, skip detection, and leave the element unchanged.

To opt out of this automated size detection for a single image, set the boolean no-autosize attribute on it. To opt out for the entire document, specify the Image Auto Size metadata with the value false.


4 Metadata Table of Contents 6 Definitions