@cssdoc/providers 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 +26 -5
- package/dist/index.mjs +76 -23
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,27 @@ import { ClassUsage, CssDocIndex, Location, Location as Location$1, PropertyAssi
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
/** Diagnostic severity. */
|
|
5
5
|
type Severity = "error" | "warning";
|
|
6
|
+
/** A configurable per-rule severity — `off` suppresses the rule entirely. */
|
|
7
|
+
type RuleSeverity = "off" | "warn" | "error";
|
|
8
|
+
/**
|
|
9
|
+
* Every rule id an aspect can emit, author-side and consumer-side. A superset of `@cssdoc/lint-core`'s
|
|
10
|
+
* author-side `RuleName` (which omits the consumer-side `unknown-modifier`/`deprecated-modifier` and
|
|
11
|
+
* the opt-in `unknown-custom-property`).
|
|
12
|
+
*/
|
|
13
|
+
type RuleId = "missing-summary" | "undocumented-modifier" | "deprecated-requires-canonical" | "name-not-in-css" | "unknown-modifier" | "deprecated-modifier" | "undocumented-part" | "invalid-default-value" | "invalid-property-value" | "invalid-fallback-value" | "unknown-custom-property";
|
|
14
|
+
/** A resolved severity for every rule. */
|
|
15
|
+
type RuleSeverities = Record<RuleId, RuleSeverity>;
|
|
16
|
+
/**
|
|
17
|
+
* The default rule severities. `unknown-modifier` defaults to `warn` — safe under the BEM default's
|
|
18
|
+
* strong `--` signal; lower it to `off` for weak-signal conventions (bare/OOCSS) where every chained
|
|
19
|
+
* class is a candidate. `unknown-custom-property` stays `off` (it needs an opt-in `propertyPrefix`).
|
|
20
|
+
*/
|
|
21
|
+
declare const DEFAULT_RULE_SEVERITIES: RuleSeverities;
|
|
22
|
+
/**
|
|
23
|
+
* Merge per-rule overrides over {@link DEFAULT_RULE_SEVERITIES}. A `boolean` override is accepted for
|
|
24
|
+
* back-compat: `false` → `off`, `true` → the rule's default.
|
|
25
|
+
*/
|
|
26
|
+
declare function resolveRuleSeverities(overrides?: Partial<Record<RuleId, RuleSeverity | boolean>>): RuleSeverities;
|
|
6
27
|
/** One diagnostic from an aspect. */
|
|
7
28
|
interface Diagnostic {
|
|
8
29
|
/** The aspect that produced it (e.g. `modifier`). */
|
|
@@ -98,13 +119,13 @@ declare const func: {
|
|
|
98
119
|
/** The aspect names covered, in a stable order (the extension point for future aspects). */
|
|
99
120
|
declare const ASPECTS: readonly ["record", "modifier", "part", "custom-property", "structure", "function", "state", "condition"];
|
|
100
121
|
/** Author-side hygiene diagnostics over the whole model (missing summaries, undocumented members, drift, invalid defaults). */
|
|
101
|
-
declare function lintModel(index: CssDocIndex): Diagnostic[];
|
|
122
|
+
declare function lintModel(index: CssDocIndex, severities?: RuleSeverities): Diagnostic[];
|
|
102
123
|
/** Consumer-side diagnostics for custom-property assignments (`--x: value` must match its `@property` syntax). */
|
|
103
|
-
declare function checkPropertyAssignments(assignments: readonly PropertyAssignment[], index: CssDocIndex): Diagnostic[];
|
|
124
|
+
declare function checkPropertyAssignments(assignments: readonly PropertyAssignment[], index: CssDocIndex, severities?: RuleSeverities): Diagnostic[];
|
|
104
125
|
/** Consumer-side diagnostics for class-attribute usage (unknown or deprecated modifiers). */
|
|
105
|
-
declare function checkClassUsage(usages: readonly ClassUsage[], index: CssDocIndex): Diagnostic[];
|
|
126
|
+
declare function checkClassUsage(usages: readonly ClassUsage[], index: CssDocIndex, severities?: RuleSeverities): Diagnostic[];
|
|
106
127
|
/** Consumer-side diagnostics for `var(--…)` references (unknown custom properties; opt-in via prefix). */
|
|
107
|
-
declare function checkPropertyUsage(usages: readonly PropertyUsage[], index: CssDocIndex, options?: UsageOptions): Diagnostic[];
|
|
128
|
+
declare function checkPropertyUsage(usages: readonly PropertyUsage[], index: CssDocIndex, options?: UsageOptions, severities?: RuleSeverities): Diagnostic[];
|
|
108
129
|
/** Completions for a class attribute: modifiers of `base` when given, else the component classes. */
|
|
109
130
|
declare function completeClasses(base: string | undefined, index: CssDocIndex): Completion[];
|
|
110
131
|
/** Completions for `var(--…)`: the declared custom properties. */
|
|
@@ -124,4 +145,4 @@ declare function definitionForCustomProperty(name: string, index: CssDocIndex):
|
|
|
124
145
|
/** Definition of a custom function (its `@function` rule). */
|
|
125
146
|
declare function definitionForFunction(name: string, index: CssDocIndex): Location$1 | undefined;
|
|
126
147
|
//#endregion
|
|
127
|
-
export { ASPECTS, Completion, CompletionKind, Diagnostic, Hover, type Location, Severity, type SourceSpan, SyntaxMatch, UsageOptions, checkClassUsage, checkPropertyAssignments, checkPropertyUsage, completeClasses, completeCustomProperties, completeFunctions, customProperty, definitionForClass, definitionForCustomProperty, definitionForFunction, func, hoverForClass, hoverForCustomProperty, hoverForFunction, lintModel, matchesSyntax, modifier, part, record };
|
|
148
|
+
export { ASPECTS, Completion, CompletionKind, DEFAULT_RULE_SEVERITIES, Diagnostic, Hover, type Location, RuleId, RuleSeverities, RuleSeverity, Severity, type SourceSpan, SyntaxMatch, UsageOptions, checkClassUsage, checkPropertyAssignments, checkPropertyUsage, completeClasses, completeCustomProperties, completeFunctions, customProperty, definitionForClass, definitionForCustomProperty, definitionForFunction, func, hoverForClass, hoverForCustomProperty, hoverForFunction, lintModel, matchesSyntax, modifier, part, record, resolveRuleSeverities };
|
package/dist/index.mjs
CHANGED
|
@@ -119,26 +119,27 @@ const modifier = {
|
|
|
119
119
|
for (const info of index.records) {
|
|
120
120
|
const name = info.entry.name;
|
|
121
121
|
for (const m of info.entry.modifiers) {
|
|
122
|
+
const sel = index.matcher.selectorFor(m.name);
|
|
122
123
|
const span = info.memberSpans.get(memberKey("modifier", m.name)) ?? info.span;
|
|
123
124
|
if (!m.description?.trim() && !m.deprecated) out.push(warn({
|
|
124
125
|
aspect: "modifier",
|
|
125
126
|
rule: "undocumented-modifier",
|
|
126
|
-
message: `Modifier "
|
|
127
|
+
message: `Modifier "${sel}" of "${name}" has no @modifier description.`,
|
|
127
128
|
record: name,
|
|
128
129
|
span
|
|
129
130
|
}));
|
|
130
131
|
if (m.deprecated && !m.deprecated.canonical && !m.deprecated.note?.trim()) out.push(warn({
|
|
131
132
|
aspect: "modifier",
|
|
132
133
|
rule: "deprecated-requires-canonical",
|
|
133
|
-
message: `Deprecated modifier "
|
|
134
|
+
message: `Deprecated modifier "${sel}" of "${name}" needs a canonical replacement ({@link}) or a note.`,
|
|
134
135
|
record: name,
|
|
135
136
|
span
|
|
136
137
|
}));
|
|
137
138
|
}
|
|
138
|
-
for (const authored of info.authoredModifiers) if (!info.selectorText.includes(
|
|
139
|
+
for (const authored of info.authoredModifiers) if (!info.selectorText.includes(index.matcher.selectorFor(authored))) out.push(warn({
|
|
139
140
|
aspect: "modifier",
|
|
140
141
|
rule: "name-not-in-css",
|
|
141
|
-
message: `Documented modifier "
|
|
142
|
+
message: `Documented modifier "${index.matcher.selectorFor(authored)}" of "${name}" is not defined by any selector.`,
|
|
142
143
|
record: name,
|
|
143
144
|
span: info.span
|
|
144
145
|
}));
|
|
@@ -146,23 +147,24 @@ const modifier = {
|
|
|
146
147
|
return out;
|
|
147
148
|
},
|
|
148
149
|
classUsage(usage, index) {
|
|
149
|
-
if (!usage.base || !usage.token.
|
|
150
|
+
if (!usage.base || !index.matcher.looksLikeUsage(usage.token, usage.base)) return [];
|
|
150
151
|
const entry = index.componentForClass(usage.base);
|
|
151
152
|
if (!entry) return [];
|
|
153
|
+
const sel = index.matcher.selectorFor(index.matcher.normalizeMember(usage.token));
|
|
152
154
|
if (!index.isModifier(usage.base, usage.token)) return [warn({
|
|
153
155
|
aspect: "modifier",
|
|
154
156
|
rule: "unknown-modifier",
|
|
155
|
-
message: `"
|
|
157
|
+
message: `"${sel}" is not a documented modifier of "${entry.name}".`,
|
|
156
158
|
record: entry.name,
|
|
157
159
|
span: usage.loc
|
|
158
160
|
})];
|
|
159
161
|
const dep = index.deprecationOf(usage.base, usage.token);
|
|
160
162
|
if (dep) {
|
|
161
|
-
const advice = dep.canonical ? `use "
|
|
163
|
+
const advice = dep.canonical ? `use "${index.matcher.selectorFor(dep.canonical)}"` : dep.note ?? "no replacement given";
|
|
162
164
|
return [warn({
|
|
163
165
|
aspect: "modifier",
|
|
164
166
|
rule: "deprecated-modifier",
|
|
165
|
-
message: `Modifier "
|
|
167
|
+
message: `Modifier "${sel}" of "${entry.name}" is deprecated — ${advice}.`,
|
|
166
168
|
record: entry.name,
|
|
167
169
|
span: usage.loc
|
|
168
170
|
})];
|
|
@@ -173,7 +175,7 @@ const modifier = {
|
|
|
173
175
|
const entry = index.componentForClass(base);
|
|
174
176
|
if (!entry) return [];
|
|
175
177
|
return entry.modifiers.map((m) => ({
|
|
176
|
-
label:
|
|
178
|
+
label: m.name,
|
|
177
179
|
kind: "modifier",
|
|
178
180
|
detail: m.prop,
|
|
179
181
|
documentation: m.description,
|
|
@@ -182,19 +184,19 @@ const modifier = {
|
|
|
182
184
|
},
|
|
183
185
|
hover(base, token, index) {
|
|
184
186
|
const entry = index.componentForClass(base);
|
|
185
|
-
const m = entry?.modifiers.find((x) => x.name ===
|
|
187
|
+
const m = entry?.modifiers.find((x) => x.name === index.matcher.normalizeMember(token));
|
|
186
188
|
if (!m) return void 0;
|
|
187
|
-
const lines = [
|
|
189
|
+
const lines = [`\`${index.matcher.selectorFor(m.name)}\` — modifier of \`${entry.className}\``];
|
|
188
190
|
if (m.description) lines.push("", m.description);
|
|
189
191
|
if (m.deprecated) {
|
|
190
|
-
const advice = m.deprecated.canonical ? `use
|
|
192
|
+
const advice = m.deprecated.canonical ? `use \`${index.matcher.selectorFor(m.deprecated.canonical)}\`` : m.deprecated.note ?? "";
|
|
191
193
|
lines.push("", `**Deprecated** — ${advice}`);
|
|
192
194
|
}
|
|
193
195
|
return { contents: lines.join("\n") };
|
|
194
196
|
},
|
|
195
197
|
definition(base, token, index) {
|
|
196
198
|
const entry = index.componentForClass(base);
|
|
197
|
-
return entry ? index.location(entry.name, memberKey("modifier",
|
|
199
|
+
return entry ? index.location(entry.name, memberKey("modifier", index.matcher.normalizeMember(token))) : void 0;
|
|
198
200
|
}
|
|
199
201
|
};
|
|
200
202
|
const part = { model(index) {
|
|
@@ -328,7 +330,58 @@ const func = {
|
|
|
328
330
|
}
|
|
329
331
|
};
|
|
330
332
|
//#endregion
|
|
333
|
+
//#region src/types.ts
|
|
334
|
+
/**
|
|
335
|
+
* The default rule severities. `unknown-modifier` defaults to `warn` — safe under the BEM default's
|
|
336
|
+
* strong `--` signal; lower it to `off` for weak-signal conventions (bare/OOCSS) where every chained
|
|
337
|
+
* class is a candidate. `unknown-custom-property` stays `off` (it needs an opt-in `propertyPrefix`).
|
|
338
|
+
*/
|
|
339
|
+
const DEFAULT_RULE_SEVERITIES = {
|
|
340
|
+
"missing-summary": "warn",
|
|
341
|
+
"undocumented-modifier": "warn",
|
|
342
|
+
"deprecated-requires-canonical": "warn",
|
|
343
|
+
"name-not-in-css": "warn",
|
|
344
|
+
"unknown-modifier": "warn",
|
|
345
|
+
"deprecated-modifier": "warn",
|
|
346
|
+
"undocumented-part": "warn",
|
|
347
|
+
"invalid-default-value": "warn",
|
|
348
|
+
"invalid-property-value": "warn",
|
|
349
|
+
"invalid-fallback-value": "warn",
|
|
350
|
+
"unknown-custom-property": "off"
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Merge per-rule overrides over {@link DEFAULT_RULE_SEVERITIES}. A `boolean` override is accepted for
|
|
354
|
+
* back-compat: `false` → `off`, `true` → the rule's default.
|
|
355
|
+
*/
|
|
356
|
+
function resolveRuleSeverities(overrides) {
|
|
357
|
+
const resolved = { ...DEFAULT_RULE_SEVERITIES };
|
|
358
|
+
if (!overrides) return resolved;
|
|
359
|
+
for (const [rule, value] of Object.entries(overrides)) {
|
|
360
|
+
if (value === void 0) continue;
|
|
361
|
+
if (typeof value === "boolean") resolved[rule] = value ? DEFAULT_RULE_SEVERITIES[rule] : "off";
|
|
362
|
+
else resolved[rule] = value;
|
|
363
|
+
}
|
|
364
|
+
return resolved;
|
|
365
|
+
}
|
|
366
|
+
//#endregion
|
|
331
367
|
//#region src/index.ts
|
|
368
|
+
/**
|
|
369
|
+
* Apply resolved rule severities to a batch of diagnostics: drop `off` rules, and stamp the configured
|
|
370
|
+
* severity onto the rest. This is the single place severity/enablement is decided — every host inherits
|
|
371
|
+
* it. Aspects emit a placeholder `warning`; this overrides it.
|
|
372
|
+
*/
|
|
373
|
+
function applySeverities(diagnostics, severities) {
|
|
374
|
+
const out = [];
|
|
375
|
+
for (const d of diagnostics) {
|
|
376
|
+
const severity = severities[d.rule] ?? "warn";
|
|
377
|
+
if (severity === "off") continue;
|
|
378
|
+
out.push({
|
|
379
|
+
...d,
|
|
380
|
+
severity: severity === "error" ? "error" : "warning"
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return out;
|
|
384
|
+
}
|
|
332
385
|
/** The aspect names covered, in a stable order (the extension point for future aspects). */
|
|
333
386
|
const ASPECTS = [
|
|
334
387
|
"record",
|
|
@@ -341,25 +394,25 @@ const ASPECTS = [
|
|
|
341
394
|
"condition"
|
|
342
395
|
];
|
|
343
396
|
/** Author-side hygiene diagnostics over the whole model (missing summaries, undocumented members, drift, invalid defaults). */
|
|
344
|
-
function lintModel(index) {
|
|
345
|
-
return [
|
|
397
|
+
function lintModel(index, severities = DEFAULT_RULE_SEVERITIES) {
|
|
398
|
+
return applySeverities([
|
|
346
399
|
...record.model(index),
|
|
347
400
|
...modifier.model(index),
|
|
348
401
|
...part.model(index),
|
|
349
402
|
...customProperty.model(index)
|
|
350
|
-
];
|
|
403
|
+
], severities);
|
|
351
404
|
}
|
|
352
405
|
/** Consumer-side diagnostics for custom-property assignments (`--x: value` must match its `@property` syntax). */
|
|
353
|
-
function checkPropertyAssignments(assignments, index) {
|
|
354
|
-
return assignments.flatMap((a) => customProperty.assignment(a, index));
|
|
406
|
+
function checkPropertyAssignments(assignments, index, severities = DEFAULT_RULE_SEVERITIES) {
|
|
407
|
+
return applySeverities(assignments.flatMap((a) => customProperty.assignment(a, index)), severities);
|
|
355
408
|
}
|
|
356
409
|
/** Consumer-side diagnostics for class-attribute usage (unknown or deprecated modifiers). */
|
|
357
|
-
function checkClassUsage(usages, index) {
|
|
358
|
-
return usages.flatMap((usage) => modifier.classUsage(usage, index));
|
|
410
|
+
function checkClassUsage(usages, index, severities = DEFAULT_RULE_SEVERITIES) {
|
|
411
|
+
return applySeverities(usages.flatMap((usage) => modifier.classUsage(usage, index)), severities);
|
|
359
412
|
}
|
|
360
413
|
/** Consumer-side diagnostics for `var(--…)` references (unknown custom properties; opt-in via prefix). */
|
|
361
|
-
function checkPropertyUsage(usages, index, options = {}) {
|
|
362
|
-
return usages.flatMap((usage) => customProperty.propertyUsage(usage, index, options));
|
|
414
|
+
function checkPropertyUsage(usages, index, options = {}, severities = DEFAULT_RULE_SEVERITIES) {
|
|
415
|
+
return applySeverities(usages.flatMap((usage) => customProperty.propertyUsage(usage, index, options)), severities);
|
|
363
416
|
}
|
|
364
417
|
/** Completions for a class attribute: modifiers of `base` when given, else the component classes. */
|
|
365
418
|
function completeClasses(base, index) {
|
|
@@ -398,4 +451,4 @@ function definitionForFunction(name, index) {
|
|
|
398
451
|
return func.definition(name, index);
|
|
399
452
|
}
|
|
400
453
|
//#endregion
|
|
401
|
-
export { ASPECTS, checkClassUsage, checkPropertyAssignments, checkPropertyUsage, completeClasses, completeCustomProperties, completeFunctions, customProperty, definitionForClass, definitionForCustomProperty, definitionForFunction, func, hoverForClass, hoverForCustomProperty, hoverForFunction, lintModel, matchesSyntax, modifier, part, record };
|
|
454
|
+
export { ASPECTS, DEFAULT_RULE_SEVERITIES, checkClassUsage, checkPropertyAssignments, checkPropertyUsage, completeClasses, completeCustomProperties, completeFunctions, customProperty, definitionForClass, definitionForCustomProperty, definitionForFunction, func, hoverForClass, hoverForCustomProperty, hoverForFunction, lintModel, matchesSyntax, modifier, part, record, resolveRuleSeverities };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cssdoc/providers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Host-agnostic aspect providers over the @cssdoc/index — diagnostics, completions, hover, and definitions for modifiers, custom properties, structure, functions, states, and conditions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"css-tree": "^3.2.1",
|
|
32
|
-
"@cssdoc/core": "0.
|
|
33
|
-
"@cssdoc/index": "0.
|
|
32
|
+
"@cssdoc/core": "0.2.0",
|
|
33
|
+
"@cssdoc/index": "0.2.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/css-tree": "^2.3.11",
|