@cssdoc/core 0.5.3 → 0.6.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/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as CssSource, B as ModifierHit, C as CssParse, D as CssRelated, E as CssRecordKind, F as DEFAULT_MODIFIER_CONVENTION, H as resolveModifierConvention, I as DEFAULT_STATE_PSEUDO_CLASSES, L as MODIFIER_PRESETS, M as CssTokenConsumed, N as ParseOptions, O as CssReleaseStage, P as StructureNode, R as ModifierConvention, S as CssModifier, T as CssPropertyDeclared, V as ModifierMatcher, _ as CssAnimation, a as DocModifier, b as CssFunction, c as parseDocComment, d as stripCommentFraming, f as CssDocConfiguration, g as InlineCommentMode, h as CssDocTagDefinitionOptions, i as DocCssProperty, j as CssState, k as CssSlot, l as parseStructure, m as CssDocTagDefinition, n as toMermaid, o as ParsedDoc, p as CssDocSyntaxKind, r as DocCondition, s as RECORD_TAGS, t as toJson, u as recordNameOf, v as CssCondition, w as CssPart, x as CssLayer, y as CssDocEntry, z as ModifierConventionInput } from "./lite-DzhifijA.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/parse.d.ts
|
|
4
4
|
/**
|
|
@@ -20,4 +20,4 @@ import { A as CssState, B as ModifierMatcher, C as CssPart, D as CssReleaseStage
|
|
|
20
20
|
*/
|
|
21
21
|
declare function parseCssDocs(css: string, options?: ParseOptions): CssDocEntry[];
|
|
22
22
|
//#endregion
|
|
23
|
-
export { type CssAnimation, type CssCondition, CssDocConfiguration, type CssDocEntry, type CssDocSyntaxKind, CssDocTagDefinition, type CssDocTagDefinitionOptions, type CssFunction, type CssLayer, type CssModifier, type CssParse, type CssPart, type CssPropertyDeclared, type CssRecordKind, type CssRelated, type CssReleaseStage, type CssSlot, type CssSource, type CssState, type CssTokenConsumed, DEFAULT_MODIFIER_CONVENTION, DEFAULT_STATE_PSEUDO_CLASSES, type DocCondition, type DocCssProperty, type DocModifier, MODIFIER_PRESETS, type ModifierConvention, type ModifierConventionInput, type ModifierHit, ModifierMatcher, type ParseOptions, type ParsedDoc, RECORD_TAGS, type StructureNode, parseCssDocs, parseDocComment, parseStructure, recordNameOf, resolveModifierConvention, stripCommentFraming, toJson, toMermaid };
|
|
23
|
+
export { type CssAnimation, type CssCondition, CssDocConfiguration, type CssDocEntry, type CssDocSyntaxKind, CssDocTagDefinition, type CssDocTagDefinitionOptions, type CssFunction, type CssLayer, type CssModifier, type CssParse, type CssPart, type CssPropertyDeclared, type CssRecordKind, type CssRelated, type CssReleaseStage, type CssSlot, type CssSource, type CssState, type CssTokenConsumed, DEFAULT_MODIFIER_CONVENTION, DEFAULT_STATE_PSEUDO_CLASSES, type DocCondition, type DocCssProperty, type DocModifier, type InlineCommentMode, MODIFIER_PRESETS, type ModifierConvention, type ModifierConventionInput, type ModifierHit, ModifierMatcher, type ParseOptions, type ParsedDoc, RECORD_TAGS, type StructureNode, parseCssDocs, parseDocComment, parseStructure, recordNameOf, resolveModifierConvention, stripCommentFraming, toJson, toMermaid };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as parseStructure, c as CssDocConfiguration, d as DEFAULT_STATE_PSEUDO_CLASSES, f as MODIFIER_PRESETS, i as parseDocComment, l as CssDocTagDefinition, m as resolveModifierConvention, n as toMermaid, o as recordNameOf, p as ModifierMatcher, r as RECORD_TAGS, s as stripCommentFraming, t as toJson, u as DEFAULT_MODIFIER_CONVENTION } from "./lite-
|
|
1
|
+
import { a as parseStructure, c as CssDocConfiguration, d as DEFAULT_STATE_PSEUDO_CLASSES, f as MODIFIER_PRESETS, i as parseDocComment, l as CssDocTagDefinition, m as resolveModifierConvention, n as toMermaid, o as recordNameOf, p as ModifierMatcher, r as RECORD_TAGS, s as stripCommentFraming, t as toJson, u as DEFAULT_MODIFIER_CONVENTION } from "./lite-CEVmwLGF.mjs";
|
|
2
2
|
import postcss from "postcss";
|
|
3
3
|
//#region src/parse.ts
|
|
4
4
|
/**
|
|
@@ -38,12 +38,20 @@ function collectFunction(node, acc) {
|
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
/** Extract every fact from one record's nodes into `acc`. */
|
|
41
|
-
function collect(nodes, acc, matcher, baseNoDot, prefixNoDot, inScope) {
|
|
41
|
+
function collect(nodes, acc, matcher, baseNoDot, prefixNoDot, inScope, inlineMode) {
|
|
42
42
|
let pendingCanonical;
|
|
43
|
+
let pendingDescription;
|
|
43
44
|
for (const node of nodes) {
|
|
44
45
|
if (node.type === "comment") {
|
|
45
46
|
const dep = node.text.match(/@deprecated.*?use\s+(\.[\w-]+|\[[^\]]*\])/u);
|
|
46
47
|
if (dep) pendingCanonical = matcher.normalizeMember(dep[1]);
|
|
48
|
+
else if (/(^|\s)@todo\b/u.test(node.text)) {
|
|
49
|
+
const todo = stripCommentFraming(node.text).replace(/^@todo\b[:\s]*/u, "").trim();
|
|
50
|
+
if (todo) acc.todos.push(todo);
|
|
51
|
+
} else if (!/^\s*cssdoc-/u.test(node.text) && inlineMode !== "ignore") {
|
|
52
|
+
const text = stripCommentFraming(node.text).replace(/\s+/gu, " ").trim();
|
|
53
|
+
if (text) pendingDescription = text;
|
|
54
|
+
}
|
|
47
55
|
continue;
|
|
48
56
|
}
|
|
49
57
|
if (node.type === "decl") {
|
|
@@ -98,7 +106,7 @@ function collect(nodes, acc, matcher, baseNoDot, prefixNoDot, inScope) {
|
|
|
98
106
|
type: "media",
|
|
99
107
|
query: node.params.trim()
|
|
100
108
|
});
|
|
101
|
-
if (node.nodes) collect(node.nodes, acc, matcher, baseNoDot, prefixNoDot, inScope || node.name === "scope");
|
|
109
|
+
if (node.nodes) collect(node.nodes, acc, matcher, baseNoDot, prefixNoDot, inScope || node.name === "scope", inlineMode);
|
|
102
110
|
continue;
|
|
103
111
|
}
|
|
104
112
|
if (node.type === "rule") {
|
|
@@ -112,6 +120,10 @@ function collect(nodes, acc, matcher, baseNoDot, prefixNoDot, inScope) {
|
|
|
112
120
|
kind: "pseudo-class"
|
|
113
121
|
});
|
|
114
122
|
for (const sp of selector.matchAll(/::part\(\s*([\w-]+)\s*\)/gu)) if (!acc.shadowParts.has(sp[1])) acc.shadowParts.set(sp[1], { name: sp[1] });
|
|
123
|
+
for (const pe of matcher.pseudoElementsIn(selector)) if (!acc.pseudoElements.has(pe.name)) acc.pseudoElements.set(pe.name, {
|
|
124
|
+
name: pe.name,
|
|
125
|
+
description: pendingDescription
|
|
126
|
+
});
|
|
115
127
|
const bare = selector.replace(/::?[\w-]+(\([^)]*\))?/gu, "");
|
|
116
128
|
const mods = matcher.modifiersIn(bare, baseNoDot);
|
|
117
129
|
const modNames = new Set(mods.map((mod) => mod.name));
|
|
@@ -123,10 +135,12 @@ function collect(nodes, acc, matcher, baseNoDot, prefixNoDot, inScope) {
|
|
|
123
135
|
...mod.pattern ? { pattern: true } : {}
|
|
124
136
|
};
|
|
125
137
|
if (pendingCanonical) entry.deprecated = { canonical: pendingCanonical };
|
|
138
|
+
if (pendingDescription && !entry.description) entry.description = pendingDescription;
|
|
126
139
|
acc.modifiers.set(mod.name, entry);
|
|
127
140
|
}
|
|
128
141
|
for (const el of matcher.elementsIn(bare, baseNoDot)) {
|
|
129
142
|
const part = acc.parts.get(el.name) ?? { name: el.name };
|
|
143
|
+
if (pendingDescription && !part.description) part.description = pendingDescription;
|
|
130
144
|
for (const m of el.modifiers) {
|
|
131
145
|
part.modifiers ??= [];
|
|
132
146
|
if (!part.modifiers.some((x) => x.name === m.name)) part.modifiers.push({
|
|
@@ -145,17 +159,33 @@ function collect(nodes, acc, matcher, baseNoDot, prefixNoDot, inScope) {
|
|
|
145
159
|
const part = m[1];
|
|
146
160
|
if (modNames.has(part)) continue;
|
|
147
161
|
if (prefixNoDot && part.startsWith(prefixNoDot)) continue;
|
|
148
|
-
if (!acc.parts.has(part)) acc.parts.set(part, {
|
|
162
|
+
if (!acc.parts.has(part)) acc.parts.set(part, {
|
|
163
|
+
name: part,
|
|
164
|
+
description: pendingDescription
|
|
165
|
+
});
|
|
149
166
|
}
|
|
150
167
|
}
|
|
151
168
|
for (const child of node.nodes ?? []) if (child.type === "decl") for (const m of child.value.matchAll(VAR_RE)) acc.consumed.add(m[1]);
|
|
152
169
|
pendingCanonical = void 0;
|
|
170
|
+
pendingDescription = void 0;
|
|
153
171
|
}
|
|
154
172
|
}
|
|
155
173
|
}
|
|
156
174
|
const byName = (a, b) => a.name.localeCompare(b.name);
|
|
175
|
+
/**
|
|
176
|
+
* Combine a member's authored tag prose with an inline `/* … *\/` comment, per the configured
|
|
177
|
+
* {@link InlineCommentMode}. Either side may be absent; when both are present, `append`/`prepend` join
|
|
178
|
+
* them (tag-first / comment-first), `replace` takes the comment, and `ignore` keeps only the tag.
|
|
179
|
+
*/
|
|
180
|
+
function combineDescription(mode, tag, inline) {
|
|
181
|
+
if (mode === "ignore") return tag;
|
|
182
|
+
if (!tag) return inline;
|
|
183
|
+
if (!inline) return tag;
|
|
184
|
+
if (mode === "replace") return inline;
|
|
185
|
+
return mode === "prepend" ? `${inline}\n\n${tag}` : `${tag}\n\n${inline}`;
|
|
186
|
+
}
|
|
157
187
|
/** Build one entry from its record name, doc comment, and nodes. */
|
|
158
|
-
function buildEntry(name, doc, nodes, matcher, source) {
|
|
188
|
+
function buildEntry(name, doc, nodes, matcher, inlineMode, source) {
|
|
159
189
|
let className = doc.className ?? "";
|
|
160
190
|
if (!className) {
|
|
161
191
|
const bare = nodes.filter((n) => n.type === "rule").map((n) => n.selector.trim()).filter((sel) => /^\.[a-z][\w-]*$/u.test(sel));
|
|
@@ -169,15 +199,17 @@ function buildEntry(name, doc, nodes, matcher, source) {
|
|
|
169
199
|
modifiers: /* @__PURE__ */ new Map(),
|
|
170
200
|
parts: /* @__PURE__ */ new Map(),
|
|
171
201
|
shadowParts: /* @__PURE__ */ new Map(),
|
|
202
|
+
pseudoElements: /* @__PURE__ */ new Map(),
|
|
172
203
|
states: /* @__PURE__ */ new Map(),
|
|
173
204
|
consumed: /* @__PURE__ */ new Set(),
|
|
174
205
|
declared: /* @__PURE__ */ new Map(),
|
|
175
206
|
functions: /* @__PURE__ */ new Map(),
|
|
176
207
|
animations: /* @__PURE__ */ new Map(),
|
|
177
208
|
layers: /* @__PURE__ */ new Map(),
|
|
178
|
-
conditions: []
|
|
209
|
+
conditions: [],
|
|
210
|
+
todos: []
|
|
179
211
|
};
|
|
180
|
-
collect(nodes, acc, matcher, className.replace(/^\./u, ""), className.endsWith(name) ? className.slice(1, className.length - name.length) : "", false);
|
|
212
|
+
collect(nodes, acc, matcher, className.replace(/^\./u, ""), className.endsWith(name) ? className.slice(1, className.length - name.length) : "", false, inlineMode);
|
|
181
213
|
for (const [modName, mdoc] of doc.modifiers) {
|
|
182
214
|
const existing = acc.modifiers.get(modName);
|
|
183
215
|
const dep = mdoc.deprecated || mdoc.deprecatedCanonical || mdoc.deprecatedFlag ? {
|
|
@@ -185,7 +217,7 @@ function buildEntry(name, doc, nodes, matcher, source) {
|
|
|
185
217
|
...mdoc.deprecatedCanonical ? { canonical: mdoc.deprecatedCanonical } : {}
|
|
186
218
|
} : void 0;
|
|
187
219
|
if (existing) {
|
|
188
|
-
|
|
220
|
+
existing.description = combineDescription(inlineMode, mdoc.description, existing.description);
|
|
189
221
|
if (dep) existing.deprecated = {
|
|
190
222
|
...existing.deprecated,
|
|
191
223
|
...dep
|
|
@@ -204,7 +236,7 @@ function buildEntry(name, doc, nodes, matcher, source) {
|
|
|
204
236
|
}
|
|
205
237
|
for (const [part, description] of doc.parts) {
|
|
206
238
|
const existing = acc.parts.get(part);
|
|
207
|
-
if (existing) existing.description = description || existing.description;
|
|
239
|
+
if (existing) existing.description = combineDescription(inlineMode, description || void 0, existing.description);
|
|
208
240
|
else acc.parts.set(part, {
|
|
209
241
|
name: part,
|
|
210
242
|
description
|
|
@@ -218,6 +250,14 @@ function buildEntry(name, doc, nodes, matcher, source) {
|
|
|
218
250
|
description: description || void 0
|
|
219
251
|
});
|
|
220
252
|
}
|
|
253
|
+
for (const [pseudo, description] of doc.pseudoElements) {
|
|
254
|
+
const existing = acc.pseudoElements.get(pseudo);
|
|
255
|
+
if (existing) existing.description = combineDescription(inlineMode, description || void 0, existing.description);
|
|
256
|
+
else acc.pseudoElements.set(pseudo, {
|
|
257
|
+
name: pseudo,
|
|
258
|
+
description: description || void 0
|
|
259
|
+
});
|
|
260
|
+
}
|
|
221
261
|
for (const [rawState, description] of doc.cssStates) {
|
|
222
262
|
const isPseudo = rawState.startsWith(":");
|
|
223
263
|
const state = isPseudo ? rawState.slice(1) : rawState;
|
|
@@ -284,6 +324,17 @@ function buildEntry(name, doc, nodes, matcher, source) {
|
|
|
284
324
|
description: description || void 0
|
|
285
325
|
});
|
|
286
326
|
}
|
|
327
|
+
if (doc.wrappers.size && doc.structure?.length) {
|
|
328
|
+
const applyWrappers = (nodes) => {
|
|
329
|
+
for (const node of nodes) {
|
|
330
|
+
const cls = node.selector.match(/\.([\w-]+)/u)?.[1];
|
|
331
|
+
const description = cls ? doc.wrappers.get(cls) : void 0;
|
|
332
|
+
if (description) node.description = description;
|
|
333
|
+
applyWrappers(node.children);
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
applyWrappers(doc.structure);
|
|
337
|
+
}
|
|
287
338
|
return {
|
|
288
339
|
name,
|
|
289
340
|
kind: doc.kind ?? "component",
|
|
@@ -301,11 +352,13 @@ function buildEntry(name, doc, nodes, matcher, source) {
|
|
|
301
352
|
modifiers: [...p.modifiers].sort(byName)
|
|
302
353
|
} : p),
|
|
303
354
|
shadowParts: [...acc.shadowParts.values()].sort(byName),
|
|
355
|
+
pseudoElements: [...acc.pseudoElements.values()].sort(byName),
|
|
304
356
|
states: [...acc.states.values()].sort(byName),
|
|
305
357
|
slots: [...doc.slots].map(([slotName, description]) => ({
|
|
306
358
|
name: slotName,
|
|
307
359
|
description: description || void 0
|
|
308
360
|
})).sort(byName),
|
|
361
|
+
todos: [...doc.todos, ...acc.todos],
|
|
309
362
|
cssPropertiesConsumed: [...consumedTokens.values()].sort(byName),
|
|
310
363
|
cssPropertiesDeclared: [...acc.declared.values()].sort(byName),
|
|
311
364
|
functions: [...acc.functions.values()].sort(byName),
|
|
@@ -383,7 +436,7 @@ function parseCssDocs(css, options = {}) {
|
|
|
383
436
|
}
|
|
384
437
|
if (current) current.nodes.push(node);
|
|
385
438
|
}
|
|
386
|
-
return records.map((r) => buildEntry(r.name, r.doc, r.nodes, matcher, r.source));
|
|
439
|
+
return records.map((r) => buildEntry(r.name, r.doc, r.nodes, matcher, configuration.inlineComments, r.source));
|
|
387
440
|
}
|
|
388
441
|
//#endregion
|
|
389
442
|
export { CssDocConfiguration, CssDocTagDefinition, DEFAULT_MODIFIER_CONVENTION, DEFAULT_STATE_PSEUDO_CLASSES, MODIFIER_PRESETS, ModifierMatcher, RECORD_TAGS, parseCssDocs, parseDocComment, parseStructure, recordNameOf, resolveModifierConvention, stripCommentFraming, toJson, toMermaid };
|
|
@@ -22,6 +22,23 @@ const DEFAULT_STATE_PSEUDO_CLASSES = [
|
|
|
22
22
|
"in-range",
|
|
23
23
|
"out-of-range"
|
|
24
24
|
];
|
|
25
|
+
/**
|
|
26
|
+
* The native pseudo-elements cssdoc documents by default when a component styles them. A curated set of
|
|
27
|
+
* the standard ones — vendor/experimental pseudo-elements (`::-webkit-*`) are left out so incidental
|
|
28
|
+
* rules don't become documented API. `::part()`/`::slotted()` are handled separately (shadow parts).
|
|
29
|
+
*/
|
|
30
|
+
const DEFAULT_PSEUDO_ELEMENTS = [
|
|
31
|
+
"before",
|
|
32
|
+
"after",
|
|
33
|
+
"marker",
|
|
34
|
+
"placeholder",
|
|
35
|
+
"selection",
|
|
36
|
+
"backdrop",
|
|
37
|
+
"first-line",
|
|
38
|
+
"first-letter",
|
|
39
|
+
"file-selector-button",
|
|
40
|
+
"details-content"
|
|
41
|
+
];
|
|
25
42
|
/** The built-in convention presets. Other schemes use the custom object (see the docs). */
|
|
26
43
|
const MODIFIER_PRESETS = {
|
|
27
44
|
/** BEM / SUIT — `.button--primary`, with `.button__element` sub-elements. The default. */
|
|
@@ -65,6 +82,7 @@ function resolveModifierConvention(input) {
|
|
|
65
82
|
...base.elementSeparator !== void 0 ? { elementSeparator: base.elementSeparator } : {},
|
|
66
83
|
...base.statePrefixes !== void 0 ? { statePrefixes: base.statePrefixes } : {},
|
|
67
84
|
statePseudoClasses: base.statePseudoClasses ?? [...DEFAULT_STATE_PSEUDO_CLASSES],
|
|
85
|
+
pseudoElements: base.pseudoElements ?? [...DEFAULT_PSEUDO_ELEMENTS],
|
|
68
86
|
propValue: base.propValue ?? false,
|
|
69
87
|
propValueSeparator: base.propValueSeparator ?? "-"
|
|
70
88
|
};
|
|
@@ -92,6 +110,8 @@ var ModifierMatcher = class {
|
|
|
92
110
|
statePrefixes;
|
|
93
111
|
/** Native pseudo-classes (no `:`) recognized as states. */
|
|
94
112
|
statePseudoClasses;
|
|
113
|
+
/** Native pseudo-elements (no `::`) recognized as documented pseudo-elements. */
|
|
114
|
+
pseudoElements;
|
|
95
115
|
constructor(convention) {
|
|
96
116
|
this.convention = convention;
|
|
97
117
|
const longestFirst = (value) => (Array.isArray(value) ? value : [value]).slice().sort((a, b) => b.length - a.length);
|
|
@@ -101,6 +121,7 @@ var ModifierMatcher = class {
|
|
|
101
121
|
this.elementSepAlt = this.elementSeparators.length ? `(?:${this.elementSeparators.map(escapeRe).join("|")})` : "";
|
|
102
122
|
this.statePrefixes = (convention.statePrefixes ?? []).filter((p) => p !== "").slice().sort((a, b) => b.length - a.length);
|
|
103
123
|
this.statePseudoClasses = new Set(convention.statePseudoClasses ?? []);
|
|
124
|
+
this.pseudoElements = new Set(convention.pseudoElements ?? []);
|
|
104
125
|
}
|
|
105
126
|
/** Does a class name (no leading dot) start with one of the convention's state prefixes? */
|
|
106
127
|
isStateClass(name) {
|
|
@@ -268,6 +289,24 @@ var ModifierMatcher = class {
|
|
|
268
289
|
}
|
|
269
290
|
return out;
|
|
270
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* Every native pseudo-element on the selector recognized for documentation — a `::name` whose `name`
|
|
294
|
+
* is in the convention's {@link ModifierConvention.pseudoElements} (e.g. `.alert::before` → `before`).
|
|
295
|
+
* `::part()`/`::slotted()` and pseudo-elements not in the set are ignored.
|
|
296
|
+
*/
|
|
297
|
+
pseudoElementsIn(selector) {
|
|
298
|
+
if (this.pseudoElements.size === 0) return [];
|
|
299
|
+
const seen = /* @__PURE__ */ new Set();
|
|
300
|
+
const out = [];
|
|
301
|
+
for (const m of selector.matchAll(/::([\w-]+)/gu)) {
|
|
302
|
+
const name = m[1];
|
|
303
|
+
if (this.pseudoElements.has(name) && !seen.has(name)) {
|
|
304
|
+
seen.add(name);
|
|
305
|
+
out.push({ name });
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
271
310
|
/** Derive `prop`/`value` for a modifier `name` (as returned by {@link modifiersIn} or authored). */
|
|
272
311
|
analyze(name) {
|
|
273
312
|
if (name.includes("*")) {
|
|
@@ -402,24 +441,12 @@ var CssDocTagDefinition = class {
|
|
|
402
441
|
function def(options) {
|
|
403
442
|
return new CssDocTagDefinition(options);
|
|
404
443
|
}
|
|
405
|
-
/**
|
|
406
|
-
* A parse configuration: the set of tag definitions plus which are supported. Construct one to get the
|
|
407
|
-
* full standard vocabulary, then add custom tags or disable standard ones.
|
|
408
|
-
*
|
|
409
|
-
* @example
|
|
410
|
-
* ```ts
|
|
411
|
-
* import { CssDocConfiguration, CssDocTagDefinition, parseCssDocs } from "@cssdoc/core";
|
|
412
|
-
*
|
|
413
|
-
* const config = new CssDocConfiguration();
|
|
414
|
-
* config.addTagDefinition(new CssDocTagDefinition({ tagName: "@token", syntaxKind: "block" }), true);
|
|
415
|
-
* const model = parseCssDocs(css, { configuration: config });
|
|
416
|
-
* ```
|
|
417
|
-
*/
|
|
418
444
|
var CssDocConfiguration = class CssDocConfiguration {
|
|
419
445
|
_tagDefinitions = [];
|
|
420
446
|
_byName = /* @__PURE__ */ new Map();
|
|
421
447
|
_supported = /* @__PURE__ */ new Set();
|
|
422
448
|
_modifierConvention = DEFAULT_MODIFIER_CONVENTION;
|
|
449
|
+
_inlineComments = "append";
|
|
423
450
|
constructor() {
|
|
424
451
|
this.addTagDefinitions(CssDocConfiguration.standardTags(), true);
|
|
425
452
|
}
|
|
@@ -431,6 +458,14 @@ var CssDocConfiguration = class CssDocConfiguration {
|
|
|
431
458
|
setModifierConvention(input) {
|
|
432
459
|
this._modifierConvention = resolveModifierConvention(input);
|
|
433
460
|
}
|
|
461
|
+
/** How inline `/* … *\/` comments combine with tag prose (defaults to `append`). */
|
|
462
|
+
get inlineComments() {
|
|
463
|
+
return this._inlineComments;
|
|
464
|
+
}
|
|
465
|
+
/** Set the inline-comment combine mode. */
|
|
466
|
+
setInlineComments(mode) {
|
|
467
|
+
this._inlineComments = mode;
|
|
468
|
+
}
|
|
434
469
|
/** Every registered tag definition, in registration order. */
|
|
435
470
|
get tagDefinitions() {
|
|
436
471
|
return this._tagDefinitions;
|
|
@@ -561,6 +596,9 @@ function parseDocComment(raw, configuration = new CssDocConfiguration(), parse)
|
|
|
561
596
|
parts: /* @__PURE__ */ new Map(),
|
|
562
597
|
tokens: /* @__PURE__ */ new Map(),
|
|
563
598
|
cssParts: /* @__PURE__ */ new Map(),
|
|
599
|
+
pseudoElements: /* @__PURE__ */ new Map(),
|
|
600
|
+
wrappers: /* @__PURE__ */ new Map(),
|
|
601
|
+
todos: [],
|
|
564
602
|
cssProperties: [],
|
|
565
603
|
cssStates: /* @__PURE__ */ new Map(),
|
|
566
604
|
slots: /* @__PURE__ */ new Map(),
|
|
@@ -613,6 +651,11 @@ function applyBlockTag(doc, canonical, tagName, rest, parse) {
|
|
|
613
651
|
case "privateRemarks":
|
|
614
652
|
doc.privateRemarks = rest.trim();
|
|
615
653
|
break;
|
|
654
|
+
case "todo": {
|
|
655
|
+
const todo = rest.trim();
|
|
656
|
+
if (todo) doc.todos.push(todo);
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
616
659
|
case "since":
|
|
617
660
|
doc.since = rest.trim();
|
|
618
661
|
break;
|
|
@@ -648,6 +691,16 @@ function applyBlockTag(doc, canonical, tagName, rest, parse) {
|
|
|
648
691
|
doc.cssParts.set(head.replace(/^\./u, ""), description ?? "");
|
|
649
692
|
break;
|
|
650
693
|
}
|
|
694
|
+
case "pseudo": {
|
|
695
|
+
const { head, description } = splitDesc(rest);
|
|
696
|
+
doc.pseudoElements.set(head.replace(/^::/u, ""), description ?? "");
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
case "wrapper": {
|
|
700
|
+
const { head, description } = splitDesc(rest);
|
|
701
|
+
doc.wrappers.set(head.replace(/^\./u, ""), description ?? "");
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
651
704
|
case "cssproperty": {
|
|
652
705
|
const propMatch = rest.match(/^(--[\w-]+)\s*(<[^>]+>)?\s*(?:(?:—|-{1,2})\s*(.*))?$/u);
|
|
653
706
|
if (propMatch) doc.cssProperties.push({
|
|
@@ -700,7 +753,7 @@ function applyBlockTag(doc, canonical, tagName, rest, parse) {
|
|
|
700
753
|
break;
|
|
701
754
|
}
|
|
702
755
|
case "example":
|
|
703
|
-
doc.examples.push(rest);
|
|
756
|
+
doc.examples.push(rest.replace(/\\`/gu, "`"));
|
|
704
757
|
break;
|
|
705
758
|
case "deprecated":
|
|
706
759
|
doc.deprecated = rest;
|
|
@@ -828,6 +881,12 @@ const EDGE = {
|
|
|
828
881
|
many: "-->|0..n|",
|
|
829
882
|
"one-or-more": "-->|1..n|"
|
|
830
883
|
};
|
|
884
|
+
/** The ER range token for a cardinality — used on the root's label, which has no incoming edge. */
|
|
885
|
+
const CARDINALITY_TOKEN = {
|
|
886
|
+
optional: "0..1",
|
|
887
|
+
many: "0..n",
|
|
888
|
+
"one-or-more": "1..n"
|
|
889
|
+
};
|
|
831
890
|
/** Wrap a node's label in the shape mermaid draws for its class. */
|
|
832
891
|
const SHAPE = {
|
|
833
892
|
"cssdoc-root": (id, l) => `${id}["${l}"]`,
|
|
@@ -853,10 +912,13 @@ function classify(node, isRoot, options) {
|
|
|
853
912
|
klass: "cssdoc-slot",
|
|
854
913
|
label: slot[1] ? `‹content: ${slot[1]}›` : "‹content›"
|
|
855
914
|
};
|
|
856
|
-
if (isRoot)
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
915
|
+
if (isRoot) {
|
|
916
|
+
const card = node.cardinality ? ` (${CARDINALITY_TOKEN[node.cardinality]})` : "";
|
|
917
|
+
return {
|
|
918
|
+
klass: "cssdoc-root",
|
|
919
|
+
label: `${node.selector}${card}`
|
|
920
|
+
};
|
|
921
|
+
}
|
|
860
922
|
const primary = firstClass(node.selector);
|
|
861
923
|
if (primary && primary !== options.self) {
|
|
862
924
|
const component = options.resolveComponent?.(primary);
|
|
@@ -50,6 +50,12 @@ interface ModifierConvention {
|
|
|
50
50
|
* of form/UI states, deliberately excluding ubiquitous interaction pseudos (`:hover`, `:focus`).
|
|
51
51
|
*/
|
|
52
52
|
statePseudoClasses?: string[];
|
|
53
|
+
/**
|
|
54
|
+
* Native pseudo-elements (without the `::`) to document when they appear on a component's selectors,
|
|
55
|
+
* e.g. `["before", "after"]`. Defaults to {@link DEFAULT_PSEUDO_ELEMENTS} — a curated set of standard
|
|
56
|
+
* pseudo-elements, excluding vendor/experimental ones. Shadow `::part()` is handled separately.
|
|
57
|
+
*/
|
|
58
|
+
pseudoElements?: string[];
|
|
53
59
|
/**
|
|
54
60
|
* Split the modifier body into `prop`/`value` on {@link ModifierConvention.propValueSeparator}?
|
|
55
61
|
* Defaults to `false`. Ignored for `attribute` (which always derives `prop` from the attribute name
|
|
@@ -127,6 +133,8 @@ declare class ModifierMatcher {
|
|
|
127
133
|
private readonly statePrefixes;
|
|
128
134
|
/** Native pseudo-classes (no `:`) recognized as states. */
|
|
129
135
|
private readonly statePseudoClasses;
|
|
136
|
+
/** Native pseudo-elements (no `::`) recognized as documented pseudo-elements. */
|
|
137
|
+
private readonly pseudoElements;
|
|
130
138
|
constructor(convention: ModifierConvention);
|
|
131
139
|
/** Does a class name (no leading dot) start with one of the convention's state prefixes? */
|
|
132
140
|
private isStateClass;
|
|
@@ -180,6 +188,14 @@ declare class ModifierMatcher {
|
|
|
180
188
|
pseudoStatesIn(selector: string): {
|
|
181
189
|
name: string;
|
|
182
190
|
}[];
|
|
191
|
+
/**
|
|
192
|
+
* Every native pseudo-element on the selector recognized for documentation — a `::name` whose `name`
|
|
193
|
+
* is in the convention's {@link ModifierConvention.pseudoElements} (e.g. `.alert::before` → `before`).
|
|
194
|
+
* `::part()`/`::slotted()` and pseudo-elements not in the set are ignored.
|
|
195
|
+
*/
|
|
196
|
+
pseudoElementsIn(selector: string): {
|
|
197
|
+
name: string;
|
|
198
|
+
}[];
|
|
183
199
|
/** Derive `prop`/`value` for a modifier `name` (as returned by {@link modifiersIn} or authored). */
|
|
184
200
|
analyze(name: string): {
|
|
185
201
|
prop: string;
|
|
@@ -283,6 +299,17 @@ interface CssState {
|
|
|
283
299
|
/** Prose from a `@cssstate` doc tag, when authored. */
|
|
284
300
|
description?: string;
|
|
285
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* A native pseudo-element a component styles (`::before`, `::marker`, `::selection`, …) — from a
|
|
304
|
+
* `@pseudo` doc tag or derived from a `::name` selector. Shadow `::part()` parts are modeled separately
|
|
305
|
+
* as {@link CssPart} (`shadowParts`), since only they map to a Custom Elements Manifest entry.
|
|
306
|
+
*/
|
|
307
|
+
interface CssPseudoElement {
|
|
308
|
+
/** The pseudo-element name without the leading `::`, e.g. `before`. */
|
|
309
|
+
name: string;
|
|
310
|
+
/** Prose from a `@pseudo` doc tag, when authored. */
|
|
311
|
+
description?: string;
|
|
312
|
+
}
|
|
286
313
|
/** A named slot a component shell exposes (`@slot`, Custom Elements Manifest). */
|
|
287
314
|
interface CssSlot {
|
|
288
315
|
/** The slot name (empty string for the default slot). */
|
|
@@ -367,6 +394,8 @@ interface StructureNode {
|
|
|
367
394
|
* the stored selector.
|
|
368
395
|
*/
|
|
369
396
|
cardinality?: "optional" | "many" | "one-or-more";
|
|
397
|
+
/** Prose from a `@wrapper` doc tag matching this node's class, when authored (annotates the node). */
|
|
398
|
+
description?: string;
|
|
370
399
|
/** Child nodes (rules nested one brace level deeper). */
|
|
371
400
|
children: StructureNode[];
|
|
372
401
|
}
|
|
@@ -426,10 +455,17 @@ interface CssDocEntry {
|
|
|
426
455
|
parts: CssPart[];
|
|
427
456
|
/** Shadow-DOM exposed parts (`::part(name)`), from `@csspart` or a `::part()` selector. */
|
|
428
457
|
shadowParts: CssPart[];
|
|
458
|
+
/** Native pseudo-elements the component styles (`::before`, `::marker`, …), from `@pseudo` or a selector. */
|
|
459
|
+
pseudoElements: CssPseudoElement[];
|
|
429
460
|
/** States the component reacts to, from `@cssstate`, `:state()`, pseudo-classes, or state classes. */
|
|
430
461
|
states: CssState[];
|
|
431
462
|
/** Named slots the component shell exposes, from `@slot`. */
|
|
432
463
|
slots: CssSlot[];
|
|
464
|
+
/**
|
|
465
|
+
* Internal to-do notes, from `@todo` tags and `/* @todo … *\/` inline comments. Development notes,
|
|
466
|
+
* not public API — emitters may omit them (like {@link CssDocEntry.privateRemarks}).
|
|
467
|
+
*/
|
|
468
|
+
todos: string[];
|
|
433
469
|
/**
|
|
434
470
|
* Design tokens this component consumes: every `--*` custom property referenced via `var(...)` inside
|
|
435
471
|
* its rules, each annotated with `@tokens` prose where authored (and including any `@tokens`-declared
|
|
@@ -553,16 +589,27 @@ declare class CssDocTagDefinition {
|
|
|
553
589
|
* const model = parseCssDocs(css, { configuration: config });
|
|
554
590
|
* ```
|
|
555
591
|
*/
|
|
592
|
+
/**
|
|
593
|
+
* How a `/* … *\/` comment on a member's rule combines with the member's authored tag prose:
|
|
594
|
+
* `append` (tag then comment, the default), `prepend` (comment then tag), `replace` (comment wins when
|
|
595
|
+
* present), or `ignore` (comments are never used as descriptions).
|
|
596
|
+
*/
|
|
597
|
+
type InlineCommentMode = "append" | "prepend" | "replace" | "ignore";
|
|
556
598
|
declare class CssDocConfiguration {
|
|
557
599
|
private readonly _tagDefinitions;
|
|
558
600
|
private readonly _byName;
|
|
559
601
|
private readonly _supported;
|
|
560
602
|
private _modifierConvention;
|
|
603
|
+
private _inlineComments;
|
|
561
604
|
constructor();
|
|
562
605
|
/** The resolved modifier convention this configuration parses with (defaults to BEM). */
|
|
563
606
|
get modifierConvention(): ModifierConvention;
|
|
564
607
|
/** Set the modifier convention from a preset name or a custom {@link ModifierConvention}. */
|
|
565
608
|
setModifierConvention(input: ModifierConventionInput): void;
|
|
609
|
+
/** How inline `/* … *\/` comments combine with tag prose (defaults to `append`). */
|
|
610
|
+
get inlineComments(): InlineCommentMode;
|
|
611
|
+
/** Set the inline-comment combine mode. */
|
|
612
|
+
setInlineComments(mode: InlineCommentMode): void;
|
|
566
613
|
/** Every registered tag definition, in registration order. */
|
|
567
614
|
get tagDefinitions(): readonly CssDocTagDefinition[];
|
|
568
615
|
/** Only the tag definitions that are currently supported. */
|
|
@@ -656,6 +703,12 @@ interface ParsedDoc {
|
|
|
656
703
|
tokens: Map<string, string>;
|
|
657
704
|
/** `@csspart` descriptions (shadow-DOM `::part()`), keyed by the bare part name (e.g. `header`). */
|
|
658
705
|
cssParts: Map<string, string>;
|
|
706
|
+
/** `@pseudo` descriptions (native pseudo-elements), keyed by the bare name (e.g. `before`). */
|
|
707
|
+
pseudoElements: Map<string, string>;
|
|
708
|
+
/** `@wrapper` descriptions (optional-ancestor wrappers), keyed by the bare class (e.g. `badge-wrapper`). */
|
|
709
|
+
wrappers: Map<string, string>;
|
|
710
|
+
/** `@todo` notes (internal development notes). */
|
|
711
|
+
todos: string[];
|
|
659
712
|
/** `@cssproperty` declarations. */
|
|
660
713
|
cssProperties: DocCssProperty[];
|
|
661
714
|
/** `@cssstate` descriptions, keyed by state name. */
|
|
@@ -768,4 +821,4 @@ declare function toMermaid(roots: StructureNode[], options?: MermaidOptions): st
|
|
|
768
821
|
*/
|
|
769
822
|
declare function toJson(model: CssDocEntry[]): string;
|
|
770
823
|
//#endregion
|
|
771
|
-
export {
|
|
824
|
+
export { CssSource as A, ModifierHit as B, CssParse as C, CssRelated as D, CssRecordKind as E, DEFAULT_MODIFIER_CONVENTION as F, resolveModifierConvention as H, DEFAULT_STATE_PSEUDO_CLASSES as I, MODIFIER_PRESETS as L, CssTokenConsumed as M, ParseOptions as N, CssReleaseStage as O, StructureNode as P, ModifierConvention as R, CssModifier as S, CssPropertyDeclared as T, ModifierMatcher as V, CssAnimation as _, DocModifier as a, CssFunction as b, parseDocComment as c, stripCommentFraming as d, CssDocConfiguration as f, InlineCommentMode as g, CssDocTagDefinitionOptions as h, DocCssProperty as i, CssState as j, CssSlot as k, parseStructure as l, CssDocTagDefinition as m, toMermaid as n, ParsedDoc as o, CssDocSyntaxKind as p, DocCondition as r, RECORD_TAGS as s, toJson as t, recordNameOf as u, CssCondition as v, CssPart as w, CssLayer as x, CssDocEntry as y, ModifierConventionInput as z };
|
package/dist/lite.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { type CssAnimation, type CssCondition, CssDocConfiguration, type CssDocEntry, type CssDocSyntaxKind, CssDocTagDefinition, type CssDocTagDefinitionOptions, type CssFunction, type CssLayer, type CssModifier, type CssParse, type CssPart, type CssPropertyDeclared, type CssRecordKind, type CssRelated, type CssReleaseStage, type CssSlot, type CssSource, type CssState, type CssTokenConsumed, DEFAULT_MODIFIER_CONVENTION, DEFAULT_STATE_PSEUDO_CLASSES, type DocCondition, type DocCssProperty, type DocModifier, MODIFIER_PRESETS, type ModifierConvention, type ModifierConventionInput, type ModifierHit, ModifierMatcher, type ParseOptions, type ParsedDoc, RECORD_TAGS, type StructureNode, parseDocComment, parseStructure, recordNameOf, resolveModifierConvention, stripCommentFraming, toJson, toMermaid };
|
|
1
|
+
import { A as CssSource, B as ModifierHit, C as CssParse, D as CssRelated, E as CssRecordKind, F as DEFAULT_MODIFIER_CONVENTION, H as resolveModifierConvention, I as DEFAULT_STATE_PSEUDO_CLASSES, L as MODIFIER_PRESETS, M as CssTokenConsumed, N as ParseOptions, O as CssReleaseStage, P as StructureNode, R as ModifierConvention, S as CssModifier, T as CssPropertyDeclared, V as ModifierMatcher, _ as CssAnimation, a as DocModifier, b as CssFunction, c as parseDocComment, d as stripCommentFraming, f as CssDocConfiguration, g as InlineCommentMode, h as CssDocTagDefinitionOptions, i as DocCssProperty, j as CssState, k as CssSlot, l as parseStructure, m as CssDocTagDefinition, n as toMermaid, o as ParsedDoc, p as CssDocSyntaxKind, r as DocCondition, s as RECORD_TAGS, t as toJson, u as recordNameOf, v as CssCondition, w as CssPart, x as CssLayer, y as CssDocEntry, z as ModifierConventionInput } from "./lite-DzhifijA.mjs";
|
|
2
|
+
export { type CssAnimation, type CssCondition, CssDocConfiguration, type CssDocEntry, type CssDocSyntaxKind, CssDocTagDefinition, type CssDocTagDefinitionOptions, type CssFunction, type CssLayer, type CssModifier, type CssParse, type CssPart, type CssPropertyDeclared, type CssRecordKind, type CssRelated, type CssReleaseStage, type CssSlot, type CssSource, type CssState, type CssTokenConsumed, DEFAULT_MODIFIER_CONVENTION, DEFAULT_STATE_PSEUDO_CLASSES, type DocCondition, type DocCssProperty, type DocModifier, type InlineCommentMode, MODIFIER_PRESETS, type ModifierConvention, type ModifierConventionInput, type ModifierHit, ModifierMatcher, type ParseOptions, type ParsedDoc, RECORD_TAGS, type StructureNode, parseDocComment, parseStructure, recordNameOf, resolveModifierConvention, stripCommentFraming, toJson, toMermaid };
|
package/dist/lite.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as parseStructure, c as CssDocConfiguration, d as DEFAULT_STATE_PSEUDO_CLASSES, f as MODIFIER_PRESETS, i as parseDocComment, l as CssDocTagDefinition, m as resolveModifierConvention, n as toMermaid, o as recordNameOf, p as ModifierMatcher, r as RECORD_TAGS, s as stripCommentFraming, t as toJson, u as DEFAULT_MODIFIER_CONVENTION } from "./lite-
|
|
1
|
+
import { a as parseStructure, c as CssDocConfiguration, d as DEFAULT_STATE_PSEUDO_CLASSES, f as MODIFIER_PRESETS, i as parseDocComment, l as CssDocTagDefinition, m as resolveModifierConvention, n as toMermaid, o as recordNameOf, p as ModifierMatcher, r as RECORD_TAGS, s as stripCommentFraming, t as toJson, u as DEFAULT_MODIFIER_CONVENTION } from "./lite-CEVmwLGF.mjs";
|
|
2
2
|
export { CssDocConfiguration, CssDocTagDefinition, DEFAULT_MODIFIER_CONVENTION, DEFAULT_STATE_PSEUDO_CLASSES, MODIFIER_PRESETS, ModifierMatcher, RECORD_TAGS, parseDocComment, parseStructure, recordNameOf, resolveModifierConvention, stripCommentFraming, toJson, toMermaid };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cssdoc/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A generic CSS documentation extractor: parse doc-comments + the CSS AST into a serializable model (TSDoc, for CSS).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"postcss": "^8.5.
|
|
36
|
-
"@cssdoc/spec": "0.
|
|
35
|
+
"postcss": "^8.5.19",
|
|
36
|
+
"@cssdoc/spec": "0.6.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^24.13.3",
|