@cssdoc/spec 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/index.d.mts +50 -0
- package/dist/index.mjs +222 -0
- package/grammar/CssDoc.grammarkdown +437 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Danny Wahl
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @cssdoc/spec
|
|
2
|
+
|
|
3
|
+
The canonical cssdoc tag vocabulary — the single source of truth for the doc-comment tags, shared by
|
|
4
|
+
the parser and every syntax grammar. Zero dependencies, data only.
|
|
5
|
+
|
|
6
|
+
Each tag carries its name, syntactic `kind` (`record` / `block` / `modifier` / `inline`), any
|
|
7
|
+
`aliasFor` target, whether it `allowMultiple`, its `recordKind` (for record tags), and its `argument`
|
|
8
|
+
shape (for the three argument-bearing tags: `@modifier`, `@part`/`@slot`, `@cssproperty`).
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { CSSDOC_TAGS, cssdocTagNamesByKind, cssdocTagNamesByArgument } from "@cssdoc/spec";
|
|
12
|
+
|
|
13
|
+
cssdocTagNamesByKind("inline"); // ["link", "inheritDoc", "label"]
|
|
14
|
+
cssdocTagNamesByArgument("custom-property"); // ["cssproperty", "property"]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Consumers
|
|
18
|
+
|
|
19
|
+
- [`@cssdoc/core`](../core) seeds its parser's tag-definition registry from `CSSDOC_TAGS`.
|
|
20
|
+
- [`@cssdoc/tmlanguage`](../../syntaxes/cssdoc/tmlanguage) generates its TextMate grammar from it.
|
|
21
|
+
- [`@cssdoc/codemirror`](../../syntaxes/cssdoc/codemirror) builds its highlighter's matcher from it.
|
|
22
|
+
|
|
23
|
+
Add or change a tag here, and the parser and both grammars follow.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* `@cssdoc/spec` — the canonical cssdoc tag vocabulary. This is the single source of truth for the
|
|
4
|
+
* doc-comment tags: their names, syntactic kinds, aliases, and (for the three argument-bearing tags)
|
|
5
|
+
* the shape of the argument they take. Everything that needs to know "what are the cssdoc tags"
|
|
6
|
+
* derives it from here:
|
|
7
|
+
*
|
|
8
|
+
* - `@cssdoc/core` seeds its {@link https://cssdoc.dev parser configuration} from {@link CSSDOC_TAGS}.
|
|
9
|
+
* - `@cssdoc/tmlanguage` generates its TextMate grammar from it.
|
|
10
|
+
* - `@cssdoc/codemirror` builds its highlighter's matcher from it.
|
|
11
|
+
*
|
|
12
|
+
* The package is intentionally zero-dependency and data-only, so a syntax grammar can consume the
|
|
13
|
+
* vocabulary without pulling in the CSS parser.
|
|
14
|
+
*
|
|
15
|
+
* @module @cssdoc/spec
|
|
16
|
+
*/
|
|
17
|
+
/** The syntactic kind of a tag, mirroring TSDoc's Block/Modifier/Inline split, plus cssdoc's `record`. */
|
|
18
|
+
type CssdocTagKind = "record" | "block" | "modifier" | "inline";
|
|
19
|
+
/** The record kind a `record` tag opens. */
|
|
20
|
+
type CssdocRecordKind = "component" | "utility" | "rule" | "declaration";
|
|
21
|
+
/** The argument shape a tag accepts, for grammars that highlight it distinctly. */
|
|
22
|
+
type CssdocTagArgument = "modifier-name" | "part-name" | "custom-property";
|
|
23
|
+
/** One tag in the canonical vocabulary. */
|
|
24
|
+
interface CssdocTag {
|
|
25
|
+
/** The tag name, without the leading `@` (e.g. `modifier`). */
|
|
26
|
+
name: string;
|
|
27
|
+
/** The tag's syntactic kind. */
|
|
28
|
+
kind: CssdocTagKind;
|
|
29
|
+
/** The canonical tag (without `@`) this tag is an alias of, e.g. `csspart` aliases `part`. */
|
|
30
|
+
aliasFor?: string;
|
|
31
|
+
/** Whether the tag may appear more than once in a comment. */
|
|
32
|
+
allowMultiple?: boolean;
|
|
33
|
+
/** For `record` tags, the {@link CssdocRecordKind} the tag selects. */
|
|
34
|
+
recordKind?: CssdocRecordKind;
|
|
35
|
+
/** For the argument-bearing tags, the shape of the token that follows the tag. */
|
|
36
|
+
argument?: CssdocTagArgument;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Every standard cssdoc tag, in canonical order. Adopts the Custom Elements Manifest names
|
|
40
|
+
* (`@cssproperty`, `@csspart`, `@cssstate`) where they exist, so the vocabulary is standards-aligned.
|
|
41
|
+
*/
|
|
42
|
+
declare const CSSDOC_TAGS: readonly CssdocTag[];
|
|
43
|
+
/** The names (without `@`) of every standard tag, in canonical order. */
|
|
44
|
+
declare const CSSDOC_TAG_NAMES: readonly string[];
|
|
45
|
+
/** The names of the tags of a given kind, in canonical order. */
|
|
46
|
+
declare const cssdocTagNamesByKind: (kind: CssdocTagKind) => string[];
|
|
47
|
+
/** The names of the tags that take a given argument shape, in canonical order. */
|
|
48
|
+
declare const cssdocTagNamesByArgument: (argument: CssdocTagArgument) => string[];
|
|
49
|
+
//#endregion
|
|
50
|
+
export { CSSDOC_TAGS, CSSDOC_TAG_NAMES, CssdocRecordKind, CssdocTag, CssdocTagArgument, CssdocTagKind, cssdocTagNamesByArgument, cssdocTagNamesByKind };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* Every standard cssdoc tag, in canonical order. Adopts the Custom Elements Manifest names
|
|
4
|
+
* (`@cssproperty`, `@csspart`, `@cssstate`) where they exist, so the vocabulary is standards-aligned.
|
|
5
|
+
*/
|
|
6
|
+
const CSSDOC_TAGS = [
|
|
7
|
+
{
|
|
8
|
+
name: "component",
|
|
9
|
+
kind: "record",
|
|
10
|
+
recordKind: "component"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: "name",
|
|
14
|
+
kind: "record",
|
|
15
|
+
recordKind: "component"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "utility",
|
|
19
|
+
kind: "record",
|
|
20
|
+
recordKind: "utility"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "rule",
|
|
24
|
+
kind: "record",
|
|
25
|
+
recordKind: "rule"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "declaration",
|
|
29
|
+
kind: "record",
|
|
30
|
+
recordKind: "declaration"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "class",
|
|
34
|
+
kind: "block"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "summary",
|
|
38
|
+
kind: "block"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "remarks",
|
|
42
|
+
kind: "block"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "privateRemarks",
|
|
46
|
+
kind: "block"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "deprecated",
|
|
50
|
+
kind: "block"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "example",
|
|
54
|
+
kind: "block",
|
|
55
|
+
allowMultiple: true
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "see",
|
|
59
|
+
kind: "block",
|
|
60
|
+
allowMultiple: true
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "since",
|
|
64
|
+
kind: "block"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "group",
|
|
68
|
+
kind: "block"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "category",
|
|
72
|
+
kind: "block",
|
|
73
|
+
aliasFor: "group"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "defaultValue",
|
|
77
|
+
kind: "block"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "modifier",
|
|
81
|
+
kind: "block",
|
|
82
|
+
allowMultiple: true,
|
|
83
|
+
argument: "modifier-name"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "part",
|
|
87
|
+
kind: "block",
|
|
88
|
+
allowMultiple: true,
|
|
89
|
+
argument: "part-name"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "csspart",
|
|
93
|
+
kind: "block",
|
|
94
|
+
allowMultiple: true,
|
|
95
|
+
argument: "part-name"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "cssproperty",
|
|
99
|
+
kind: "block",
|
|
100
|
+
allowMultiple: true,
|
|
101
|
+
argument: "custom-property"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "property",
|
|
105
|
+
kind: "block",
|
|
106
|
+
allowMultiple: true,
|
|
107
|
+
aliasFor: "cssproperty",
|
|
108
|
+
argument: "custom-property"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "cssstate",
|
|
112
|
+
kind: "block",
|
|
113
|
+
allowMultiple: true
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: "slot",
|
|
117
|
+
kind: "block",
|
|
118
|
+
allowMultiple: true,
|
|
119
|
+
argument: "part-name"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "function",
|
|
123
|
+
kind: "block",
|
|
124
|
+
allowMultiple: true
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "keyframes",
|
|
128
|
+
kind: "block",
|
|
129
|
+
allowMultiple: true
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "animation",
|
|
133
|
+
kind: "block",
|
|
134
|
+
allowMultiple: true,
|
|
135
|
+
aliasFor: "keyframes"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "layer",
|
|
139
|
+
kind: "block",
|
|
140
|
+
allowMultiple: true
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "container",
|
|
144
|
+
kind: "block",
|
|
145
|
+
allowMultiple: true
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "supports",
|
|
149
|
+
kind: "block",
|
|
150
|
+
allowMultiple: true
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "media",
|
|
154
|
+
kind: "block",
|
|
155
|
+
allowMultiple: true
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "responsive",
|
|
159
|
+
kind: "block",
|
|
160
|
+
allowMultiple: true,
|
|
161
|
+
aliasFor: "media"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "a11y",
|
|
165
|
+
kind: "block",
|
|
166
|
+
allowMultiple: true
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "accessibility",
|
|
170
|
+
kind: "block",
|
|
171
|
+
allowMultiple: true,
|
|
172
|
+
aliasFor: "a11y"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "structure",
|
|
176
|
+
kind: "block"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "demo",
|
|
180
|
+
kind: "block"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "alpha",
|
|
184
|
+
kind: "modifier"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "beta",
|
|
188
|
+
kind: "modifier"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "experimental",
|
|
192
|
+
kind: "modifier"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: "internal",
|
|
196
|
+
kind: "modifier"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "public",
|
|
200
|
+
kind: "modifier"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "link",
|
|
204
|
+
kind: "inline"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "inheritDoc",
|
|
208
|
+
kind: "inline"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "label",
|
|
212
|
+
kind: "inline"
|
|
213
|
+
}
|
|
214
|
+
];
|
|
215
|
+
/** The names (without `@`) of every standard tag, in canonical order. */
|
|
216
|
+
const CSSDOC_TAG_NAMES = CSSDOC_TAGS.map((t) => t.name);
|
|
217
|
+
/** The names of the tags of a given kind, in canonical order. */
|
|
218
|
+
const cssdocTagNamesByKind = (kind) => CSSDOC_TAGS.filter((t) => t.kind === kind).map((t) => t.name);
|
|
219
|
+
/** The names of the tags that take a given argument shape, in canonical order. */
|
|
220
|
+
const cssdocTagNamesByArgument = (argument) => CSSDOC_TAGS.filter((t) => t.argument === argument).map((t) => t.name);
|
|
221
|
+
//#endregion
|
|
222
|
+
export { CSSDOC_TAGS, CSSDOC_TAG_NAMES, cssdocTagNamesByArgument, cssdocTagNamesByKind };
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
// CssDoc — the cssdoc doc-comment grammar.
|
|
2
|
+
//
|
|
3
|
+
// Notation: `::` marks a lexical production, `:` a syntactic one. Terminals are in backticks; `> …`
|
|
4
|
+
// lines are prose (character classes and layout-sensitive constructs outside context-free notation).
|
|
5
|
+
// Productions read bottom-up: primitives first, building to the DocComment goal symbol last.
|
|
6
|
+
|
|
7
|
+
// ============================================================================================
|
|
8
|
+
// Lexical Grammar
|
|
9
|
+
// ============================================================================================
|
|
10
|
+
|
|
11
|
+
SourceCharacter ::
|
|
12
|
+
> any Unicode code point
|
|
13
|
+
|
|
14
|
+
WhiteSpace ::
|
|
15
|
+
> a space or a horizontal tab
|
|
16
|
+
|
|
17
|
+
LineTerminator ::
|
|
18
|
+
> a line feed or a carriage return
|
|
19
|
+
|
|
20
|
+
// --- Comment framing ---------------------------------------------------------------------------
|
|
21
|
+
// The comment framing is stripped before the tags are parsed.
|
|
22
|
+
|
|
23
|
+
CommentOpen ::
|
|
24
|
+
`/**`
|
|
25
|
+
|
|
26
|
+
CommentClose ::
|
|
27
|
+
`*/`
|
|
28
|
+
|
|
29
|
+
LinePrefix ::
|
|
30
|
+
WhiteSpace? `*` WhiteSpace?
|
|
31
|
+
|
|
32
|
+
// --- Tokens ------------------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
BlockSigil ::
|
|
35
|
+
`@`
|
|
36
|
+
|
|
37
|
+
InlineOpen ::
|
|
38
|
+
`{@`
|
|
39
|
+
|
|
40
|
+
InlineClose ::
|
|
41
|
+
`}`
|
|
42
|
+
|
|
43
|
+
// The head/description separator on a tag line: an em dash or a hyphen, surrounded by whitespace.
|
|
44
|
+
Separator :: one of
|
|
45
|
+
`—` `-`
|
|
46
|
+
|
|
47
|
+
Digit :: one of
|
|
48
|
+
`0` `1` `2` `3` `4` `5` `6` `7` `8` `9`
|
|
49
|
+
|
|
50
|
+
Letter ::
|
|
51
|
+
> an ASCII letter
|
|
52
|
+
|
|
53
|
+
// --- Names -------------------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
IdentifierStart ::
|
|
56
|
+
Letter
|
|
57
|
+
`_`
|
|
58
|
+
|
|
59
|
+
IdentifierPart ::
|
|
60
|
+
IdentifierStart
|
|
61
|
+
Digit
|
|
62
|
+
`-`
|
|
63
|
+
|
|
64
|
+
Identifier ::
|
|
65
|
+
IdentifierStart
|
|
66
|
+
Identifier IdentifierPart
|
|
67
|
+
|
|
68
|
+
// A record name, e.g. `button` or `progress-circle`.
|
|
69
|
+
RecordName ::
|
|
70
|
+
Identifier
|
|
71
|
+
|
|
72
|
+
// How a modifier is spelled is configurable. Three structural forms are recognized,
|
|
73
|
+
// shown with their default separators and a neutral `.base` component class;
|
|
74
|
+
// every separator and prefix below is configurable:
|
|
75
|
+
// suffix — joined into the base class name: `.base--name` (the default, below)
|
|
76
|
+
// chained — a separate prefixed class on the base: `.base.-name` (optionally split prop/value)
|
|
77
|
+
// attribute — an attribute selector on the base: `.base[name="value"]`
|
|
78
|
+
|
|
79
|
+
// The suffix form (the default): the modifier joined into the base class name with a separator.
|
|
80
|
+
ModifierName ::
|
|
81
|
+
Identifier `--` Identifier
|
|
82
|
+
|
|
83
|
+
// The chained form: a separate prefixed class on the base — a `-<prop>` boolean modifier, or a
|
|
84
|
+
// `-<prop>-<value>` modifier split into prop and value. `Prop` is the segment up to the first interior
|
|
85
|
+
// hyphen; `Value` is the remainder (which may itself contain hyphens).
|
|
86
|
+
ChainedModifierName ::
|
|
87
|
+
`-` Prop
|
|
88
|
+
`-` Prop `-` Value
|
|
89
|
+
|
|
90
|
+
// The attribute form: an attribute selector on the base, e.g. `.base[name="value"]`.
|
|
91
|
+
AttributeModifier ::
|
|
92
|
+
`[` AttributeName `]`
|
|
93
|
+
`[` AttributeName `=` AttributeValue `]`
|
|
94
|
+
|
|
95
|
+
AttributeName ::
|
|
96
|
+
Identifier
|
|
97
|
+
|
|
98
|
+
AttributeValue ::
|
|
99
|
+
QuotedString
|
|
100
|
+
Identifier
|
|
101
|
+
|
|
102
|
+
QuotedString ::
|
|
103
|
+
`"` StringCharacters `"`
|
|
104
|
+
`'` StringCharacters `'`
|
|
105
|
+
|
|
106
|
+
StringCharacters ::
|
|
107
|
+
> one or more SourceCharacters other than the enclosing quote
|
|
108
|
+
|
|
109
|
+
// Two non-modifier roles a convention may name. An element is joined into the base class with `__`,
|
|
110
|
+
// e.g. `.base__part`, and is recorded as a PART. A state class is a class chained to the base whose
|
|
111
|
+
// name starts with a state prefix, e.g. `.base.is-open`, and is recorded as a STATE. Neither is a
|
|
112
|
+
// modifier.
|
|
113
|
+
ElementName ::
|
|
114
|
+
Identifier `__` Identifier
|
|
115
|
+
|
|
116
|
+
StateClass ::
|
|
117
|
+
> a class chained to the base whose name starts with a state prefix
|
|
118
|
+
|
|
119
|
+
Prop ::
|
|
120
|
+
> an identifier segment of letters and digits, containing no hyphen
|
|
121
|
+
|
|
122
|
+
Value ::
|
|
123
|
+
Identifier
|
|
124
|
+
|
|
125
|
+
// A `.`-prefixed sub-element class, e.g. `.part`.
|
|
126
|
+
PartName ::
|
|
127
|
+
`.` Identifier
|
|
128
|
+
|
|
129
|
+
// A base-class selector, e.g. `.base`.
|
|
130
|
+
ClassSelector ::
|
|
131
|
+
`.` Identifier
|
|
132
|
+
|
|
133
|
+
// A `--`-prefixed custom property (`@property`) or custom function (`@function`) name.
|
|
134
|
+
CustomPropertyName ::
|
|
135
|
+
`--` Identifier
|
|
136
|
+
|
|
137
|
+
// The `<…>` CSS syntax descriptor on a `@cssproperty`/`@property` line, e.g. `<number>`.
|
|
138
|
+
SyntaxDescriptor ::
|
|
139
|
+
`<` SyntaxBody `>`
|
|
140
|
+
|
|
141
|
+
// A syntax component name from the CSS Properties and Values API supported-names list.
|
|
142
|
+
SyntaxBody :: one of
|
|
143
|
+
`angle` `color` `custom-ident` `image` `integer` `length` `length-percentage` `number`
|
|
144
|
+
`percentage` `resolution` `string` `time` `transform-function` `transform-list` `url`
|
|
145
|
+
|
|
146
|
+
// ============================================================================================
|
|
147
|
+
// Syntactic Grammar
|
|
148
|
+
// ============================================================================================
|
|
149
|
+
|
|
150
|
+
// --- Descriptions & inline tags ----------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
// The target of an inline reference: a modifier, a part, or a record.
|
|
153
|
+
CssReference :
|
|
154
|
+
ModifierName
|
|
155
|
+
PartName
|
|
156
|
+
RecordName
|
|
157
|
+
|
|
158
|
+
LinkTag :
|
|
159
|
+
InlineOpen `link` WhiteSpace CssReference InlineClose
|
|
160
|
+
|
|
161
|
+
InheritDocTag :
|
|
162
|
+
InlineOpen `inheritDoc` WhiteSpace CssReference InlineClose
|
|
163
|
+
|
|
164
|
+
LabelTag :
|
|
165
|
+
InlineOpen `label` WhiteSpace Identifier InlineClose
|
|
166
|
+
|
|
167
|
+
InlineTag :
|
|
168
|
+
LinkTag
|
|
169
|
+
InheritDocTag
|
|
170
|
+
LabelTag
|
|
171
|
+
|
|
172
|
+
TextRun ::
|
|
173
|
+
> a run of prose containing no inline tag
|
|
174
|
+
|
|
175
|
+
DescriptionAtom :
|
|
176
|
+
TextRun
|
|
177
|
+
InlineTag
|
|
178
|
+
|
|
179
|
+
// Free-text prose that may interleave inline tags.
|
|
180
|
+
Description :
|
|
181
|
+
DescriptionAtom
|
|
182
|
+
Description DescriptionAtom
|
|
183
|
+
|
|
184
|
+
// --- Record-opening tags (choose the CssRecordKind; `@name` is an alias for `@component`) --------
|
|
185
|
+
|
|
186
|
+
RecordKeyword :
|
|
187
|
+
`@component`
|
|
188
|
+
`@name`
|
|
189
|
+
`@utility`
|
|
190
|
+
`@rule`
|
|
191
|
+
`@declaration`
|
|
192
|
+
|
|
193
|
+
RecordTag :
|
|
194
|
+
RecordKeyword WhiteSpace RecordName
|
|
195
|
+
|
|
196
|
+
// --- Prose tags --------------------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
ClassTag :
|
|
199
|
+
`@class` WhiteSpace ClassSelector
|
|
200
|
+
|
|
201
|
+
SummaryTag :
|
|
202
|
+
`@summary` WhiteSpace Description
|
|
203
|
+
|
|
204
|
+
RemarksTag :
|
|
205
|
+
`@remarks` WhiteSpace Description
|
|
206
|
+
|
|
207
|
+
PrivateRemarksTag :
|
|
208
|
+
`@privateRemarks` WhiteSpace Description
|
|
209
|
+
|
|
210
|
+
SeeTag :
|
|
211
|
+
`@see` WhiteSpace Description
|
|
212
|
+
|
|
213
|
+
SinceTag :
|
|
214
|
+
`@since` WhiteSpace Description
|
|
215
|
+
|
|
216
|
+
GroupKeyword :
|
|
217
|
+
`@group`
|
|
218
|
+
`@category`
|
|
219
|
+
|
|
220
|
+
GroupTag :
|
|
221
|
+
GroupKeyword WhiteSpace Description
|
|
222
|
+
|
|
223
|
+
DefaultValueTag :
|
|
224
|
+
`@defaultValue` WhiteSpace Description
|
|
225
|
+
|
|
226
|
+
DeprecatedTag :
|
|
227
|
+
`@deprecated`
|
|
228
|
+
`@deprecated` WhiteSpace Description
|
|
229
|
+
|
|
230
|
+
ExampleBody :
|
|
231
|
+
> verbatim example text, which may span multiple lines
|
|
232
|
+
|
|
233
|
+
ExampleTag :
|
|
234
|
+
`@example` ExampleBody
|
|
235
|
+
|
|
236
|
+
// --- CSS-surface tags (existing + Custom Elements Manifest) ------------------------------------
|
|
237
|
+
|
|
238
|
+
// `@deprecated` on a modifier line: free-text guidance and/or a `{@link -canonical}` replacement.
|
|
239
|
+
InlineDeprecation :
|
|
240
|
+
`@deprecated`
|
|
241
|
+
`@deprecated` WhiteSpace Description
|
|
242
|
+
|
|
243
|
+
ModifierBody :
|
|
244
|
+
Description
|
|
245
|
+
InlineDeprecation
|
|
246
|
+
|
|
247
|
+
// A modifier; the list itself is derived from the CSS, this supplies prose (or an inline deprecation).
|
|
248
|
+
ModifierTag :
|
|
249
|
+
`@modifier` WhiteSpace ModifierName
|
|
250
|
+
`@modifier` WhiteSpace ModifierName Separator ModifierBody
|
|
251
|
+
|
|
252
|
+
// A class-based sub-element, e.g. `@part .list`.
|
|
253
|
+
PartTag :
|
|
254
|
+
`@part` WhiteSpace PartName
|
|
255
|
+
`@part` WhiteSpace PartName Separator Description
|
|
256
|
+
|
|
257
|
+
// A shadow-DOM exposed part (`::part(name)`), named by a bare identifier, e.g. `@csspart header`.
|
|
258
|
+
ShadowPartName :
|
|
259
|
+
Identifier
|
|
260
|
+
|
|
261
|
+
CssPartTag :
|
|
262
|
+
`@csspart` WhiteSpace ShadowPartName
|
|
263
|
+
`@csspart` WhiteSpace ShadowPartName Separator Description
|
|
264
|
+
|
|
265
|
+
CssPropertyKeyword :
|
|
266
|
+
`@cssproperty`
|
|
267
|
+
`@property`
|
|
268
|
+
|
|
269
|
+
// A registered custom property; the registration is derived from the `@property` at-rule, this adds prose.
|
|
270
|
+
CssPropertyTag :
|
|
271
|
+
CssPropertyKeyword WhiteSpace CustomPropertyName
|
|
272
|
+
CssPropertyKeyword WhiteSpace CustomPropertyName SyntaxDescriptor
|
|
273
|
+
CssPropertyKeyword WhiteSpace CustomPropertyName Separator Description
|
|
274
|
+
CssPropertyKeyword WhiteSpace CustomPropertyName SyntaxDescriptor Separator Description
|
|
275
|
+
|
|
276
|
+
// A state name: a bare identifier (a custom `:state(name)` state) or a `:`-prefixed native
|
|
277
|
+
// pseudo-class state, e.g. `:disabled`.
|
|
278
|
+
StateName :
|
|
279
|
+
Identifier
|
|
280
|
+
`:` Identifier
|
|
281
|
+
|
|
282
|
+
CssStateTag :
|
|
283
|
+
`@cssstate` WhiteSpace StateName
|
|
284
|
+
`@cssstate` WhiteSpace StateName Separator Description
|
|
285
|
+
|
|
286
|
+
SlotName :
|
|
287
|
+
Identifier
|
|
288
|
+
|
|
289
|
+
SlotTag :
|
|
290
|
+
`@slot` WhiteSpace SlotName
|
|
291
|
+
`@slot` WhiteSpace SlotName Separator Description
|
|
292
|
+
|
|
293
|
+
// --- CSSOM at-rule surfaces (derived from the CSS; prose optional) -----------------------------
|
|
294
|
+
|
|
295
|
+
// A CSS custom function (`@function --name`), derived from the `@function` at-rule.
|
|
296
|
+
CssFunctionTag :
|
|
297
|
+
`@function` WhiteSpace CustomPropertyName
|
|
298
|
+
`@function` WhiteSpace CustomPropertyName Separator Description
|
|
299
|
+
|
|
300
|
+
AnimationName :
|
|
301
|
+
Identifier
|
|
302
|
+
|
|
303
|
+
KeyframesKeyword :
|
|
304
|
+
`@keyframes`
|
|
305
|
+
`@animation`
|
|
306
|
+
|
|
307
|
+
// An animation the component exposes (`@keyframes`/`@animation`), derived from the `@keyframes` at-rule.
|
|
308
|
+
KeyframesTag :
|
|
309
|
+
KeyframesKeyword WhiteSpace AnimationName
|
|
310
|
+
KeyframesKeyword WhiteSpace AnimationName Separator Description
|
|
311
|
+
|
|
312
|
+
LayerName ::
|
|
313
|
+
> a cascade-layer name, optionally dotted, e.g. theme.dark
|
|
314
|
+
|
|
315
|
+
// A cascade layer (`@layer`), derived from `@layer` names.
|
|
316
|
+
LayerTag :
|
|
317
|
+
`@layer` WhiteSpace LayerName
|
|
318
|
+
`@layer` WhiteSpace LayerName Separator Description
|
|
319
|
+
|
|
320
|
+
// A container-query surface (`@container`), derived from `@container` / `container-name`.
|
|
321
|
+
ContainerTag :
|
|
322
|
+
`@container` WhiteSpace Description
|
|
323
|
+
|
|
324
|
+
// A feature-query dependency (`@supports`), derived from `@supports` conditions.
|
|
325
|
+
SupportsTag :
|
|
326
|
+
`@supports` WhiteSpace Description
|
|
327
|
+
|
|
328
|
+
MediaKeyword :
|
|
329
|
+
`@media`
|
|
330
|
+
`@responsive`
|
|
331
|
+
|
|
332
|
+
// Responsive behavior (`@media`/`@responsive`), derived from `@media` conditions.
|
|
333
|
+
MediaTag :
|
|
334
|
+
MediaKeyword WhiteSpace Description
|
|
335
|
+
|
|
336
|
+
AccessibilityKeyword :
|
|
337
|
+
`@a11y`
|
|
338
|
+
`@accessibility`
|
|
339
|
+
|
|
340
|
+
// Accessibility guidance.
|
|
341
|
+
AccessibilityTag :
|
|
342
|
+
AccessibilityKeyword WhiteSpace Description
|
|
343
|
+
|
|
344
|
+
// --- Structure & demo --------------------------------------------------------------------------
|
|
345
|
+
|
|
346
|
+
// Nested CSS: each rule's selector is a node, and the rules nested inside it are its children. A
|
|
347
|
+
// node's selector is a full compound/complex selector, so `:has()` (contains), `:is()` or a selector
|
|
348
|
+
// list (one-of), and `:not()` (not) express relationships between the related parts.
|
|
349
|
+
Selector ::
|
|
350
|
+
> a CSS compound or complex selector
|
|
351
|
+
|
|
352
|
+
StructureNode :
|
|
353
|
+
Selector `{` StructureNodeList? `}`
|
|
354
|
+
|
|
355
|
+
StructureNodeList :
|
|
356
|
+
StructureNode
|
|
357
|
+
StructureNodeList StructureNode
|
|
358
|
+
|
|
359
|
+
StructureTag :
|
|
360
|
+
`@structure` StructureNodeList
|
|
361
|
+
`@structure` Description StructureNodeList
|
|
362
|
+
|
|
363
|
+
Provider ::
|
|
364
|
+
Identifier
|
|
365
|
+
|
|
366
|
+
Ref ::
|
|
367
|
+
> a provider-specific reference token
|
|
368
|
+
|
|
369
|
+
Url ::
|
|
370
|
+
> an absolute URL
|
|
371
|
+
|
|
372
|
+
DemoSpec :
|
|
373
|
+
Url
|
|
374
|
+
Provider `:` Ref
|
|
375
|
+
`self` `:` RecordName
|
|
376
|
+
|
|
377
|
+
DemoTag :
|
|
378
|
+
`@demo` WhiteSpace DemoSpec
|
|
379
|
+
|
|
380
|
+
// --- Modifier (flag) tags: release stage / traits; presence means true ------------------------
|
|
381
|
+
|
|
382
|
+
ModifierFlagTag :
|
|
383
|
+
`@alpha`
|
|
384
|
+
`@beta`
|
|
385
|
+
`@experimental`
|
|
386
|
+
`@internal`
|
|
387
|
+
`@public`
|
|
388
|
+
|
|
389
|
+
// --- Custom tags: registered by the host tooling; unregistered tags are ignored ---------------
|
|
390
|
+
|
|
391
|
+
CustomTagContent ::
|
|
392
|
+
> tag-specific content, interpreted per the tag's configured syntax kind
|
|
393
|
+
|
|
394
|
+
CustomTag :
|
|
395
|
+
BlockSigil Identifier
|
|
396
|
+
BlockSigil Identifier WhiteSpace CustomTagContent
|
|
397
|
+
|
|
398
|
+
// --- The doc comment ---------------------------------------------------------------------------
|
|
399
|
+
|
|
400
|
+
BlockTag :
|
|
401
|
+
RecordTag
|
|
402
|
+
ClassTag
|
|
403
|
+
SummaryTag
|
|
404
|
+
RemarksTag
|
|
405
|
+
PrivateRemarksTag
|
|
406
|
+
ModifierTag
|
|
407
|
+
PartTag
|
|
408
|
+
CssPartTag
|
|
409
|
+
CssPropertyTag
|
|
410
|
+
CssStateTag
|
|
411
|
+
CssFunctionTag
|
|
412
|
+
KeyframesTag
|
|
413
|
+
LayerTag
|
|
414
|
+
ContainerTag
|
|
415
|
+
SupportsTag
|
|
416
|
+
MediaTag
|
|
417
|
+
SlotTag
|
|
418
|
+
AccessibilityTag
|
|
419
|
+
StructureTag
|
|
420
|
+
ExampleTag
|
|
421
|
+
DemoTag
|
|
422
|
+
DeprecatedTag
|
|
423
|
+
SeeTag
|
|
424
|
+
SinceTag
|
|
425
|
+
GroupTag
|
|
426
|
+
DefaultValueTag
|
|
427
|
+
ModifierFlagTag
|
|
428
|
+
CustomTag
|
|
429
|
+
|
|
430
|
+
TagList :
|
|
431
|
+
[empty]
|
|
432
|
+
TagList BlockTag
|
|
433
|
+
|
|
434
|
+
// A doc comment is a sequence of block tags. Leading untagged prose is ignored; each `@tag` opens a
|
|
435
|
+
// block that runs until the next `@tag` (so multi-line @example / @summary bodies are captured).
|
|
436
|
+
DocComment :
|
|
437
|
+
CommentOpen TagList CommentClose
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cssdoc/spec",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The canonical cssdoc spec: the tag vocabulary and the formal grammar (CssDoc.grammarkdown), the single source of truth shared by the parser and every syntax grammar. Zero runtime dependencies.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cssdoc",
|
|
7
|
+
"doc-comments",
|
|
8
|
+
"grammar",
|
|
9
|
+
"spec",
|
|
10
|
+
"tags",
|
|
11
|
+
"vocabulary"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://cssdoc.dev",
|
|
14
|
+
"bugs": "https://github.com/thedannywahl/cssdoc/issues",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/thedannywahl/cssdoc.git",
|
|
19
|
+
"directory": "packages/spec"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"grammar"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./dist/index.mjs",
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^24.13.3",
|
|
35
|
+
"@vitest/coverage-v8": "4.1.9",
|
|
36
|
+
"grammarkdown": "^3.3.2",
|
|
37
|
+
"publint": "^0.3.21",
|
|
38
|
+
"typescript": "^6.0.3",
|
|
39
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.4",
|
|
40
|
+
"vite-plus": "0.2.4"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "vp pack",
|
|
44
|
+
"dev": "vp pack --watch",
|
|
45
|
+
"test": "vp test",
|
|
46
|
+
"check": "vp check",
|
|
47
|
+
"publint": "publint"
|
|
48
|
+
}
|
|
49
|
+
}
|