onsystem 0.5.0 → 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/README.md +21 -4
- package/dist/cli.js +302 -33
- package/dist/{types-DJtccu3A.d.ts → config-lbfW91qB.d.ts} +263 -167
- package/dist/{design-system-CnEv5sIL.js → design-system-A3pRX3Ka.js} +2861 -414
- package/dist/eslint-worker.d.ts +1 -1
- package/dist/eslint-worker.js +9 -2
- package/dist/eslint.js +1 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +3 -3
- package/dist/{stdio-DjfkiDMV.js → stdio-CEChNFLR.js} +21 -24
- package/dist/{workspace-DzWQ4L8R.js → workspace-CHvUwgz9.js} +44 -10
- package/package.json +3 -2
- package/schema.json +19 -1
package/dist/eslint-worker.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as DesignSystemModel, i as ResolvedConfig } from "./config-lbfW91qB.js";
|
|
2
2
|
import { MessagePort } from "node:worker_threads";
|
|
3
3
|
//#region src/eslint/worker.d.ts
|
|
4
4
|
export interface LoadRequest {
|
package/dist/eslint-worker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as loadTarget } from "./workspace-
|
|
1
|
+
import { H as DEFAULT_TEST_EXCLUDE, U as DEFAULT_TEST_FOLDERS, _t as relativePath, gt as matchesGlob, i as componentFiles, r as buildModel } from "./design-system-A3pRX3Ka.js";
|
|
2
|
+
import { r as loadTarget } from "./workspace-CHvUwgz9.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { parentPort } from "node:worker_threads";
|
|
@@ -9,6 +9,8 @@ import { parentPort } from "node:worker_threads";
|
|
|
9
9
|
* project's design system does not (config files written in code, globs, the extraction
|
|
10
10
|
* cache), so the plugin asks this worker and waits for the answer (see `bridge.ts`).
|
|
11
11
|
*/
|
|
12
|
+
/** What the configs said (a design-system package's skipped, or its paths ignored), each said once. */
|
|
13
|
+
const warned = /* @__PURE__ */ new Set();
|
|
12
14
|
/** How long a loaded design system is trusted before its files are looked at again. */
|
|
13
15
|
const FRESH_MS = 2e3;
|
|
14
16
|
const targets = /* @__PURE__ */ new Map();
|
|
@@ -44,6 +46,11 @@ async function targetFor({ cwd, root, config }) {
|
|
|
44
46
|
async function load(request) {
|
|
45
47
|
const target = await targetFor(request);
|
|
46
48
|
const config = target.workspace ? (await target.workspace.projectFor(request.file)).config : target.config;
|
|
49
|
+
for (const text of config.warnings ?? []) {
|
|
50
|
+
if (warned.has(text)) continue;
|
|
51
|
+
warned.add(text);
|
|
52
|
+
process.stderr.write(`onsystem: ${text}\n`);
|
|
53
|
+
}
|
|
47
54
|
let project = projects.get(config.root);
|
|
48
55
|
if (!project || Date.now() - project.at >= FRESH_MS) {
|
|
49
56
|
const { model, key } = await buildModel(config, { cache: true });
|
package/dist/eslint.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H as DEFAULT_TEST_EXCLUDE, T as RULES, U as DEFAULT_TEST_FOLDERS, V as DEFAULT_SEVERITY, _ as VERSION, _t as relativePath, g as NAME, t as DesignSystem } from "./design-system-A3pRX3Ka.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { MessageChannel, Worker, receiveMessageOnPort } from "node:worker_threads";
|
|
4
4
|
//#region src/eslint/bridge.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as TOKEN_CATEGORIES, D as VariantInfo, E as TokenCategory, O as ImportMapping, S as SourceLocation, T as Token, _ as DocSection, a as ResolvedRule, b as PropInfo, c as configJsonSchema, d as CheckResult, f as ComponentDocs, g as Diagnostic, h as DesignSystemModel, i as ResolvedConfig, l as defineConfig, m as CompoundVariantInfo, n as LoadConfigOptions, o as RuleId, p as ComponentInfo, r as RULE_IDS, s as RuleOptions, t as Config, u as loadConfig, v as ExampleInfo, w as TextEdit, x as Severity, y as InheritedProps } from "./config-lbfW91qB.js";
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
import { Oklch } from "culori";
|
|
4
4
|
import { McpServer, Transport } from "@modelcontextprotocol/server";
|
|
@@ -115,6 +115,12 @@ export declare function parseCssTokens(css: string, file: string): {
|
|
|
115
115
|
warnings: string[];
|
|
116
116
|
};
|
|
117
117
|
//#endregion
|
|
118
|
+
//#region src/tokens/design-md.d.ts
|
|
119
|
+
export declare function parseDesignMd(text: string, file: string): {
|
|
120
|
+
tokens: Token[];
|
|
121
|
+
warnings: string[];
|
|
122
|
+
};
|
|
123
|
+
//#endregion
|
|
118
124
|
//#region src/tokens/dtcg.d.ts
|
|
119
125
|
interface DtcgOptions {
|
|
120
126
|
/** Prefix for generated custom property names: `ds` → `--ds-color-primary`. */
|
|
@@ -125,6 +131,34 @@ export declare function parseDtcgTokens(text: string, file: string, options?: Dt
|
|
|
125
131
|
warnings: string[];
|
|
126
132
|
};
|
|
127
133
|
//#endregion
|
|
134
|
+
//#region src/tokens/export.d.ts
|
|
135
|
+
/**
|
|
136
|
+
* Writes the tokens onsystem found as a DTCG 2025.10 file or a DESIGN.md. Both are grouped by
|
|
137
|
+
* category; reading the DTCG file back gives the same tokens, with the same names.
|
|
138
|
+
*/
|
|
139
|
+
interface Exported {
|
|
140
|
+
text: string;
|
|
141
|
+
/** How many tokens were written. */
|
|
142
|
+
count: number;
|
|
143
|
+
/** Tokens left out, and why. */
|
|
144
|
+
warnings: string[];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The tokens as a DTCG 2025.10 file: a group per category, colors as color objects in their
|
|
148
|
+
* own color space, lengths as `{ value, unit }`, aliases as references, and what DTCG has no
|
|
149
|
+
* field for (the token's name, the custom property, the Tailwind theme variable, dark and
|
|
150
|
+
* other modes) under `$extensions["com.github.dgesteves.onsystem"]`.
|
|
151
|
+
*/
|
|
152
|
+
export declare function toDtcg(tokens: readonly Token[]): Exported;
|
|
153
|
+
/**
|
|
154
|
+
* The tokens as a DESIGN.md: front matter with the colors, typography, rounded corners and
|
|
155
|
+
* spacing in the spec's schema, then a heading per category with a table of its tokens, their
|
|
156
|
+
* values in each mode and how code uses them.
|
|
157
|
+
*/
|
|
158
|
+
export declare function toDesignMd(tokens: readonly Token[], options: {
|
|
159
|
+
name: string;
|
|
160
|
+
}): Exported;
|
|
161
|
+
//#endregion
|
|
128
162
|
//#region src/tokens/index.d.ts
|
|
129
163
|
interface TokenSource {
|
|
130
164
|
file: string;
|
|
@@ -261,6 +295,8 @@ declare class LintTarget {
|
|
|
261
295
|
private readonly moduleDirs;
|
|
262
296
|
/** The files extraction read, when the model says. */
|
|
263
297
|
private readonly sources?;
|
|
298
|
+
/** Published libraries the model read from type declarations: `@mui/material`. */
|
|
299
|
+
readonly libraries: Set<string>;
|
|
264
300
|
/**
|
|
265
301
|
* `resolver` finds the module an import points at and what it exports
|
|
266
302
|
* (`@calcom/ui/components/icon` → `components/icon/index.ts`), so a name from
|
|
@@ -316,6 +352,10 @@ declare class LintTarget {
|
|
|
316
352
|
/** The component a module exports as `default`, for `import Anything from "..."`. */
|
|
317
353
|
defaultExport(specifier: string, fromFile?: string): ComponentInfo | undefined;
|
|
318
354
|
private resolveRelative;
|
|
355
|
+
/** The library an import specifier points into (`@mui/material/Button`), if any. */
|
|
356
|
+
libraryOf(specifier: string): string | undefined;
|
|
357
|
+
/** The library's own component of that name: `Button` from `@mui/material`, not a wrapper. */
|
|
358
|
+
libraryComponent(name: string, library: string): ComponentInfo | undefined;
|
|
319
359
|
/** Component names for "did you mean" suggestions. */
|
|
320
360
|
names(): string[];
|
|
321
361
|
}
|
|
@@ -480,6 +520,12 @@ export declare class DesignSystem {
|
|
|
480
520
|
readonly config: ResolvedConfig;
|
|
481
521
|
readonly lint: LintTarget;
|
|
482
522
|
private readonly searchIndex;
|
|
523
|
+
/**
|
|
524
|
+
* The components the tools offer: all of them, except a library's (MUI's) where the project
|
|
525
|
+
* has its own of that name, a wrapper the team means to be used. The rules still check code
|
|
526
|
+
* that imports the library's directly against the library's.
|
|
527
|
+
*/
|
|
528
|
+
private readonly offered;
|
|
483
529
|
constructor(model: DesignSystemModel, config: ResolvedConfig);
|
|
484
530
|
get root(): string;
|
|
485
531
|
get components(): ComponentInfo[];
|
|
@@ -498,6 +544,14 @@ export declare class DesignSystem {
|
|
|
498
544
|
}): Token[];
|
|
499
545
|
/** Tokens a component's classes and CSS variables reference, e.g. `bg-primary` → `primary`. */
|
|
500
546
|
relatedTokens(component: ComponentInfo): Token[];
|
|
547
|
+
/**
|
|
548
|
+
* Whether `check --require-design-system` (and the GitHub Action, where it is on by default)
|
|
549
|
+
* finds a design system to check against: components and color tokens, or components from a
|
|
550
|
+
* published library (MUI). A library is the design system whatever its theme: when the theme's
|
|
551
|
+
* colors cannot be read (a palette from Sass variables), the check still runs and `notice()`
|
|
552
|
+
* says that no-hardcoded-color did not.
|
|
553
|
+
*/
|
|
554
|
+
hasDesignSystem(): boolean;
|
|
501
555
|
/**
|
|
502
556
|
* What the rules could not check, when it matters: without components the
|
|
503
557
|
* component rules find nothing, and without color tokens neither does
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { n as INSTRUCTIONS, r as createServer, t as serveStdio } from "./stdio-
|
|
3
|
-
export { DesignSystem, DesignSystemHost, INSTRUCTIONS, RULES, RULE_IDS, TokenIndex, VERSION, applyFixes, attachDocs, buildModel, checkSource, configJsonSchema, createServer, defineConfig, extractComponents, findVariantDefinitions, fingerprint, formatDiagnostics, loadConfig, loadDesignSystem, loadTokens, mergeTokens, parseCssTokens, parseDoc, parseDtcgTokens, searchComponents, serveStdio };
|
|
1
|
+
import { $ as findVariantDefinitions, A as toDtcg, D as loadTokens, E as TokenIndex, F as attachDocs, G as RULE_IDS, I as parseDoc, K as configJsonSchema, L as extractComponents, M as parseDtcgTokens, N as parseDesignMd, O as mergeTokens, P as parseCssTokens, T as RULES, Y as loadConfig, _ as VERSION, a as fingerprint, d as searchComponents, f as applyFixes, h as formatDiagnostics, k as toDesignMd, n as DesignSystemHost, o as loadDesignSystem, p as checkSource, q as defineConfig, r as buildModel, t as DesignSystem } from "./design-system-A3pRX3Ka.js";
|
|
2
|
+
import { n as INSTRUCTIONS, r as createServer, t as serveStdio } from "./stdio-CEChNFLR.js";
|
|
3
|
+
export { DesignSystem, DesignSystemHost, INSTRUCTIONS, RULES, RULE_IDS, TokenIndex, VERSION, applyFixes, attachDocs, buildModel, checkSource, configJsonSchema, createServer, defineConfig, extractComponents, findVariantDefinitions, fingerprint, formatDiagnostics, loadConfig, loadDesignSystem, loadTokens, mergeTokens, parseCssTokens, parseDesignMd, parseDoc, parseDtcgTokens, searchComponents, serveStdio, toDesignMd, toDtcg };
|
|
@@ -1,26 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as hasProjectMarker, r as loadTarget, t as findProjectRoot } from "./workspace-
|
|
1
|
+
import { Q as formatPx, R as CONFIG_FILES, W as LEGACY_CONFIG_FILES, Y as loadConfig, _ as VERSION, _t as relativePath, d as searchComponents, dt as closest, ft as plural, g as NAME, ht as isInside, j as TOKEN_CATEGORIES, m as uncheckedNotice, mt as unique, n as DesignSystemHost, pt as truncate, u as buildSearchIndex } from "./design-system-A3pRX3Ka.js";
|
|
2
|
+
import { n as hasProjectMarker, r as loadTarget, t as findProjectRoot } from "./workspace-CHvUwgz9.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import * as z from "zod";
|
|
7
|
-
import
|
|
7
|
+
import fsp from "node:fs/promises";
|
|
8
8
|
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/server";
|
|
9
9
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
10
|
-
//#region src/types.ts
|
|
11
|
-
/**
|
|
12
|
-
* The design-system model the server exposes. Everything here is plain JSON so
|
|
13
|
-
* it can be cached on disk and returned as MCP structured content.
|
|
14
|
-
*/
|
|
15
|
-
const TOKEN_CATEGORIES = [
|
|
16
|
-
"color",
|
|
17
|
-
"spacing",
|
|
18
|
-
"radius",
|
|
19
|
-
"typography",
|
|
20
|
-
"shadow",
|
|
21
|
-
"other"
|
|
22
|
-
];
|
|
23
|
-
//#endregion
|
|
24
10
|
//#region src/server/render.ts
|
|
25
11
|
/**
|
|
26
12
|
* Tool results are read by models, so they are rendered as compact Markdown:
|
|
@@ -44,15 +30,21 @@ function renderComponentList(ds, project) {
|
|
|
44
30
|
if (!roots.length) return `No components found${project ? ` in ${project}` : ""}. Check the "components" globs in the config (root: ${ds.root}).`;
|
|
45
31
|
const parts = ds.components.length - roots.length;
|
|
46
32
|
const lines = [`${plural(roots.length, "component")}${parts ? ` (+${plural(parts, "part")})` : ""}${project ? ` in ${project}` : ""}. Call get_component before using one.`, ""];
|
|
47
|
-
|
|
33
|
+
const own = roots.filter((c) => !c.library);
|
|
34
|
+
for (const component of own) lines.push(...listItem(component));
|
|
35
|
+
for (const library of new Set(roots.flatMap((c) => c.library ? [c.library] : []))) {
|
|
36
|
+
if (own.length) lines.push("");
|
|
37
|
+
lines.push(`From ${library} (import { Name } from "${library}"):`, "");
|
|
38
|
+
for (const component of roots.filter((c) => c.library === library)) lines.push(...listItem(component, "", false));
|
|
39
|
+
}
|
|
48
40
|
return lines.join("\n");
|
|
49
41
|
}
|
|
50
|
-
function listItem(component, note = "") {
|
|
42
|
+
function listItem(component, note = "", withImport = true) {
|
|
51
43
|
const element = component.element ? ` <${component.element}>` : "";
|
|
52
44
|
const lines = [`${component.name}${element}${note} — ${firstSentence(component.description) || "No description."}`];
|
|
53
45
|
for (const variant of variantSummary(component)) lines.push(` ${variant}`);
|
|
54
46
|
if (component.subcomponents.length) lines.push(` parts: ${component.subcomponents.join(", ")}`);
|
|
55
|
-
lines.push(` ${importStatement(component)}`);
|
|
47
|
+
if (withImport) lines.push(` ${importStatement(component)}`);
|
|
56
48
|
return lines;
|
|
57
49
|
}
|
|
58
50
|
/** `apps/web`, `apps/web and packages/ui`, `a, b, c and 4 more`. */
|
|
@@ -191,6 +183,10 @@ function renderComponent(ds, component, origin) {
|
|
|
191
183
|
if (component.variants.length) {
|
|
192
184
|
lines.push("", "## Variants");
|
|
193
185
|
for (const variant of component.variants) {
|
|
186
|
+
if (!Object.values(variant.classes).some(Boolean)) {
|
|
187
|
+
lines.push(`${variant.name}: ${variant.values.join(" | ")}${variant.default ? ` (default "${variant.default}")` : ""}`);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
194
190
|
lines.push(`${variant.name}${variant.default ? ` (default "${variant.default}")` : ""}`);
|
|
195
191
|
const width = Math.max(...variant.values.map((v) => v.length));
|
|
196
192
|
for (const value of variant.values) lines.push(` ${value.padEnd(width)} ${variant.classes[value] ?? ""}`.trimEnd());
|
|
@@ -848,16 +844,16 @@ function createServer({ getDesignSystem, getProjects }) {
|
|
|
848
844
|
const outside = errorResult(`${filePath} is outside the project root (${base}).`);
|
|
849
845
|
if (!isInside(base, absolute)) return outside;
|
|
850
846
|
try {
|
|
851
|
-
const [root, real] = await Promise.all([
|
|
847
|
+
const [root, real] = await Promise.all([fsp.realpath(base), fsp.realpath(absolute)]);
|
|
852
848
|
if (!isInside(root, real)) return outside;
|
|
853
|
-
if ((await
|
|
849
|
+
if ((await fsp.stat(real)).size > MAX_CODE) return {
|
|
854
850
|
isError: true,
|
|
855
851
|
content: [{
|
|
856
852
|
type: "text",
|
|
857
853
|
text: `${filePath} is too large to check.`
|
|
858
854
|
}]
|
|
859
855
|
};
|
|
860
|
-
source = await
|
|
856
|
+
source = await fsp.readFile(real, "utf8");
|
|
861
857
|
} catch {
|
|
862
858
|
return {
|
|
863
859
|
isError: true,
|
|
@@ -1035,7 +1031,7 @@ var Catalog = class {
|
|
|
1035
1031
|
byKey.set(key, {
|
|
1036
1032
|
component: rebase(component, root, file),
|
|
1037
1033
|
ds,
|
|
1038
|
-
package: owner(file),
|
|
1034
|
+
package: component.library ?? owner(file),
|
|
1039
1035
|
projects: [dir],
|
|
1040
1036
|
ambiguous: false
|
|
1041
1037
|
});
|
|
@@ -1265,6 +1261,7 @@ function serveStdio$1(options) {
|
|
|
1265
1261
|
};
|
|
1266
1262
|
const { config, workspace } = await loadTarget(configOptions);
|
|
1267
1263
|
for (const text of config.deprecations ?? []) logger.warn(text);
|
|
1264
|
+
for (const text of (workspace ? workspace.warnings : config.warnings) ?? []) logger.warn(text);
|
|
1268
1265
|
if (workspace) {
|
|
1269
1266
|
const projects = new WorkspaceProjects(workspace, {
|
|
1270
1267
|
cache: options.cache,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { J as hasOwnConfig, R as CONFIG_FILES, W as LEGACY_CONFIG_FILES, X as loadConfigWith, Y as loadConfig, _t as relativePath, ct as isWorkspaceRoot, ht as isInside, i as componentFiles, lt as workspacePackageDirs, ot as findDesignSystemPackage, rt as PackageFinder, ut as workspacePatterns } from "./design-system-A3pRX3Ka.js";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import os from "node:os";
|
|
@@ -18,7 +18,8 @@ const PROJECT_MARKERS = [
|
|
|
18
18
|
];
|
|
19
19
|
/**
|
|
20
20
|
* A monorepo seen from its root: every workspace package with a design system (an app
|
|
21
|
-
* that uses one, or
|
|
21
|
+
* that uses one, from source or a published library, or the design-system package
|
|
22
|
+
* itself), and how to find the project of
|
|
22
23
|
* any file in it. Without a design system at the root, `check`, `inspect` and the MCP
|
|
23
24
|
* server work from here, each file checked by its own project's design system.
|
|
24
25
|
*/
|
|
@@ -30,8 +31,9 @@ var Workspace = class {
|
|
|
30
31
|
configFile;
|
|
31
32
|
options;
|
|
32
33
|
rootConfig;
|
|
34
|
+
otherConfigs;
|
|
33
35
|
bare = /* @__PURE__ */ new Map();
|
|
34
|
-
constructor(root, source, projects, others, configFile, options, rootConfig) {
|
|
36
|
+
constructor(root, source, projects, others, configFile, options, rootConfig, otherConfigs = []) {
|
|
35
37
|
this.root = root;
|
|
36
38
|
this.source = source;
|
|
37
39
|
this.projects = projects;
|
|
@@ -39,6 +41,19 @@ var Workspace = class {
|
|
|
39
41
|
this.configFile = configFile;
|
|
40
42
|
this.options = options;
|
|
41
43
|
this.rootConfig = rootConfig;
|
|
44
|
+
this.otherConfigs = otherConfigs;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* What the configs of the workspace's packages have to say ({@link ResolvedConfig.warnings}),
|
|
48
|
+
* each once, as they were read when the workspace was found.
|
|
49
|
+
*/
|
|
50
|
+
get warnings() {
|
|
51
|
+
const configs = [
|
|
52
|
+
this.rootConfig,
|
|
53
|
+
...this.projects.map((p) => p.config),
|
|
54
|
+
...this.otherConfigs
|
|
55
|
+
];
|
|
56
|
+
return [...new Set(configs.flatMap((c) => c.warnings ?? []))];
|
|
42
57
|
}
|
|
43
58
|
/**
|
|
44
59
|
* The project `target` (a file or a folder) belongs to: the nearest folder at or above
|
|
@@ -102,24 +117,31 @@ async function discoverWorkspace(rootConfig, options) {
|
|
|
102
117
|
].filter(Boolean).join(", ");
|
|
103
118
|
const projects = [];
|
|
104
119
|
const others = [];
|
|
120
|
+
const otherConfigs = [];
|
|
105
121
|
for (const dir of workspacePackageDirs(root)) {
|
|
106
122
|
const config = await loadProjectConfig(dir, root, rootConfig.configFile, options);
|
|
107
123
|
const files = (await componentFiles(config)).length;
|
|
108
124
|
const own = config.configFile !== void 0 && config.configFile !== rootConfig.configFile;
|
|
109
|
-
|
|
125
|
+
const library = config.libraries?.some((l) => l.dir !== void 0) ?? false;
|
|
126
|
+
if (files || own || library) projects.push({
|
|
110
127
|
root: dir,
|
|
111
128
|
dir: relativePath(root, dir),
|
|
112
129
|
name: packageName(dir),
|
|
113
130
|
config,
|
|
114
131
|
componentFiles: files
|
|
115
132
|
});
|
|
116
|
-
else
|
|
133
|
+
else {
|
|
134
|
+
others.push(relativePath(root, dir));
|
|
135
|
+
if (config.warnings) otherConfigs.push(config);
|
|
136
|
+
}
|
|
117
137
|
}
|
|
118
|
-
return new Workspace(root, source, projects, others, rootConfig.configFile, options, rootConfig);
|
|
138
|
+
return new Workspace(root, source, projects, others, rootConfig.configFile, options, rootConfig, otherConfigs);
|
|
119
139
|
}
|
|
120
140
|
/**
|
|
121
|
-
* A project's config: its own config file,
|
|
122
|
-
*
|
|
141
|
+
* A project's config: its own config file, else the config its design-system package declares
|
|
142
|
+
* (a dependency with `"onsystem"` in its package.json), else the workspace root's, with paths
|
|
143
|
+
* relative to the workspace root, else zero config. `loadConfig` from the project's folder finds
|
|
144
|
+
* the first two the same way. CLI flags that apply to every project carry over.
|
|
123
145
|
*/
|
|
124
146
|
function loadProjectConfig(dir, workspaceRoot, rootConfigFile, options) {
|
|
125
147
|
const shared = {
|
|
@@ -127,15 +149,27 @@ function loadProjectConfig(dir, workspaceRoot, rootConfigFile, options) {
|
|
|
127
149
|
includeDesignSystem: options.includeDesignSystem,
|
|
128
150
|
jsonConfigOnly: options.jsonConfigOnly
|
|
129
151
|
};
|
|
130
|
-
|
|
152
|
+
const packages = new PackageFinder(dir);
|
|
153
|
+
if (!rootConfigFile || hasOwnConfig(dir)) return loadConfigWith({
|
|
154
|
+
...shared,
|
|
155
|
+
root: dir
|
|
156
|
+
}, { packages });
|
|
157
|
+
const lookup = findDesignSystemPackage(dir, packages);
|
|
158
|
+
if (lookup?.found || lookup?.problems.length) return loadConfigWith({
|
|
131
159
|
...shared,
|
|
132
160
|
root: dir
|
|
161
|
+
}, {
|
|
162
|
+
packages,
|
|
163
|
+
lookup
|
|
133
164
|
});
|
|
134
|
-
return
|
|
165
|
+
return loadConfigWith({
|
|
135
166
|
...shared,
|
|
136
167
|
root: dir,
|
|
137
168
|
config: rootConfigFile,
|
|
138
169
|
base: workspaceRoot
|
|
170
|
+
}, {
|
|
171
|
+
packages,
|
|
172
|
+
lookup
|
|
139
173
|
});
|
|
140
174
|
}
|
|
141
175
|
/** The nearest folder at or above `target` (a file or folder) with a project marker, up to `root`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onsystem",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"mcpName": "io.github.dgesteves/onsystem",
|
|
5
5
|
"description": "Keeps coding agents on your design system: it knows your real components, props, variants and tokens, catches the moment an agent invents one and has it fix it, and the same check gates your PRs. Local, zero config, works alongside @shadcn/lint.",
|
|
6
6
|
"keywords": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"mcp",
|
|
26
26
|
"model-context-protocol"
|
|
27
27
|
],
|
|
28
|
-
"homepage": "https://
|
|
28
|
+
"homepage": "https://onsystem.vercel.app",
|
|
29
29
|
"bugs": "https://github.com/dgesteves/onsystem/issues",
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"stemmer": "^2.0.1",
|
|
69
69
|
"tinyglobby": "^0.2.17",
|
|
70
70
|
"typescript": "~6.0.3",
|
|
71
|
+
"yaml": "^2.9.1",
|
|
71
72
|
"zod": "^4.6.5"
|
|
72
73
|
},
|
|
73
74
|
"peerDependencies": {
|
package/schema.json
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"tokens": {
|
|
32
|
-
"description": "Token files: W3C DTCG JSON (*.json)
|
|
32
|
+
"description": "Token files: W3C DTCG JSON (*.json), CSS custom properties (*.css) or a DESIGN.md's front matter (*.md).",
|
|
33
33
|
"anyOf": [
|
|
34
34
|
{
|
|
35
35
|
"anyOf": [
|
|
@@ -116,6 +116,24 @@
|
|
|
116
116
|
"type": "string"
|
|
117
117
|
}
|
|
118
118
|
},
|
|
119
|
+
"libraries": {
|
|
120
|
+
"description": "Published component libraries to read from their type declarations when the project depends on them. Omitted: every one onsystem reads (mui). false: none. A list: only those, e.g. [\"mui\"].",
|
|
121
|
+
"anyOf": [
|
|
122
|
+
{
|
|
123
|
+
"type": "boolean",
|
|
124
|
+
"const": false
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"type": "array",
|
|
128
|
+
"items": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"enum": [
|
|
131
|
+
"mui"
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
},
|
|
119
137
|
"includeDesignSystem": {
|
|
120
138
|
"description": "check: lint the design system's own component files too. Off by default: they implement the scale and primitives the rules enforce.",
|
|
121
139
|
"type": "boolean"
|