@cssdoc/index 0.1.0 → 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/dist/index.d.mts +12 -7
- package/dist/index.mjs +27 -14
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CssAnimation, CssCondition, CssDocConfiguration, CssDocEntry, CssFunction, CssModifier, CssPart, CssPropertyDeclared, CssState, StructureNode } from "@cssdoc/core";
|
|
1
|
+
import { CssAnimation, CssCondition, CssDocConfiguration, CssDocEntry, CssFunction, CssModifier, CssPart, CssPropertyDeclared, CssState, ModifierConventionInput, ModifierMatcher, StructureNode } from "@cssdoc/core";
|
|
2
2
|
|
|
3
3
|
//#region src/index.d.ts
|
|
4
4
|
/** A 1-based line/column position (matching PostCSS). */
|
|
@@ -17,16 +17,18 @@ interface Location {
|
|
|
17
17
|
span: SourceSpan;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* A
|
|
21
|
-
* resolved `base` component class (when one of the tokens names a documented component).
|
|
22
|
-
*
|
|
20
|
+
* A member usage on one element: the classes on the element, the specific `token` under inspection,
|
|
21
|
+
* and the resolved `base` component class (when one of the tokens names a documented component).
|
|
22
|
+
* `token` is normally a class token, but for attribute conventions (CUBE) it may be an attribute
|
|
23
|
+
* expression like `data-variant="ghost"`. Producers for HTML, JSX, and CSS selectors all emit this
|
|
24
|
+
* shape.
|
|
23
25
|
*/
|
|
24
26
|
interface ClassUsage {
|
|
25
27
|
/** The base component class among the tokens, if any (e.g. `.button` → `button`). */
|
|
26
28
|
base?: string;
|
|
27
29
|
/** Every class token on the element. */
|
|
28
30
|
tokens: string[];
|
|
29
|
-
/** The specific token this usage is about (
|
|
31
|
+
/** The specific token/expression this usage is about (a modifier candidate). */
|
|
30
32
|
token: string;
|
|
31
33
|
/** Where the token sits in the host document. */
|
|
32
34
|
loc?: SourceSpan;
|
|
@@ -77,9 +79,11 @@ interface CssDocManifest {
|
|
|
77
79
|
declare class CssDocIndex {
|
|
78
80
|
readonly file?: string;
|
|
79
81
|
readonly records: readonly RecordInfo[];
|
|
82
|
+
/** The modifier matcher for this index's convention — how members are matched and rendered. */
|
|
83
|
+
readonly matcher: ModifierMatcher;
|
|
80
84
|
private readonly byName;
|
|
81
85
|
private readonly byClass;
|
|
82
|
-
constructor(records: RecordInfo[], file?: string);
|
|
86
|
+
constructor(records: RecordInfo[], file?: string, matcher?: ModifierMatcher);
|
|
83
87
|
/** Every documented record's model entry. */
|
|
84
88
|
get entries(): CssDocEntry[];
|
|
85
89
|
/** The record whose base class matches `className` (with or without a leading dot). */
|
|
@@ -94,7 +98,7 @@ declare class CssDocIndex {
|
|
|
94
98
|
conditionsFor(name: string): CssCondition[];
|
|
95
99
|
animationsFor(name: string): CssAnimation[];
|
|
96
100
|
structureFor(name: string): StructureNode[] | undefined;
|
|
97
|
-
/** Whether `modifier` (
|
|
101
|
+
/** Whether `modifier` (a class token or attribute expression) is a documented modifier of `base`. */
|
|
98
102
|
isModifier(base: string, modifier: string): boolean;
|
|
99
103
|
/** The deprecation of a modifier on `base`, if it is deprecated. */
|
|
100
104
|
deprecationOf(base: string, modifier: string): {
|
|
@@ -129,6 +133,7 @@ declare function indexFromEntries(entries: CssDocEntry[], file?: string): CssDoc
|
|
|
129
133
|
declare function createIndex(css: string, options?: {
|
|
130
134
|
file?: string;
|
|
131
135
|
configuration?: CssDocConfiguration;
|
|
136
|
+
modifierConvention?: ModifierConventionInput;
|
|
132
137
|
}): CssDocIndex;
|
|
133
138
|
/**
|
|
134
139
|
* Extract custom-property assignments (`--name: value`) and `var(--name, fallback)` references from
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseCssDocs, parseDocComment, recordNameOf } from "@cssdoc/core";
|
|
1
|
+
import { DEFAULT_MODIFIER_CONVENTION, ModifierMatcher, parseCssDocs, parseDocComment, recordNameOf, resolveModifierConvention } from "@cssdoc/core";
|
|
2
2
|
import postcss from "postcss";
|
|
3
3
|
import valueParser from "postcss-value-parser";
|
|
4
4
|
//#region src/index.ts
|
|
@@ -18,7 +18,6 @@ import valueParser from "postcss-value-parser";
|
|
|
18
18
|
function memberKey(kind, id = "") {
|
|
19
19
|
return id ? `${kind}:${id}` : kind;
|
|
20
20
|
}
|
|
21
|
-
const escapeRe = (value) => value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
22
21
|
const stripDot = (name) => name.replace(/^\./u, "");
|
|
23
22
|
const spanOf = (node) => {
|
|
24
23
|
const { source } = node;
|
|
@@ -39,11 +38,14 @@ const spanOf = (node) => {
|
|
|
39
38
|
var CssDocIndex = class {
|
|
40
39
|
file;
|
|
41
40
|
records;
|
|
41
|
+
/** The modifier matcher for this index's convention — how members are matched and rendered. */
|
|
42
|
+
matcher;
|
|
42
43
|
byName = /* @__PURE__ */ new Map();
|
|
43
44
|
byClass = /* @__PURE__ */ new Map();
|
|
44
|
-
constructor(records, file) {
|
|
45
|
+
constructor(records, file, matcher) {
|
|
45
46
|
this.records = records;
|
|
46
47
|
this.file = file;
|
|
48
|
+
this.matcher = matcher ?? new ModifierMatcher(DEFAULT_MODIFIER_CONVENTION);
|
|
47
49
|
for (const record of records) {
|
|
48
50
|
this.byName.set(record.entry.name, record);
|
|
49
51
|
this.byClass.set(stripDot(record.entry.className), record);
|
|
@@ -85,14 +87,14 @@ var CssDocIndex = class {
|
|
|
85
87
|
structureFor(name) {
|
|
86
88
|
return this.byName.get(name)?.entry.structure;
|
|
87
89
|
}
|
|
88
|
-
/** Whether `modifier` (
|
|
90
|
+
/** Whether `modifier` (a class token or attribute expression) is a documented modifier of `base`. */
|
|
89
91
|
isModifier(base, modifier) {
|
|
90
|
-
const wanted =
|
|
92
|
+
const wanted = this.matcher.normalizeMember(modifier);
|
|
91
93
|
return this.byClass.get(stripDot(base))?.entry.modifiers.some((m) => m.name === wanted) ?? false;
|
|
92
94
|
}
|
|
93
95
|
/** The deprecation of a modifier on `base`, if it is deprecated. */
|
|
94
96
|
deprecationOf(base, modifier) {
|
|
95
|
-
const wanted =
|
|
97
|
+
const wanted = this.matcher.normalizeMember(modifier);
|
|
96
98
|
return this.byClass.get(stripDot(base))?.entry.modifiers.find((m) => m.name === wanted)?.deprecated;
|
|
97
99
|
}
|
|
98
100
|
/** Every declared custom property, paired with the record that declares it (for `var(...)` completion). */
|
|
@@ -139,8 +141,8 @@ function indexFromEntries(entries, file) {
|
|
|
139
141
|
})), file);
|
|
140
142
|
}
|
|
141
143
|
/** Scan a record's nodes for member spans, recording each member's first occurrence. */
|
|
142
|
-
function scanNodes(nodes, build, base) {
|
|
143
|
-
const
|
|
144
|
+
function scanNodes(nodes, build, base, matcher) {
|
|
145
|
+
const baseNoDot = stripDot(base);
|
|
144
146
|
const set = (key, node) => {
|
|
145
147
|
const span = spanOf(node);
|
|
146
148
|
if (span && !build.memberSpans.has(key)) build.memberSpans.set(key, span);
|
|
@@ -149,10 +151,17 @@ function scanNodes(nodes, build, base) {
|
|
|
149
151
|
build.selectorText += ` ${node.selector}`;
|
|
150
152
|
if (`.${stripDot(node.selector.trim())}` === base && !build.span) build.span = spanOf(node);
|
|
151
153
|
for (const selector of node.selector.split(",")) {
|
|
152
|
-
for (const m of selector.matchAll(modRe)) for (const mod of m[1].matchAll(/\.(-[\w-]+)/gu)) set(memberKey("modifier", mod[1]), node);
|
|
153
154
|
for (const s of selector.matchAll(/:state\(\s*([\w-]+)\s*\)/gu)) set(memberKey("state", s[1]), node);
|
|
154
155
|
const bare = selector.replace(/::?[\w-]+(\([^)]*\))?/gu, "");
|
|
155
|
-
|
|
156
|
+
const modNames = /* @__PURE__ */ new Set();
|
|
157
|
+
for (const mod of matcher.modifiersIn(bare, baseNoDot)) {
|
|
158
|
+
modNames.add(mod.name);
|
|
159
|
+
set(memberKey("modifier", mod.name), node);
|
|
160
|
+
}
|
|
161
|
+
for (const p of bare.matchAll(/\.([a-z][\w-]*)/gu)) {
|
|
162
|
+
if (modNames.has(p[1])) continue;
|
|
163
|
+
set(memberKey("part", p[1]), node);
|
|
164
|
+
}
|
|
156
165
|
}
|
|
157
166
|
} else if (node.type === "atrule") {
|
|
158
167
|
if (node.name === "property") set(memberKey("property", node.params.trim()), node);
|
|
@@ -165,7 +174,7 @@ function scanNodes(nodes, build, base) {
|
|
|
165
174
|
if (layer) set(memberKey("layer", layer), node);
|
|
166
175
|
}
|
|
167
176
|
else if (node.name === "container" || node.name === "supports" || node.name === "media") set(memberKey("condition", `${node.name}:${node.params.trim()}`), node);
|
|
168
|
-
if (node.nodes) scanNodes(node.nodes, build, base);
|
|
177
|
+
if (node.nodes) scanNodes(node.nodes, build, base, matcher);
|
|
169
178
|
}
|
|
170
179
|
}
|
|
171
180
|
/**
|
|
@@ -177,7 +186,11 @@ function scanNodes(nodes, build, base) {
|
|
|
177
186
|
* @returns The index.
|
|
178
187
|
*/
|
|
179
188
|
function createIndex(css, options = {}) {
|
|
180
|
-
const
|
|
189
|
+
const matcher = new ModifierMatcher(resolveModifierConvention(options.modifierConvention ?? options.configuration?.modifierConvention));
|
|
190
|
+
const entries = parseCssDocs(css, {
|
|
191
|
+
configuration: options.configuration,
|
|
192
|
+
modifierConvention: options.modifierConvention
|
|
193
|
+
});
|
|
181
194
|
const byName = new Map(entries.map((e) => [e.name, e]));
|
|
182
195
|
const builds = /* @__PURE__ */ new Map();
|
|
183
196
|
const root = postcss.parse(css);
|
|
@@ -200,7 +213,7 @@ function createIndex(css, options = {}) {
|
|
|
200
213
|
continue;
|
|
201
214
|
}
|
|
202
215
|
}
|
|
203
|
-
if (current) scanNodes([node], current, current.entry.className);
|
|
216
|
+
if (current) scanNodes([node], current, current.entry.className, matcher);
|
|
204
217
|
}
|
|
205
218
|
return new CssDocIndex(entries.map((entry) => builds.get(entry.name) ?? {
|
|
206
219
|
entry,
|
|
@@ -208,7 +221,7 @@ function createIndex(css, options = {}) {
|
|
|
208
221
|
authoredModifiers: /* @__PURE__ */ new Set(),
|
|
209
222
|
authoredParts: /* @__PURE__ */ new Set(),
|
|
210
223
|
selectorText: ""
|
|
211
|
-
}), options.file);
|
|
224
|
+
}), options.file, matcher);
|
|
212
225
|
}
|
|
213
226
|
/**
|
|
214
227
|
* Extract custom-property assignments (`--name: value`) and `var(--name, fallback)` references from
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cssdoc/index",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A queryable semantic index over the @cssdoc/core model, plus a host-agnostic Usage abstraction and source spans — the shared data layer for cssdoc's linters and language server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"postcss": "^8.5.16",
|
|
32
32
|
"postcss-value-parser": "^4.2.0",
|
|
33
|
-
"@cssdoc/core": "0.
|
|
33
|
+
"@cssdoc/core": "0.2.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^24.13.3",
|