@cssdoc/config 0.6.1 → 0.7.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.
@@ -130,6 +130,25 @@
130
130
  "description": "How a /* … */ comment on a member's rule combines with its tag prose: append (default), prepend, replace, or ignore.",
131
131
  "enum": ["append", "prepend", "replace", "ignore"]
132
132
  },
133
+ "providers": {
134
+ "description": "Upstream cssdoc providers this config consumes, so their components resolve in this scope's lint/hover/docs. Each points at a provider's model.json or a source stylesheet.",
135
+ "type": "array",
136
+ "items": {
137
+ "type": "object",
138
+ "additionalProperties": false,
139
+ "required": ["path"],
140
+ "properties": {
141
+ "path": {
142
+ "type": "string",
143
+ "description": "Path to the provider's model.json or a source stylesheet — relative (starts with .) or a package specifier."
144
+ },
145
+ "baseHref": {
146
+ "type": "string",
147
+ "description": "URL prefix for links to the provider's rendered doc pages."
148
+ }
149
+ }
150
+ }
151
+ },
133
152
  "rules": {
134
153
  "description": "Per-rule severity overrides (off/warn/error).",
135
154
  "type": "object",
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { CssDocConfiguration, CssDocTagDefinition, InlineCommentMode, ModifierConventionInput } from "@cssdoc/core";
1
+ import { CssDocConfiguration, CssDocEntry, CssDocTagDefinition, InlineCommentMode, ModifierConventionInput } from "@cssdoc/core";
2
2
 
3
3
  //#region src/CssDocConfigFile.d.ts
4
4
  /** A per-rule severity override, as spelled in `cssdoc.json`. */
@@ -20,6 +20,16 @@ interface RenderConfig {
20
20
  /** Which Structure representation(s) to emit: `"text"`, `"diagram"`, or `"both"` (default). */
21
21
  structureView?: "text" | "diagram" | "both";
22
22
  }
23
+ /**
24
+ * An upstream cssdoc provider this config consumes. `path` points at the provider's published model
25
+ * (`model.json`, the JSON emitter's output) or a source stylesheet (`.css`/`.scss`/…) — resolved
26
+ * relative to this file for `.`-paths, else via Node resolution (so a package specifier works).
27
+ * `baseHref` prefixes links to the provider's rendered doc pages (`<baseHref><name>.md`).
28
+ */
29
+ interface ProviderRef {
30
+ path: string;
31
+ baseHref?: string;
32
+ }
23
33
  /**
24
34
  * The conventional file names loaders look for, in preference order. Both are parsed the same way
25
35
  * (JSON with comments); `.jsonc` just makes the comments explicit.
@@ -47,6 +57,11 @@ declare class CssDocConfigFile {
47
57
  readonly modifierConvention?: ModifierConventionInput;
48
58
  /** How inline `/* … *\/` comments combine with tag prose, if declared by this file. */
49
59
  readonly inlineComments?: InlineCommentMode;
60
+ /**
61
+ * Upstream cssdoc providers this file consumes (this file's own — NOT inherited via `extends`, which
62
+ * carries configuration, not components). Resolve with {@link resolveProviders}.
63
+ */
64
+ readonly providers: readonly ProviderRef[];
50
65
  /**
51
66
  * The per-rule severity overrides, merged across the `extends` chain (this file wins). Not the
52
67
  * resolved severities — pass these to `resolveRuleSeverities` in `@cssdoc/providers`.
@@ -104,6 +119,23 @@ declare class CssDocConfigFile {
104
119
  private static _loadFile;
105
120
  }
106
121
  //#endregion
122
+ //#region src/providers.d.ts
123
+ /** The upstream components a config consumes, plus a resolver for links to their rendered pages. */
124
+ interface ResolvedProviders {
125
+ /** Every component/record the declared providers document. */
126
+ entries: CssDocEntry[];
127
+ /** The doc-page URL for a class, from the owning provider's `baseHref` (`undefined` if none). */
128
+ href: (className: string) => string | undefined;
129
+ /** Resolution problems (missing file, parse/JSON error), one per provider that failed. */
130
+ messages: string[];
131
+ }
132
+ /**
133
+ * Resolve every provider a config declares. `.json` paths load a published model; other paths are
134
+ * parsed as stylesheets. Paths starting with `.` resolve relative to the config file; the rest go
135
+ * through Node resolution (so a package specifier works), mirroring `extends`.
136
+ */
137
+ declare function resolveProviders(configFile: CssDocConfigFile): ResolvedProviders;
138
+ //#endregion
107
139
  //#region src/schema.d.ts
108
140
  /**
109
141
  * The JSON Schema for a `cssdoc.json` file — the single source of truth used to validate config files
@@ -236,6 +268,25 @@ declare const cssDocSchema: {
236
268
  readonly description: "How a /* … */ comment on a member's rule combines with its tag prose: append (default), prepend, replace, or ignore.";
237
269
  readonly enum: readonly ["append", "prepend", "replace", "ignore"];
238
270
  };
271
+ readonly providers: {
272
+ readonly description: "Upstream cssdoc providers this config consumes, so their components resolve in this scope's lint/hover/docs. Each points at a provider's model.json or a source stylesheet.";
273
+ readonly type: "array";
274
+ readonly items: {
275
+ readonly type: "object";
276
+ readonly additionalProperties: false;
277
+ readonly required: readonly ["path"];
278
+ readonly properties: {
279
+ readonly path: {
280
+ readonly type: "string";
281
+ readonly description: "Path to the provider's model.json or a source stylesheet — relative (starts with .) or a package specifier.";
282
+ };
283
+ readonly baseHref: {
284
+ readonly type: "string";
285
+ readonly description: "URL prefix for links to the provider's rendered doc pages.";
286
+ };
287
+ };
288
+ };
289
+ };
239
290
  readonly rules: {
240
291
  readonly description: "Per-rule severity overrides (off/warn/error).";
241
292
  readonly type: "object";
@@ -292,4 +343,4 @@ declare const cssDocSchema: {
292
343
  };
293
344
  };
294
345
  //#endregion
295
- export { CSSDOC_CONFIG_FILENAME, CSSDOC_CONFIG_FILENAMES, CssDocConfigFile, cssDocSchema };
346
+ export { CSSDOC_CONFIG_FILENAME, CSSDOC_CONFIG_FILENAMES, CssDocConfigFile, type ProviderRef, type ResolvedProviders, cssDocSchema, resolveProviders };
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ import { existsSync, readFileSync } from "node:fs";
3
3
  import { dirname, parse, resolve } from "node:path";
4
4
  import { Ajv } from "ajv";
5
5
  import { parse as parse$1, printParseErrorCode } from "jsonc-parser";
6
- import { CssDocConfiguration, CssDocTagDefinition } from "@cssdoc/core";
6
+ import { CssDocConfiguration, CssDocTagDefinition, parseCssDocs } from "@cssdoc/core";
7
7
  //#region src/schema.ts
8
8
  /**
9
9
  * The JSON Schema for a `cssdoc.json` file — the single source of truth used to validate config files
@@ -121,6 +121,25 @@ const cssDocSchema = {
121
121
  "ignore"
122
122
  ]
123
123
  },
124
+ providers: {
125
+ description: "Upstream cssdoc providers this config consumes, so their components resolve in this scope's lint/hover/docs. Each points at a provider's model.json or a source stylesheet.",
126
+ type: "array",
127
+ items: {
128
+ type: "object",
129
+ additionalProperties: false,
130
+ required: ["path"],
131
+ properties: {
132
+ path: {
133
+ type: "string",
134
+ description: "Path to the provider's model.json or a source stylesheet — relative (starts with .) or a package specifier."
135
+ },
136
+ baseHref: {
137
+ type: "string",
138
+ description: "URL prefix for links to the provider's rendered doc pages."
139
+ }
140
+ }
141
+ }
142
+ },
124
143
  rules: {
125
144
  description: "Per-rule severity overrides (off/warn/error).",
126
145
  type: "object",
@@ -234,6 +253,11 @@ var CssDocConfigFile = class CssDocConfigFile {
234
253
  /** How inline `/* … *\/` comments combine with tag prose, if declared by this file. */
235
254
  inlineComments;
236
255
  /**
256
+ * Upstream cssdoc providers this file consumes (this file's own — NOT inherited via `extends`, which
257
+ * carries configuration, not components). Resolve with {@link resolveProviders}.
258
+ */
259
+ providers;
260
+ /**
237
261
  * The per-rule severity overrides, merged across the `extends` chain (this file wins). Not the
238
262
  * resolved severities — pass these to `resolveRuleSeverities` in `@cssdoc/providers`.
239
263
  */
@@ -264,6 +288,7 @@ var CssDocConfigFile = class CssDocConfigFile {
264
288
  this.extendsFiles = init.extendsFiles;
265
289
  this.modifierConvention = init.modifierConvention;
266
290
  this.inlineComments = init.inlineComments;
291
+ this.providers = init.providers;
267
292
  const severities = {};
268
293
  const naming = {};
269
294
  const render = {};
@@ -353,6 +378,7 @@ var CssDocConfigFile = class CssDocConfigFile {
353
378
  tagDefinitions: [],
354
379
  supportForTags: /* @__PURE__ */ new Map(),
355
380
  extendsFiles: [],
381
+ providers: [],
356
382
  rules: {},
357
383
  naming: {},
358
384
  structureIgnore: [],
@@ -369,6 +395,7 @@ var CssDocConfigFile = class CssDocConfigFile {
369
395
  tagDefinitions: [],
370
396
  supportForTags: /* @__PURE__ */ new Map(),
371
397
  extendsFiles: [],
398
+ providers: [],
372
399
  rules: {},
373
400
  naming: {},
374
401
  structureIgnore: [],
@@ -419,6 +446,7 @@ var CssDocConfigFile = class CssDocConfigFile {
419
446
  extendsFiles,
420
447
  modifierConvention: raw.modifierConvention,
421
448
  inlineComments: raw.inlineComments,
449
+ providers: raw.providers ?? [],
422
450
  rules: raw.rules ?? {},
423
451
  naming: raw.naming ?? {},
424
452
  structureIgnore: raw.structureIgnore ?? [],
@@ -427,4 +455,72 @@ var CssDocConfigFile = class CssDocConfigFile {
427
455
  }
428
456
  };
429
457
  //#endregion
430
- export { CSSDOC_CONFIG_FILENAME, CSSDOC_CONFIG_FILENAMES, CssDocConfigFile, cssDocSchema };
458
+ //#region src/providers.ts
459
+ /**
460
+ * Resolve the upstream cssdoc **providers** a `cssdoc.json` declares (its `providers` field) into a flat
461
+ * set of {@link CssDocEntry} plus a cross-link resolver. This is how a consumer scope learns another
462
+ * provider's documented components — so the consumer's lint, hover, and docs recognize (and link to)
463
+ * vendor classes it composes, without a `structureIgnore` escape hatch.
464
+ *
465
+ * A provider is consumed via its published model (`model.json`, the JSON emitter's `CssDocEntry[]`
466
+ * output) or a source stylesheet parsed on the spot with the provider's own convention. `extends`
467
+ * carries configuration; `providers` carries components — the two are orthogonal.
468
+ *
469
+ * @module
470
+ */
471
+ const stripDot = (name) => name.replace(/^\./u, "");
472
+ /** Read a provider's `model.json` — a `CssDocEntry[]` or a `{ entries }` manifest wrapper. */
473
+ function loadModel(file) {
474
+ const data = JSON.parse(readFileSync(file, "utf8"));
475
+ if (Array.isArray(data)) return data;
476
+ if (data && typeof data === "object" && Array.isArray(data.entries)) return data.entries;
477
+ throw new Error("expected a CssDocEntry[] or a { entries } manifest");
478
+ }
479
+ /** Parse a provider source stylesheet with its own governing `cssdoc.json` convention. */
480
+ function loadStylesheet(file) {
481
+ const configuration = CssDocConfigFile.loadForFolder(dirname(file)).toConfiguration();
482
+ return parseCssDocs(readFileSync(file, "utf8"), {
483
+ configuration,
484
+ fileName: file
485
+ });
486
+ }
487
+ /**
488
+ * Resolve every provider a config declares. `.json` paths load a published model; other paths are
489
+ * parsed as stylesheets. Paths starting with `.` resolve relative to the config file; the rest go
490
+ * through Node resolution (so a package specifier works), mirroring `extends`.
491
+ */
492
+ function resolveProviders(configFile) {
493
+ const entries = [];
494
+ const messages = [];
495
+ const hrefByClass = /* @__PURE__ */ new Map();
496
+ const requireFrom = createRequire(configFile.filePath);
497
+ const from = dirname(configFile.filePath);
498
+ for (const provider of configFile.providers) {
499
+ let resolved;
500
+ try {
501
+ resolved = provider.path.startsWith(".") ? resolve(from, provider.path) : requireFrom.resolve(provider.path);
502
+ } catch (error) {
503
+ messages.push(`Cannot resolve provider "${provider.path}": ${error.message}`);
504
+ continue;
505
+ }
506
+ let loaded;
507
+ try {
508
+ loaded = resolved.endsWith(".json") ? loadModel(resolved) : loadStylesheet(resolved);
509
+ } catch (error) {
510
+ messages.push(`Cannot load provider "${provider.path}": ${error.message}`);
511
+ continue;
512
+ }
513
+ const base = provider.baseHref?.replace(/\/?$/u, "/");
514
+ for (const entry of loaded) {
515
+ entries.push(entry);
516
+ if (base && entry.className) hrefByClass.set(stripDot(entry.className), `${base}${entry.name}.md`);
517
+ }
518
+ }
519
+ return {
520
+ entries,
521
+ messages,
522
+ href: (className) => hrefByClass.get(stripDot(className))
523
+ };
524
+ }
525
+ //#endregion
526
+ export { CSSDOC_CONFIG_FILENAME, CSSDOC_CONFIG_FILENAMES, CssDocConfigFile, cssDocSchema, resolveProviders };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cssdoc/config",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Load a cssdoc.json configuration file (custom tags, extends) into an @cssdoc/core CssDocConfiguration — TSDoc-config, for CSS.",
5
5
  "keywords": [
6
6
  "config",
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "ajv": "^8.20.0",
34
34
  "jsonc-parser": "^3.3.1",
35
- "@cssdoc/core": "0.6.1"
35
+ "@cssdoc/core": "0.7.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^24.13.3",