This document describes the structure that individual MDN reference documentation pages should have, and how the linter should check that the documentation follows the defined structure.
A set of documentation - the JavaScript reference documentation, for example - consists of several different page types, where each type describes the same sort of thing. For example, one page type describes classes, a different type describes methods, and another describes properties.
Different page types will need to contain different elements. For example, pages for JavaScript classes will want to contain lists of links to its members, while pages for a JavaScript method will want to contain a section describing the method syntax.
To reflect this, a "recipe" is a short YAML file that describes at a high level the elements that a particular type of page must have. A recipe provides a list of elements that must appear in the page in the order given. Each distinct type of page must map to a single recipe.
Each element in a recipe is called an "ingredient". Ingredients are often shared across recipes. So for example we have an ingredient called data.browser_compatibility
, which most recipes will contain. Each ingredient may have particular requirements about how it is represented in the page: for example, to satisfy the data.browser_compatibility
ingredient a page must include the {{Compat}}
KumaScript macro.
So at a high level, compliance to a recipe means:
the items in the page must correspond to the ingredients listed in the recipe, in the correct order, and each item must satisfy the particular requirements for its ingredient.
A recipe can mark an ingredient as optional by placing a question mark after it, like prose.description?
. This means that the page does not have to contain a representation of the ingredient, but if it does, the representation must be properly formed according to the ingredient's specification, and the representation must appear in the place specified by the recipe.
Technically, whether an ingredient is optional or not is a separate attribute of the ingredient. This means that a single ingredient may be marked as optional in one recipe and mandatory in a different recipe. In practice, in the our documentation, this does not occur: there are currently no ingredients that are optional in some recipes and mandatory in others.
Many, but not all, ingredients correspond to sections of a page. A section of a page is defined as a part of the page beginning with an <h2>
heading and ending with either another <h2>
or the end of the page.
Sections are identified by an id
attribute on the <h2>
. For example, the prose.description
section starts with an element whose opening tag is like <h2 id="Description">
. In this document we'll refer to page sections using a notation like h2#identifier
: for example, h2#Description
.
We've defined the following recipes for the JS docs:
- javascript-class
- javascript-namespace
- javascript-constructor
- javascript-method
- javascript-property
- javascript-error
- javascript-language-feature
In total these recipes use the following ingredients:
prose ingredients:
- prose.*
- prose.accessibility_concerns?
- prose.description?
- prose.error_type
- prose.message
- prose.see_also
- prose.short_description
- prose.syntax
- prose.what_went_wrong
data ingredients:
- data.browser_compatibility
- data.permitted_properties?
- data.constituent_properties
- data.constructor
- data.constructor_properties?
- data.examples
- data.formal_definition
- data.formal_syntax
- data.instance_methods?
- data.instance_properties?
- data.interactive_example?
- data.specifications
- data.static_methods?
- data.static_properties?
All ingredients except two are demarcated in the page using an <h2>
heading. The exceptions are prose.short_description
and data.interactive_example
.
With three exceptions, all prose ingredients impose the same requirement on the page: it must have an <h2>
section whose ID attribute maps to the named section. The mapping is simply that prose.
is removed, and the first letter is capitalized:
prose.syntax -> h2#Syntax
prose.see_also -> h2#See_also
The exceptions are prose.short_description
, prose.description?
, and prose.*
.
This is an optional prose ingredient. To satisfy the ingredient, if the page contains an h2#Description
section, then it must appear in the place specified by the recipe.
This ingredient isn't demarcated by an <h2>
at all. To satisfy the ingredient, a page must:
- contain a
<p>
element - that is not a note or a warning
- before the interactive example or the first
<h2>
, whichever comes first
This ingredient enables writers to include extra sections that are not explicitly listed in the recipe, while ensuring that the extra sections always appear in the same place in the page. To satisfy this ingredient: if the page contains any <h2>
headings that are not expected by the recipe, then they must appear at the point in the page that the prose.*
ingredient is listed in the recipe.
Data ingredients typically impose more detailed requirements on pages than prose ingredients.
To satisfy this ingredient a page must have a section demarcated by H2#Browser_compatibility
. It must contain a call to the {{Compat}}
macro.
This is an optional ingredient. It is present if the page has a section demarcated by H2#Permitted_properties
. The section must contain only the following elements:
-
A
<p>
element consisting of the text:Rules whose selectors include this element may only use the following CSS properties:
-
An unordered list (a
<ul>
element) of two or more CSS property names. Each property name must be in the form<li><a><code>p</code></a></li>
, where p is the name of a property. The<li>
elements must be in alphabetical order.
To satisfy this ingredient a page must have a section demarcated by H2#Constituent_properties
. The section must contain only the following elements:
-
A
<p>
element consisting of the text:This property is a shorthand for the following CSS properties:
-
An unordered list (a
<ul>
element) of two or more CSS property names. Each property name must be in the form<li><a><code>p</code></a></li>
, where p is the name of a property. The<li>
elements must be in alphabetical order.
To satisfy this ingredient, a page must contain a section demarcated by H2#Constructor
that contains one of the following:
-
Only a
<dl>
element.- The
<dl>
must contain a single<dt>
followed by a single<dd>
. - The
<dt>
must contain either:- only a single
<code>
element, that contains only a single<a>
element - only a call to the
{{jsxref}}
macro.
- only a single
- The
<dd>
must contain eitherCreates a new <code>NameOfTheObject</code> object.
orCreates a new <code>NameOfTheObject</code> value.
whereNameOfTheObject
is replaced with the actual name.
- The
-
A
<p>
element that starts with the text "This object cannot be instantiated directly.".
This is an optional ingredient. If a page contains a section demarcated by H2#Constructor_properties
, then it must meet the following requirements:
- Must contain only a
<dl>
element. - The
<dl>
must contain one or more<dt><dd>
pairs. - The
<dt>
must contain either:- only a single
<code>
element, that contains only a single<a>
element - only a call to the
{{jsxref}}
macro.
- only a single
<dt><dd>
pairs must be ordered by the alphabetical order of the<dt><code><a>
text content, or by the display name given in the{{jsxref}}
macro call.
To satisfy this ingredient a page must have a section demarcated by H2#Examples
. It must contain one or more sections demarcated by an H3. Each of these H3 sections represents a single example.
Each example may be a simple example or a live sample. If the example contains a call to the {{EmbedLiveSample}}
macro, it is a live sample. Otherwise it is a simple example.
Live samples must satisfy certain additional constraints:
- The call to
{{EmbedLiveSample}}
must be the last element in the example (the only exception is that text nodes consisting only of newlines may follow the{{EmbedLiveSample}}
call). This implies that there may only be one live sample in a given H3 section, and that the iframe showing the output must appear last in the rendered page, after any code or explanatory prose. - The ID parameter passed to
{{EmbedLiveSample}}
must match the ID of the example's H3 heading. This implies that the example is not allowed to contain any code blocks that are not included in the live sample.
To satisfy this ingredient a page must have a section demarcated by H2#Formal_definition
. It must contain only a single <p>
, itself containing a single {{CSSInfo}}
macro call.
To satisfy this ingredient a page must have a section demarcated by H2#Formal_syntax
. It must contain only a single <pre class="syntaxbox">
, itself containing a single {{CSSSyntax}}
macro call.
This is an optional ingredient. It's just the same as data.constructor_properties?
, except the section is demarcated by H2#Instance_methods
.
This is an optional ingredient. It's just the same as data.constructor_properties?
, except the section is demarcated by H2#Instance_properties
.
This is an optional data ingredient. To satisfy the ingredient, either:
- the page must not contain a
{{EmbedInteractiveExample}}
macro call, or - the page must have a
<div>
containing an{{EmbedInteractiveExample}}
macro call. The<div>
must be immediately preceded by paragraph that is neither a note nor a warning. The<div>
must precede any<h2>
.
To satisfy this ingredient a page must have a section demarcated by H2#Specifications
. It must contain either a call to the {{SpecName}}
macro, or a text node containing the text "Not part of any standard.".
This is an optional ingredient. It's just the same as data.constructor_properties?
, except the section is demarcated by H2#Static_methods
.
This is an optional ingredient. It's just the same as data.constructor_properties?
, except the section is demarcated by H2#Static_properties
.