Skip to content

Grammar

cssdoc's doc-comment syntax is defined by a formal, RFC-style specification written in grammarkdown, modeled on TSDoc's DeclarationReference.grammarkdown. It's organized as a lexical grammar — characters, comment framing, tokens, and names — building toward a syntactic grammar: the doc comment, its block tags, and the CssReference used inside inline {@link} and {@inheritDoc} tags.

The grammar is the source of truth for the shape of a doc comment. The runtime parser in @cssdoc/core is hand-written to conform to these productions, and a test validates the spec on every run, so the two can't drift. grammarkdown is notation and validation only — it doesn't generate a parser.

In the notation, :: marks a lexical production and : a syntactic one. Terminals are in backticks, and > … lines are prose used for character classes and layout-sensitive constructs that sit outside context-free notation.

grammarkdown
// CssDoc — the doc-comment grammar for @cssdoc/core.
//
// A formal, RFC-style specification of the tag vocabulary parsed out of `/** … */` block comments,
// modeled on TSDoc's DeclarationReference.grammarkdown. It is organized as a lexical grammar
// (characters, comment framing, tokens, names) building toward a syntactic grammar (the doc comment,
// its block tags, and the CssReference used inside inline `{@link}` / `{@inheritDoc}` tags).
//
// The grammar is the source of truth for the shape of a doc comment; the runtime parser in
// grammar.ts is hand-written to conform to these productions. It is deliberately expansive — modeled
// on TSDoc's full Block / Modifier / Inline taxonomy plus cssdoc's own Record kind — and documents the
// modern CSSOM surface (registered properties, custom functions, keyframes, cascade layers, container
// / supports / media conditions, states, parts, slots). Where a feature is a real CSS at-rule, core
// derives the facts from the CSS AST; the tags below supply the authored prose.
//
// Notation: `::` marks a lexical production, `:` a syntactic one. Terminals are in backticks; `> …`
// lines are prose (used for character classes and layout-sensitive constructs that sit outside
// context-free notation).

// ============================================================================================
// Lexical Grammar
// ============================================================================================

SourceCharacter ::
    > any Unicode code point

WhiteSpace ::
    > a space or a horizontal tab

LineTerminator ::
    > a line feed or a carriage return

// --- Comment framing ---------------------------------------------------------------------------
// PostCSS hands the parser the comment's inner text; the framing is stripped either way.

CommentOpen ::
    `/**`

CommentClose ::
    `*/`

LinePrefix ::
    WhiteSpace? `*` WhiteSpace?

// --- Tokens ------------------------------------------------------------------------------------

BlockSigil ::
    `@`

InlineOpen ::
    `{@`

InlineClose ::
    `}`

// The head/description separator on a tag line: an em dash or a hyphen, surrounded by whitespace.
Separator :: one of
    `—` `-`

Digit :: one of
    `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`

Letter ::
    > an ASCII letter

// --- Names -------------------------------------------------------------------------------------

IdentifierStart ::
    Letter
    `_`

IdentifierPart ::
    IdentifierStart
    Digit
    `-`

Identifier ::
    IdentifierStart
    Identifier IdentifierPart

// A record name, e.g. `button` or `progress-circle`.
RecordName ::
    Identifier

// A `-<prop>` boolean modifier, or a `-<prop>-<value>` modifier. `Prop` is the segment up to the
// first interior hyphen; `Value` is the remainder (which may itself contain hyphens).
ModifierName ::
    `-` Prop
    `-` Prop `-` Value

Prop ::
    > an identifier segment of letters and digits, containing no hyphen

Value ::
    Identifier

// A `.`-prefixed sub-element class, e.g. `.item`.
PartName ::
    `.` Identifier

// A base-class selector, e.g. `.button`.
ClassSelector ::
    `.` Identifier

// A `--`-prefixed custom property (`@property`) or custom function (`@function`) name.
CustomPropertyName ::
    `--` Identifier

// The `<…>` CSS syntax descriptor on a `@cssproperty`/`@property` line, e.g. `<number>`.
SyntaxDescriptor ::
    `<` SyntaxBody `>`

SyntaxBody ::
    > one or more SourceCharacters other than a greater-than sign

// ============================================================================================
// Syntactic Grammar
// ============================================================================================

// A doc comment is a sequence of block tags. Leading untagged prose is ignored; each `@tag` opens a
// block that runs until the next `@tag` (so multi-line @example / @summary bodies are captured).
DocComment :
    CommentOpen TagList CommentClose

TagList :
    [empty]
    TagList BlockTag

BlockTag :
    RecordTag
    ClassTag
    SummaryTag
    RemarksTag
    PrivateRemarksTag
    ModifierTag
    PartTag
    CssPropertyTag
    CssStateTag
    CssFunctionTag
    KeyframesTag
    LayerTag
    ContainerTag
    SupportsTag
    MediaTag
    SlotTag
    AccessibilityTag
    StructureTag
    ExampleTag
    DemoTag
    DeprecatedTag
    SeeTag
    SinceTag
    GroupTag
    DefaultValueTag
    ModifierFlagTag
    CustomTag

// --- Record-opening tags (choose the CssRecordKind; `@name` is an alias for `@component`) --------

RecordTag :
    RecordKeyword WhiteSpace RecordName

RecordKeyword :
    `@component`
    `@name`
    `@utility`
    `@rule`
    `@declaration`

// --- Prose tags (TSDoc-adopted) ----------------------------------------------------------------

ClassTag :
    `@class` WhiteSpace ClassSelector

SummaryTag :
    `@summary` WhiteSpace Description

RemarksTag :
    `@remarks` WhiteSpace Description

PrivateRemarksTag :
    `@privateRemarks` WhiteSpace Description

SeeTag :
    `@see` WhiteSpace Description

SinceTag :
    `@since` WhiteSpace Description

GroupTag :
    GroupKeyword WhiteSpace Description

GroupKeyword :
    `@group`
    `@category`

DefaultValueTag :
    `@defaultValue` WhiteSpace Description

DeprecatedTag :
    `@deprecated`
    `@deprecated` WhiteSpace Description

ExampleTag :
    `@example` ExampleBody

ExampleBody :
    > verbatim example text, which may span multiple lines

// --- CSS-surface tags (existing + Custom Elements Manifest) ------------------------------------

// A `-modifier`; the list itself is AST-derived, this supplies prose (or an inline deprecation).
ModifierTag :
    `@modifier` WhiteSpace ModifierName
    `@modifier` WhiteSpace ModifierName Separator ModifierBody

ModifierBody :
    Description
    InlineDeprecation

// `@deprecated` on a modifier line: free-text guidance and/or a `{@link -canonical}` replacement.
InlineDeprecation :
    `@deprecated`
    `@deprecated` WhiteSpace Description

PartTag :
    PartKeyword WhiteSpace PartName
    PartKeyword WhiteSpace PartName Separator Description

PartKeyword :
    `@part`
    `@csspart`

// A registered custom property. Core reads the `@property` at-rule AST-first; this supplies prose.
CssPropertyTag :
    CssPropertyKeyword WhiteSpace CustomPropertyName
    CssPropertyKeyword WhiteSpace CustomPropertyName SyntaxDescriptor
    CssPropertyKeyword WhiteSpace CustomPropertyName Separator Description
    CssPropertyKeyword WhiteSpace CustomPropertyName SyntaxDescriptor Separator Description

CssPropertyKeyword :
    `@cssproperty`
    `@property`

CssStateTag :
    `@cssstate` WhiteSpace StateName
    `@cssstate` WhiteSpace StateName Separator Description

StateName :
    Identifier

SlotTag :
    `@slot` WhiteSpace SlotName
    `@slot` WhiteSpace SlotName Separator Description

SlotName :
    Identifier

// --- CSSOM at-rule surfaces (AST-derived; prose optional) --------------------------------------

// A CSS custom function (`@function --name`). Core reads the `@function` at-rule AST-first.
CssFunctionTag :
    `@function` WhiteSpace CustomPropertyName
    `@function` WhiteSpace CustomPropertyName Separator Description

// An animation the component exposes (`@keyframes`/`@animation`). AST-derived from `@keyframes`.
KeyframesTag :
    KeyframesKeyword WhiteSpace AnimationName
    KeyframesKeyword WhiteSpace AnimationName Separator Description

KeyframesKeyword :
    `@keyframes`
    `@animation`

AnimationName :
    Identifier

// A cascade layer (`@layer`). AST-derived from `@layer` names.
LayerTag :
    `@layer` WhiteSpace LayerName
    `@layer` WhiteSpace LayerName Separator Description

LayerName ::
    > a cascade-layer name, optionally dotted, e.g. theme.dark

// A container-query surface (`@container`). AST-derived from `@container` / `container-name`.
ContainerTag :
    `@container` WhiteSpace Description

// A feature-query dependency (`@supports`). AST-derived from `@supports` conditions.
SupportsTag :
    `@supports` WhiteSpace Description

// Responsive behavior (`@media`/`@responsive`). AST-derived from `@media` conditions.
MediaTag :
    MediaKeyword WhiteSpace Description

MediaKeyword :
    `@media`
    `@responsive`

// Accessibility guidance.
AccessibilityTag :
    AccessibilityKeyword WhiteSpace Description

AccessibilityKeyword :
    `@a11y`
    `@accessibility`

// --- Structure & demo --------------------------------------------------------------------------

StructureTag :
    `@structure` LineTerminator StructureTree

// Indentation-nested selectors: each deeper indent level is a child of the line above. Layout
// sensitivity (INDENT / DEDENT) sits outside pure context-free notation, so it is given as prose.
StructureTree ::
    > one selector per line; a greater indent than the preceding line makes the node its child

DemoTag :
    `@demo` WhiteSpace DemoSpec

DemoSpec :
    Url
    Provider `:` Ref
    `self` `:` RecordName

Provider ::
    Identifier

Ref ::
    > a provider-specific reference token

Url ::
    > an absolute URL

// --- Modifier (flag) tags: release stage / traits; presence means true ------------------------

ModifierFlagTag :
    `@alpha`
    `@beta`
    `@experimental`
    `@internal`
    `@public`

// --- Custom tags: registered via @cssdoc/config; unregistered tags are ignored ----------------

CustomTag :
    BlockSigil Identifier
    BlockSigil Identifier WhiteSpace CustomTagContent

CustomTagContent ::
    > tag-specific content, interpreted per the tag's configured syntax kind

// ============================================================================================
// Descriptions & inline tags
// ============================================================================================

// Free-text prose that may interleave inline tags. This is where the CssReference — cssdoc's analog
// to TSDoc's DeclarationReference — is used.
Description :
    DescriptionAtom
    Description DescriptionAtom

DescriptionAtom :
    TextRun
    InlineTag

TextRun ::
    > a run of prose containing no inline tag

InlineTag :
    LinkTag
    InheritDocTag
    LabelTag

LinkTag :
    InlineOpen `link` WhiteSpace CssReference InlineClose

InheritDocTag :
    InlineOpen `inheritDoc` WhiteSpace CssReference InlineClose

LabelTag :
    InlineOpen `label` WhiteSpace Identifier InlineClose

// The target of an inline reference: a modifier, a part, or a record — the CSS analog of TSDoc's
// DeclarationReference top-level production.
CssReference :
    ModifierName
    PartName
    RecordName

Released under the MIT License