onsystem 0.10.1 → 0.10.2
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/cli.js +6 -9
- package/dist/{config-BbTW1jKU.d.ts → config-JaNAiR9Z.d.ts} +6 -8
- package/dist/{design-system-CPH4C7-1.js → design-system-rl__N6tw.js} +102 -102
- package/dist/eslint-worker.d.ts +2 -4
- package/dist/eslint-worker.js +3 -4
- package/dist/eslint.d.ts +0 -2
- package/dist/eslint.js +3 -5
- package/dist/index.d.ts +17 -51
- package/dist/index.js +2 -2
- package/dist/{stdio-BK2kMN1x.js → stdio-CkczPt_1.js} +152 -50
- package/dist/{workspace-BINqxi7p.js → workspace-INef0Yqt.js} +10 -19
- package/package.json +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
1
3
|
import fs from "node:fs";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { pathToFileURL } from "node:url";
|
|
@@ -7,11 +9,10 @@ import ts from "typescript";
|
|
|
7
9
|
import os from "node:os";
|
|
8
10
|
import postcss from "postcss";
|
|
9
11
|
import { clampChroma, colorsNamed, converter, differenceEuclidean, formatHex, parse, wcagContrast } from "culori";
|
|
10
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
11
12
|
import fsp from "node:fs/promises";
|
|
12
13
|
import { LineCounter, isMap, isScalar, parseDocument, stringify } from "yaml";
|
|
13
14
|
import { stemmer } from "stemmer";
|
|
14
|
-
|
|
15
|
+
// src/extract/program.ts
|
|
15
16
|
const DEFAULT_OPTIONS = {
|
|
16
17
|
target: ts.ScriptTarget.ES2022,
|
|
17
18
|
module: ts.ModuleKind.ESNext,
|
|
@@ -121,8 +122,7 @@ function projectFiles(program) {
|
|
|
121
122
|
function isProjectFile(file) {
|
|
122
123
|
return !/[\\/]node_modules[\\/]/.test(file);
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
-
//#region src/util/strings.ts
|
|
125
|
+
// src/util/strings.ts
|
|
126
126
|
/** `alert-dialog` / `alert_dialog` / `alertDialog` → `AlertDialog`. */
|
|
127
127
|
function pascalCase(input) {
|
|
128
128
|
return input.replace(/\.[^.]+$/, "").split(/[^a-zA-Z0-9]+|(?<=[a-z0-9])(?=[A-Z])/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
@@ -189,8 +189,7 @@ function plural$1(count, word, pluralWord = `${word}s`) {
|
|
|
189
189
|
function unique(items) {
|
|
190
190
|
return [...new Set(items)];
|
|
191
191
|
}
|
|
192
|
-
|
|
193
|
-
//#region src/util/paths.ts
|
|
192
|
+
// src/util/paths.ts
|
|
194
193
|
function toPosix(p) {
|
|
195
194
|
return p.split(path.sep).join("/");
|
|
196
195
|
}
|
|
@@ -347,8 +346,7 @@ function escapeRegExp(text) {
|
|
|
347
346
|
function pathOf(file) {
|
|
348
347
|
return /^[\p{L}\p{N}_@$.+~/\\:()[\]{}#%,=!-]+$/u.test(file) ? file : json(file);
|
|
349
348
|
}
|
|
350
|
-
|
|
351
|
-
//#region src/package-source.ts
|
|
349
|
+
// src/package-source.ts
|
|
352
350
|
/**
|
|
353
351
|
* A package's sources behind its build output: `exports` that point at `dist/` mapped
|
|
354
352
|
* back to `src/`, and barrels (`index.ts` files that re-export) followed to the files
|
|
@@ -589,8 +587,7 @@ function isFile$1(file) {
|
|
|
589
587
|
return false;
|
|
590
588
|
}
|
|
591
589
|
}
|
|
592
|
-
|
|
593
|
-
//#region src/tokens/imports.ts
|
|
590
|
+
// src/tokens/imports.ts
|
|
594
591
|
/** Enough stylesheets for a theme split over files, without reading a whole design system. */
|
|
595
592
|
const MAX_IMPORTED = 50;
|
|
596
593
|
/**
|
|
@@ -642,8 +639,7 @@ function importedStylesheets(files, resolve) {
|
|
|
642
639
|
for (const file of files) visit(file);
|
|
643
640
|
return out;
|
|
644
641
|
}
|
|
645
|
-
|
|
646
|
-
//#region src/detect.ts
|
|
642
|
+
// src/detect.ts
|
|
647
643
|
const ignore = () => void 0;
|
|
648
644
|
const COMPONENT_FILE = /\.[jt]sx$/;
|
|
649
645
|
/** A module a barrel can lead to: TypeScript or JavaScript, not a declaration file. */
|
|
@@ -2079,8 +2075,7 @@ function isDirectory$1(dir) {
|
|
|
2079
2075
|
return false;
|
|
2080
2076
|
}
|
|
2081
2077
|
}
|
|
2082
|
-
|
|
2083
|
-
//#region src/tokens/color.ts
|
|
2078
|
+
// src/tokens/color.ts
|
|
2084
2079
|
const toOklch$1 = converter("oklch");
|
|
2085
2080
|
/**
|
|
2086
2081
|
* Euclidean distance in OKLCH with hue handled as an angle, which is ΔE in
|
|
@@ -2251,8 +2246,7 @@ function formatDistance(color, token) {
|
|
|
2251
2246
|
if (deltaE < 5e-4 && formatOpacityGap(color, token, "")) return "same color";
|
|
2252
2247
|
return formatDeltaE(deltaE);
|
|
2253
2248
|
}
|
|
2254
|
-
|
|
2255
|
-
//#region src/libraries/mui.ts
|
|
2249
|
+
// src/libraries/mui.ts
|
|
2256
2250
|
/** The palette groups MUI's components take as a `color` value (`<Button color="primary">`). */
|
|
2257
2251
|
const ROLES = /* @__PURE__ */ new Set([
|
|
2258
2252
|
"primary",
|
|
@@ -2588,8 +2582,7 @@ function themeTokens(options, source) {
|
|
|
2588
2582
|
for (const token of tokens) token.origin = "library";
|
|
2589
2583
|
return tokens;
|
|
2590
2584
|
}
|
|
2591
|
-
|
|
2592
|
-
//#region src/libraries/index.ts
|
|
2585
|
+
// src/libraries/index.ts
|
|
2593
2586
|
/** The ids of the libraries onsystem can read, for the config's `libraries` list. */
|
|
2594
2587
|
const LIBRARY_IDS = ["mui"];
|
|
2595
2588
|
/** The libraries onsystem can read, by package. */
|
|
@@ -2718,8 +2711,7 @@ function readJson(file) {
|
|
|
2718
2711
|
return;
|
|
2719
2712
|
}
|
|
2720
2713
|
}
|
|
2721
|
-
|
|
2722
|
-
//#region src/extract/cva.ts
|
|
2714
|
+
// src/extract/cva.ts
|
|
2723
2715
|
const FACTORIES = /* @__PURE__ */ new Set(["cva", "tv"]);
|
|
2724
2716
|
/** Finds every `const x = cva(base, { variants, defaultVariants })` in a file. */
|
|
2725
2717
|
function findVariantDefinitions(sourceFile) {
|
|
@@ -2961,8 +2953,7 @@ function evaluateCalc(expression) {
|
|
|
2961
2953
|
const result = sum();
|
|
2962
2954
|
return result && Number.isFinite(result.n) ? result.n : void 0;
|
|
2963
2955
|
}
|
|
2964
|
-
|
|
2965
|
-
//#region src/tokens/usage.ts
|
|
2956
|
+
// src/tokens/usage.ts
|
|
2966
2957
|
/**
|
|
2967
2958
|
* Ready-to-paste ways to use a token, most idiomatic first. With a Tailwind
|
|
2968
2959
|
* theme key that is the utility class; otherwise the custom property.
|
|
@@ -3020,8 +3011,7 @@ function utilities(namespace, key) {
|
|
|
3020
3011
|
default: return [];
|
|
3021
3012
|
}
|
|
3022
3013
|
}
|
|
3023
|
-
|
|
3024
|
-
//#region src/tokens/tailwind-config.ts
|
|
3014
|
+
// src/tokens/tailwind-config.ts
|
|
3025
3015
|
/** A preset chain is a few files deep; anything beyond is not a Tailwind config. */
|
|
3026
3016
|
const MAX_FILES = 12;
|
|
3027
3017
|
/** A config or preset module, which is read for its theme. */
|
|
@@ -3521,8 +3511,7 @@ function findTailwindConfig(root) {
|
|
|
3521
3511
|
"mts"
|
|
3522
3512
|
].map((ext) => path.join(root, `tailwind.config.${ext}`)).find((file) => fs.existsSync(file));
|
|
3523
3513
|
}
|
|
3524
|
-
|
|
3525
|
-
//#region src/config.ts
|
|
3514
|
+
// src/config.ts
|
|
3526
3515
|
const RULE_IDS = [
|
|
3527
3516
|
"no-hardcoded-color",
|
|
3528
3517
|
"no-hardcoded-spacing",
|
|
@@ -3614,6 +3603,19 @@ const CONFIG_FILES = [
|
|
|
3614
3603
|
* They are still read, when no `onsystem.config.*` exists, with a notice to rename the file.
|
|
3615
3604
|
*/
|
|
3616
3605
|
const LEGACY_CONFIG_FILES = CONFIG_FILES.map((name) => name.replace(/^onsystem\./, "design-system-mcp."));
|
|
3606
|
+
/**
|
|
3607
|
+
* What marks the folder a file belongs to: the nearest one at or above it with a config,
|
|
3608
|
+
* a components.json, a package.json or an Nx project.json. The Claude Code hook finds a
|
|
3609
|
+
* file's project the same way, so `check` from a workspace root and the hook agree on
|
|
3610
|
+
* every file.
|
|
3611
|
+
*/
|
|
3612
|
+
const PROJECT_MARKERS = [
|
|
3613
|
+
...CONFIG_FILES,
|
|
3614
|
+
...LEGACY_CONFIG_FILES,
|
|
3615
|
+
"components.json",
|
|
3616
|
+
"package.json",
|
|
3617
|
+
"project.json"
|
|
3618
|
+
];
|
|
3617
3619
|
const DEFAULT_COMPONENTS = ["components/ui/**/*.{tsx,jsx}", "src/components/ui/**/*.{tsx,jsx}"];
|
|
3618
3620
|
/** Tests and stories: neither component sources nor UI that `check` lints by default. */
|
|
3619
3621
|
const DEFAULT_TEST_EXCLUDE = "**/*.{test,spec,stories}.{ts,tsx,js,jsx}";
|
|
@@ -3906,11 +3908,17 @@ function nodeRunsTypeScript(version = process.versions.node) {
|
|
|
3906
3908
|
/** A config file, read and validated: a JSON one only with `jsonConfigOnly`. */
|
|
3907
3909
|
async function readConfig(file, options) {
|
|
3908
3910
|
if (!fs.existsSync(file)) throw new ConfigError(`Config file not found: ${file}`);
|
|
3909
|
-
if (options.jsonConfigOnly && !file.endsWith(".json"))
|
|
3911
|
+
if (options.jsonConfigOnly && !file.endsWith(".json")) {
|
|
3912
|
+
const within = options.jsonConfigWithin;
|
|
3913
|
+
const project = options.root ? path.resolve(options.cwd ?? process.cwd(), options.root) : path.dirname(file);
|
|
3914
|
+
throw new ConfigError(within ? `${pathOf(file)} was not run: the server was started for ${pathOf(within)} (with --root or the client's root), which holds no project of its own, only projects in its folders, and a project found in it from the path a tool call names reads only a JSON config. Start the server with --root ${pathOf(project)} to use this config, or use onsystem.config.json.` : `${pathOf(file)} was not run: the server runs a JavaScript or TypeScript config only in a project it was started in (its working directory, --root or the client's roots), not in one found from the path a tool call names. Start the server in the project, or use onsystem.config.json.`);
|
|
3915
|
+
}
|
|
3910
3916
|
const parsed = configSchema.safeParse(await readConfigFile(file));
|
|
3911
3917
|
if (!parsed.success) throw new ConfigError(`Invalid config in ${file}:\n${z.prettifyError(parsed.error)}`);
|
|
3912
3918
|
return parsed.data;
|
|
3913
3919
|
}
|
|
3920
|
+
/** Where require keeps the CommonJS modules it has loaded, by path. */
|
|
3921
|
+
const requireCache = createRequire(import.meta.url).cache;
|
|
3914
3922
|
async function readConfigFile(file) {
|
|
3915
3923
|
if (/\.[cm]?ts$/.test(file) && !nodeRunsTypeScript()) throw new ConfigError(`${file} is TypeScript, which Node.js runs from 22.18; this is ${process.version}. Use onsystem.config.json or .mjs, or Node.js 22.18 or later.`);
|
|
3916
3924
|
if (file.endsWith(".json")) try {
|
|
@@ -3919,7 +3927,9 @@ async function readConfigFile(file) {
|
|
|
3919
3927
|
throw new ConfigError(`Could not parse ${file}: ${error.message}`);
|
|
3920
3928
|
}
|
|
3921
3929
|
try {
|
|
3922
|
-
const
|
|
3930
|
+
const version = createHash("sha256").update(fs.readFileSync(file)).digest("hex").slice(0, 16);
|
|
3931
|
+
delete requireCache[fs.realpathSync(file)];
|
|
3932
|
+
const mod = await import(`${pathToFileURL(file).href}?v=${version}`);
|
|
3923
3933
|
return mod.default ?? mod;
|
|
3924
3934
|
} catch (error) {
|
|
3925
3935
|
const message = error.message;
|
|
@@ -3943,8 +3953,7 @@ function configJsonSchema() {
|
|
|
3943
3953
|
io: "input"
|
|
3944
3954
|
});
|
|
3945
3955
|
}
|
|
3946
|
-
|
|
3947
|
-
//#region src/extract/components.ts
|
|
3956
|
+
// src/extract/components.ts
|
|
3948
3957
|
/**
|
|
3949
3958
|
* Extracts React components from source with the TypeScript checker: props
|
|
3950
3959
|
* (types, required, defaults, JSDoc), `cva()`/`tv()` variants, the native
|
|
@@ -4790,8 +4799,7 @@ function valueExports(checker, sourceFile) {
|
|
|
4790
4799
|
return ((symbol.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol).flags & ts.SymbolFlags.Value) !== 0;
|
|
4791
4800
|
}).map((symbol) => symbol.name);
|
|
4792
4801
|
}
|
|
4793
|
-
|
|
4794
|
-
//#region src/extract/docs.ts
|
|
4802
|
+
// src/extract/docs.ts
|
|
4795
4803
|
const EXAMPLE_LANGS = /* @__PURE__ */ new Set([
|
|
4796
4804
|
"tsx",
|
|
4797
4805
|
"jsx",
|
|
@@ -4959,8 +4967,7 @@ function dedent(code) {
|
|
|
4959
4967
|
const indent = Math.min(...lines.filter((l) => l.trim()).map((l) => /^\s*/.exec(l)?.[0].length ?? 0));
|
|
4960
4968
|
return lines.map((l) => l.slice(Number.isFinite(indent) ? indent : 0)).join("\n");
|
|
4961
4969
|
}
|
|
4962
|
-
|
|
4963
|
-
//#region src/libraries/declarations.ts
|
|
4970
|
+
// src/libraries/declarations.ts
|
|
4964
4971
|
/** A component's name: a capitalised identifier (`Button`, `ButtonBase`, `Unstable_Grid2`). */
|
|
4965
4972
|
const COMPONENT_NAME = /^[A-Z][\w$]*$/;
|
|
4966
4973
|
/** Packages contributing more props than this are summarised, as in source extraction. */
|
|
@@ -5498,8 +5505,7 @@ function linkSlots(components, icons) {
|
|
|
5498
5505
|
}
|
|
5499
5506
|
}
|
|
5500
5507
|
}
|
|
5501
|
-
|
|
5502
|
-
//#region src/libraries/load.ts
|
|
5508
|
+
// src/libraries/load.ts
|
|
5503
5509
|
/** App sources read for module augmentations and themes, at most. */
|
|
5504
5510
|
const MAX_SOURCES = 5e3;
|
|
5505
5511
|
const SOURCE_FILE = /\.(?:[cm]?[jt]sx?)$/;
|
|
@@ -5612,8 +5618,7 @@ async function appSources(root, project, patterns) {
|
|
|
5612
5618
|
}
|
|
5613
5619
|
return found;
|
|
5614
5620
|
}
|
|
5615
|
-
|
|
5616
|
-
//#region src/lint/analyze.ts
|
|
5621
|
+
// src/lint/analyze.ts
|
|
5617
5622
|
const CLASS_FUNCTIONS = /^(cn|clsx|cx|twMerge|twJoin|classNames|classnames|cva|tv)$/;
|
|
5618
5623
|
/** The node's children in source order. */
|
|
5619
5624
|
function childrenOf(node) {
|
|
@@ -5967,8 +5972,7 @@ function styleObjects(expr) {
|
|
|
5967
5972
|
const fn = asFunction(expr);
|
|
5968
5973
|
return (fn ? returnedExpressions(fn).flatMap(valueBranches) : valueBranches(expr)).filter(ts.isObjectLiteralExpression);
|
|
5969
5974
|
}
|
|
5970
|
-
|
|
5971
|
-
//#region src/lint/context.ts
|
|
5975
|
+
// src/lint/context.ts
|
|
5972
5976
|
/**
|
|
5973
5977
|
* Resolves a JSX tag to a design-system component, following imports and
|
|
5974
5978
|
* aliases. `file` is the checked file relative to the root, for relative imports.
|
|
@@ -6063,8 +6067,7 @@ function fromLibrary(target, library, name, source, member) {
|
|
|
6063
6067
|
source
|
|
6064
6068
|
};
|
|
6065
6069
|
}
|
|
6066
|
-
|
|
6067
|
-
//#region src/lint/tailwind-palette.ts
|
|
6070
|
+
// src/lint/tailwind-palette.ts
|
|
6068
6071
|
/** Tailwind's default color palette: name → shade → OKLCH value. */
|
|
6069
6072
|
const TAILWIND_PALETTE = {
|
|
6070
6073
|
red: {
|
|
@@ -6411,8 +6414,7 @@ const TAILWIND_KEYWORD_COLORS = {
|
|
|
6411
6414
|
black: "#000",
|
|
6412
6415
|
white: "#fff"
|
|
6413
6416
|
};
|
|
6414
|
-
|
|
6415
|
-
//#region src/tokens/css.ts
|
|
6417
|
+
// src/tokens/css.ts
|
|
6416
6418
|
/** Tailwind v4 theme namespaces → token category. Longest prefixes first. */
|
|
6417
6419
|
const NAMESPACES = [
|
|
6418
6420
|
["--inset-shadow-", "shadow"],
|
|
@@ -6793,8 +6795,7 @@ function trails(comment, before) {
|
|
|
6793
6795
|
const line = before?.source?.end?.line;
|
|
6794
6796
|
return line !== void 0 && comment.source?.start?.line === line;
|
|
6795
6797
|
}
|
|
6796
|
-
|
|
6797
|
-
//#region src/tokens/design-md.ts
|
|
6798
|
+
// src/tokens/design-md.ts
|
|
6798
6799
|
/**
|
|
6799
6800
|
* Reads the tokens in a DESIGN.md's YAML front matter (https://github.com/google-labs-code/design.md):
|
|
6800
6801
|
* `colors`, `typography`, `rounded` and `spacing`. Tokens are named by their path
|
|
@@ -6930,8 +6931,7 @@ function reference(value) {
|
|
|
6930
6931
|
function isReference(value) {
|
|
6931
6932
|
return reference(value) !== void 0;
|
|
6932
6933
|
}
|
|
6933
|
-
|
|
6934
|
-
//#region src/tokens/dtcg.ts
|
|
6934
|
+
// src/tokens/dtcg.ts
|
|
6935
6935
|
/**
|
|
6936
6936
|
* The `$extensions` key under which onsystem keeps what DTCG has no field for: the token's
|
|
6937
6937
|
* own name, the custom property code uses, the Tailwind theme variable and the values in
|
|
@@ -7293,8 +7293,7 @@ function lineIndex(text) {
|
|
|
7293
7293
|
return lineAt(offset);
|
|
7294
7294
|
};
|
|
7295
7295
|
}
|
|
7296
|
-
|
|
7297
|
-
//#region src/tokens/roles.ts
|
|
7296
|
+
// src/tokens/roles.ts
|
|
7298
7297
|
/** The role of a Tailwind color prefix (`bg`, `text`, `border-t`); undefined for shadows and the like. */
|
|
7299
7298
|
function colorRole(prefix) {
|
|
7300
7299
|
if (!prefix) return void 0;
|
|
@@ -7528,8 +7527,7 @@ function roleFit(token, role) {
|
|
|
7528
7527
|
};
|
|
7529
7528
|
}
|
|
7530
7529
|
}
|
|
7531
|
-
|
|
7532
|
-
//#region src/types.ts
|
|
7530
|
+
// src/types.ts
|
|
7533
7531
|
/**
|
|
7534
7532
|
* The design-system model the server exposes. Everything here is plain JSON so
|
|
7535
7533
|
* it can be cached on disk and returned as MCP structured content.
|
|
@@ -7542,8 +7540,7 @@ const TOKEN_CATEGORIES = [
|
|
|
7542
7540
|
"shadow",
|
|
7543
7541
|
"other"
|
|
7544
7542
|
];
|
|
7545
|
-
|
|
7546
|
-
//#region src/tokens/export.ts
|
|
7543
|
+
// src/tokens/export.ts
|
|
7547
7544
|
/** Group names a DTCG or DESIGN.md token path may already start with, per category. */
|
|
7548
7545
|
const GROUP_NAMES = {
|
|
7549
7546
|
color: [
|
|
@@ -8241,8 +8238,7 @@ function table(tokens, keys) {
|
|
|
8241
8238
|
function use(token) {
|
|
8242
8239
|
return [token.usage.find((u) => !u.includes("(")), cssReference(token)].filter((u) => Boolean(u)).map((u) => `\`${u}\``).join(", ");
|
|
8243
8240
|
}
|
|
8244
|
-
|
|
8245
|
-
//#region src/tokens/index.ts
|
|
8241
|
+
// src/tokens/index.ts
|
|
8246
8242
|
async function loadTokens(root, sources) {
|
|
8247
8243
|
const warnings = [];
|
|
8248
8244
|
const all = [];
|
|
@@ -8565,8 +8561,7 @@ function preferTailwind(a, b) {
|
|
|
8565
8561
|
function byDistance(a, b) {
|
|
8566
8562
|
return Math.round(a.distance * 1e4) - Math.round(b.distance * 1e4) || Number(b.inScope) - Number(a.inScope) || a.fit.rank - b.fit.rank || preferTailwind(a.candidate.token, b.candidate.token) || a.index - b.index;
|
|
8567
8563
|
}
|
|
8568
|
-
|
|
8569
|
-
//#region src/lint/tailwind.ts
|
|
8564
|
+
// src/lint/tailwind.ts
|
|
8570
8565
|
function splitClasses(text, offset) {
|
|
8571
8566
|
const tokens = [];
|
|
8572
8567
|
for (const match of text.matchAll(/\S+/g)) tokens.push({
|
|
@@ -8844,8 +8839,7 @@ const STYLE_RADIUS_PROPERTIES = {
|
|
|
8844
8839
|
function isColorAttribute(name) {
|
|
8845
8840
|
return /^(color|fill|stroke|stopColor|stop-color|floodColor|flood-color|lightingColor|bgcolor)$|Color$/.test(name);
|
|
8846
8841
|
}
|
|
8847
|
-
|
|
8848
|
-
//#region src/lint/target.ts
|
|
8842
|
+
// src/lint/target.ts
|
|
8849
8843
|
/**
|
|
8850
8844
|
* Elements a design system typically replaces. Containers (`div`, `span`,
|
|
8851
8845
|
* `p`) are deliberately absent: `Card` renders a `div`, but not every `div`
|
|
@@ -9250,8 +9244,7 @@ function modulePaths(file) {
|
|
|
9250
9244
|
const module = stripExtension(file);
|
|
9251
9245
|
return module.endsWith("/index") ? [module, module.slice(0, -6)] : [module];
|
|
9252
9246
|
}
|
|
9253
|
-
|
|
9254
|
-
//#region src/lint/rules/components.ts
|
|
9247
|
+
// src/lint/rules/components.ts
|
|
9255
9248
|
function renameTag(context, element, name) {
|
|
9256
9249
|
const edits = [{
|
|
9257
9250
|
range: [element.tagName.getStart(context.sourceFile), element.tagName.end],
|
|
@@ -10406,8 +10399,7 @@ const iconButtonAccessibleName = {
|
|
|
10406
10399
|
}
|
|
10407
10400
|
}
|
|
10408
10401
|
};
|
|
10409
|
-
|
|
10410
|
-
//#region src/lint/rules/hardcoded.ts
|
|
10402
|
+
// src/lint/rules/hardcoded.ts
|
|
10411
10403
|
/** `var(--color-green-50)`: a shade of Tailwind's palette through its CSS variable. */
|
|
10412
10404
|
const PALETTE_VARIABLE = /^var\(\s*--color-([a-z]+-(?:50|[1-9]00|950))\s*\)$/;
|
|
10413
10405
|
/** Luminance values, not design colors: `white`/`black` (and hex twins). */
|
|
@@ -11698,8 +11690,7 @@ function lengthReplacement(context, category, px, prefix) {
|
|
|
11698
11690
|
tailwind: false
|
|
11699
11691
|
};
|
|
11700
11692
|
}
|
|
11701
|
-
|
|
11702
|
-
//#region src/lint/rules/index.ts
|
|
11693
|
+
// src/lint/rules/index.ts
|
|
11703
11694
|
/** Every rule, in the order they run. */
|
|
11704
11695
|
const RULES = [
|
|
11705
11696
|
noHardcodedColor,
|
|
@@ -11719,8 +11710,7 @@ const RULES = [
|
|
|
11719
11710
|
noUnknownVariant,
|
|
11720
11711
|
iconButtonAccessibleName
|
|
11721
11712
|
];
|
|
11722
|
-
|
|
11723
|
-
//#region src/lint/suppress.ts
|
|
11713
|
+
// src/lint/suppress.ts
|
|
11724
11714
|
/**
|
|
11725
11715
|
* The prefix of suppression comments, the one place it is spelled:
|
|
11726
11716
|
* `// onsystem-disable-next-line <rule>[, <rule>]`, `// onsystem-disable-line
|
|
@@ -11795,8 +11785,7 @@ function insideLiteral(sourceFile, offset) {
|
|
|
11795
11785
|
}
|
|
11796
11786
|
return ts.isStringLiteralLike(node) || ts.isTemplateLiteralToken(node) || ts.isJsxText(node) || ts.isRegularExpressionLiteral(node);
|
|
11797
11787
|
}
|
|
11798
|
-
|
|
11799
|
-
//#region src/baseline.ts
|
|
11788
|
+
// src/baseline.ts
|
|
11800
11789
|
const BASELINE_FILE = "onsystem.baseline.json";
|
|
11801
11790
|
/** The baseline's name from before the rename to onsystem: still read when the new one is absent. */
|
|
11802
11791
|
const LEGACY_BASELINE_FILE = "design-system-mcp.baseline.json";
|
|
@@ -12132,15 +12121,12 @@ function writeBaseline(file, entries, about = {}) {
|
|
|
12132
12121
|
function isObject(value) {
|
|
12133
12122
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12134
12123
|
}
|
|
12135
|
-
|
|
12136
|
-
//#region package.json
|
|
12124
|
+
// package.json
|
|
12137
12125
|
var name = "onsystem";
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
const VERSION = "0.10.1";
|
|
12126
|
+
// src/version.ts
|
|
12127
|
+
const VERSION = "0.10.2";
|
|
12141
12128
|
const NAME = name;
|
|
12142
|
-
|
|
12143
|
-
//#region src/lint/sarif.ts
|
|
12129
|
+
// src/lint/sarif.ts
|
|
12144
12130
|
const SCHEMA = "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json";
|
|
12145
12131
|
const REPO = "https://github.com/dgesteves/onsystem";
|
|
12146
12132
|
const RULES_PAGE = "https://onsystem.vercel.app/rules";
|
|
@@ -12248,8 +12234,7 @@ function sarifResult(d, uri, ruleIndex, fingerprint) {
|
|
|
12248
12234
|
function fingerprint$1(uri, identity, occurrence) {
|
|
12249
12235
|
return createHash("sha256").update(`${uri}\0${identity}\0${String(occurrence)}`).digest("hex");
|
|
12250
12236
|
}
|
|
12251
|
-
|
|
12252
|
-
//#region src/lint/format.ts
|
|
12237
|
+
// src/lint/format.ts
|
|
12253
12238
|
/** From this many findings, `pretty` ends with a summary: more than a screen to scroll back through. */
|
|
12254
12239
|
const SUMMARY_FROM = 50;
|
|
12255
12240
|
/** The palette classes the summary lists. */
|
|
@@ -12348,8 +12333,7 @@ function escapeData(value) {
|
|
|
12348
12333
|
function escapeProperty(value) {
|
|
12349
12334
|
return escapeData(value).replace(/:/g, "%3A").replace(/,/g, "%2C");
|
|
12350
12335
|
}
|
|
12351
|
-
|
|
12352
|
-
//#region src/lint/index.ts
|
|
12336
|
+
// src/lint/index.ts
|
|
12353
12337
|
/**
|
|
12354
12338
|
* Lints a TSX/JSX snippet or file against the design system. Purely
|
|
12355
12339
|
* syntactic: no type-checking of the snippet, so it works on fragments an
|
|
@@ -12563,8 +12547,7 @@ function applyFixes(code, diagnostics) {
|
|
|
12563
12547
|
}
|
|
12564
12548
|
return out;
|
|
12565
12549
|
}
|
|
12566
|
-
|
|
12567
|
-
//#region src/modules.ts
|
|
12550
|
+
// src/modules.ts
|
|
12568
12551
|
/**
|
|
12569
12552
|
* Finds the modules a checked file imports from the design system, and what
|
|
12570
12553
|
* they export, so the linter can tell a name the model left out (an excluded
|
|
@@ -12677,8 +12660,7 @@ function readExports(sourceFile, resolve) {
|
|
|
12677
12660
|
namespaces
|
|
12678
12661
|
};
|
|
12679
12662
|
}
|
|
12680
|
-
|
|
12681
|
-
//#region src/search/bm25.ts
|
|
12663
|
+
// src/search/bm25.ts
|
|
12682
12664
|
var Bm25Index = class {
|
|
12683
12665
|
docs = [];
|
|
12684
12666
|
df = /* @__PURE__ */ new Map();
|
|
@@ -12735,8 +12717,7 @@ var Bm25Index = class {
|
|
|
12735
12717
|
return hits.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
12736
12718
|
}
|
|
12737
12719
|
};
|
|
12738
|
-
|
|
12739
|
-
//#region src/search/tokenize.ts
|
|
12720
|
+
// src/search/tokenize.ts
|
|
12740
12721
|
const STOP_WORDS = new Set(`a an and are as at be but by can do does for from has have how i if in into is it its me my need
|
|
12741
12722
|
of on or our should so some that the their them then there these this to use used using want we
|
|
12742
12723
|
what when where which while who will with without would you your show make let lets get add want
|
|
@@ -12810,8 +12791,7 @@ function expandQuery(query) {
|
|
|
12810
12791
|
}
|
|
12811
12792
|
return weights;
|
|
12812
12793
|
}
|
|
12813
|
-
|
|
12814
|
-
//#region src/search/index.ts
|
|
12794
|
+
// src/search/index.ts
|
|
12815
12795
|
/** Field weights: names matter most, then descriptions and variant values. */
|
|
12816
12796
|
const WEIGHTS = {
|
|
12817
12797
|
name: 4,
|
|
@@ -12964,8 +12944,7 @@ function searchComponents(index, query, limit = 5) {
|
|
|
12964
12944
|
weak: true
|
|
12965
12945
|
}));
|
|
12966
12946
|
}
|
|
12967
|
-
|
|
12968
|
-
//#region src/util/log.ts
|
|
12947
|
+
// src/util/log.ts
|
|
12969
12948
|
const stderrLogger = {
|
|
12970
12949
|
info: (message) => process.stderr.write(`[onsystem] ${message}\n`),
|
|
12971
12950
|
warn: (message) => process.stderr.write(`[onsystem] warning: ${message}\n`),
|
|
@@ -12976,8 +12955,7 @@ const silentLogger = {
|
|
|
12976
12955
|
warn: () => void 0,
|
|
12977
12956
|
error: () => void 0
|
|
12978
12957
|
};
|
|
12979
|
-
|
|
12980
|
-
//#region src/design-system.ts
|
|
12958
|
+
// src/design-system.ts
|
|
12981
12959
|
/** A loaded design system: the model plus the indexes the tools query. */
|
|
12982
12960
|
var DesignSystem = class {
|
|
12983
12961
|
model;
|
|
@@ -13259,9 +13237,10 @@ function outsideWarning(root, files) {
|
|
|
13259
13237
|
/**
|
|
13260
13238
|
* Absolute paths matching `patterns` under the root. `node_modules` is skipped
|
|
13261
13239
|
* even when `exclude` replaces the defaults, except by patterns that name it
|
|
13262
|
-
* (tokens published as a package). Files that lead outside the project are left out.
|
|
13240
|
+
* (tokens published as a package). Files that lead outside the project are left out. Those that
|
|
13241
|
+
* `skip` accepts are left out before that check, so they are not named as leading outside.
|
|
13263
13242
|
*/
|
|
13264
|
-
async function find(config, patterns, contain = new Containment(config)) {
|
|
13243
|
+
async function find(config, patterns, contain = new Containment(config), skip = () => false) {
|
|
13265
13244
|
const options = {
|
|
13266
13245
|
cwd: config.root,
|
|
13267
13246
|
absolute: true,
|
|
@@ -13294,7 +13273,7 @@ async function find(config, patterns, contain = new Containment(config)) {
|
|
|
13294
13273
|
});
|
|
13295
13274
|
})
|
|
13296
13275
|
]);
|
|
13297
|
-
return (await contain.filter(unique(found.flat()))).sort();
|
|
13276
|
+
return (await contain.filter(unique(found.flat()).filter((file) => !skip(file)))).sort();
|
|
13298
13277
|
}
|
|
13299
13278
|
/** The design system's own component files, as absolute paths. */
|
|
13300
13279
|
function componentFiles(config) {
|
|
@@ -13316,8 +13295,9 @@ async function resolveFiles(config) {
|
|
|
13316
13295
|
seen.add(real);
|
|
13317
13296
|
return true;
|
|
13318
13297
|
};
|
|
13298
|
+
const others = config.tokensDetected && !config.configFile && !holdsProject(config.root) ? (file) => inProjectBelow(config.root, file) : () => false;
|
|
13319
13299
|
const add = async (sources) => {
|
|
13320
|
-
for (const source of sources) for (const file of await find(config, [source.path], contain)) if (await isNew(file)) tokens.push({
|
|
13300
|
+
for (const source of sources) for (const file of await find(config, [source.path], contain, others)) if (await isNew(file)) tokens.push({
|
|
13321
13301
|
file,
|
|
13322
13302
|
prefix: source.prefix
|
|
13323
13303
|
});
|
|
@@ -13335,6 +13315,17 @@ async function resolveFiles(config) {
|
|
|
13335
13315
|
outside: [...contain.outside]
|
|
13336
13316
|
};
|
|
13337
13317
|
}
|
|
13318
|
+
function holdsProject(dir) {
|
|
13319
|
+
return PROJECT_MARKERS.some((name) => fs.existsSync(path.join(dir, name)));
|
|
13320
|
+
}
|
|
13321
|
+
/** Whether a folder between `root` and `file` (in it) holds a project. */
|
|
13322
|
+
function inProjectBelow(root, file) {
|
|
13323
|
+
for (let dir = path.dirname(path.resolve(file)); isInside(root, dir); dir = path.dirname(dir)) {
|
|
13324
|
+
if (path.relative(root, dir) === "") return false;
|
|
13325
|
+
if (holdsProject(dir)) return true;
|
|
13326
|
+
}
|
|
13327
|
+
return false;
|
|
13328
|
+
}
|
|
13338
13329
|
/**
|
|
13339
13330
|
* The stylesheets zero config reads besides the ones it found: those they `@import` (by a
|
|
13340
13331
|
* path, or from a workspace package: `@import "@acme/theme"`), then those that set the colors
|
|
@@ -13586,19 +13577,29 @@ var DesignSystemHost = class {
|
|
|
13586
13577
|
this.options = options;
|
|
13587
13578
|
}
|
|
13588
13579
|
get() {
|
|
13589
|
-
this.current ??= this.build(false);
|
|
13580
|
+
this.current ??= this.kept(this.build(false));
|
|
13590
13581
|
return this.current;
|
|
13591
13582
|
}
|
|
13592
13583
|
reload() {
|
|
13593
13584
|
const next = this.build(true);
|
|
13594
13585
|
const previous = this.current;
|
|
13595
|
-
this.current = next.catch(async (error) => {
|
|
13586
|
+
this.current = this.kept(next.catch(async (error) => {
|
|
13596
13587
|
(this.options.logger ?? silentLogger).error(`reload failed: ${error.message}`);
|
|
13597
13588
|
if (previous) return previous;
|
|
13598
13589
|
throw error;
|
|
13599
|
-
});
|
|
13590
|
+
}));
|
|
13600
13591
|
return this.current;
|
|
13601
13592
|
}
|
|
13593
|
+
/**
|
|
13594
|
+
* `build`, dropped if it fails with no earlier model to serve instead (a first build that
|
|
13595
|
+
* fails), so the next `get()` builds again.
|
|
13596
|
+
*/
|
|
13597
|
+
kept(build) {
|
|
13598
|
+
build.catch(() => {
|
|
13599
|
+
if (this.current === build) this.current = void 0;
|
|
13600
|
+
});
|
|
13601
|
+
return build;
|
|
13602
|
+
}
|
|
13602
13603
|
onChange(listener) {
|
|
13603
13604
|
this.listeners.add(listener);
|
|
13604
13605
|
return () => this.listeners.delete(listener);
|
|
@@ -13729,5 +13730,4 @@ var DesignSystemHost = class {
|
|
|
13729
13730
|
return ds;
|
|
13730
13731
|
}
|
|
13731
13732
|
};
|
|
13732
|
-
|
|
13733
|
-
export { DEFAULT_TOKENS as $, unrecordedRules as A, toPosix as At, statusKinds as B, countBaseline as C, workspacePackageDirs as Ct, pruneBaseline as D, matchesGlob as Dt, onLines as E, isInside as Et, loadTokens as F, unique as Ft, parseDoc as G, parseDesignMd as H, mergeTokens as I, defaultProjectConfig as It, ConfigError as J, extractComponents as K, toDesignMd as L, readProjectConfig as Lt, writeBaseline as M, json as Mt, RULES as N, plural$1 as Nt, readBaseline as O, pathOf as Ot, TokenIndex as P, truncate as Pt, DEFAULT_TEST_FOLDERS as Q, toDtcg as R, applyBaseline as S, isWorkspaceRoot as St, goneFiles as T, SCRIPT_FILE$2 as Tt, parseCssTokens as U, parseDtcgTokens as V, attachDocs as W, DEFAULT_SEVERITY as X, DEFAULT_DOCS as Y, DEFAULT_TEST_EXCLUDE as Z, formatDiagnostics as _, PackageFinder as _t, fingerprint as a, excludedBy as at, BASELINE_FILE as b, findDesignSystemPackage as bt, silentLogger as c, loadConfigWith as ct, descriptionOf as d, findVariantDefinitions as dt, FALLBACK_TOKENS as et, searchComponents as f, LIBRARIES as ft, escapeData as g, PACKAGE_FIELD as gt, uncheckedNotice as h, notReadYet as ht, componentFiles as i, defineConfig as it, updateBaseline as j, closest as jt, rulesRun as k, relativePath as kt, stderrLogger as l, rulesFor as lt, checkSource as m, libraryTitle as mt, DesignSystemHost as n, RULE_IDS as nt, loadDesignSystem as o, hasOwnConfig as ot, applyFixes as p, LIBRARY_IDS as pt, CONFIG_FILES as q, buildModel as r, configJsonSchema as rt, tokenFiles as s, loadConfig as st, DesignSystem as t, LEGACY_CONFIG_FILES as tt, buildSearchIndex as u, formatPx as ut, NAME as v, declaredConfig as vt, findMoves as w, workspacePatterns as wt, LEGACY_BASELINE_FILE as x, isDesignSystemName as xt, VERSION as y, detectProject as yt, TOKEN_CATEGORIES as z };
|
|
13733
|
+
export { DEFAULT_TOKENS as $, unrecordedRules as A, relativePath as At, statusKinds as B, countBaseline as C, isWorkspaceRoot as Ct, pruneBaseline as D, isInside as Dt, onLines as E, SCRIPT_FILE$2 as Et, loadTokens as F, truncate as Ft, parseDoc as G, parseDesignMd as H, mergeTokens as I, unique as It, ConfigError as J, extractComponents as K, toDesignMd as L, defaultProjectConfig as Lt, writeBaseline as M, closest as Mt, RULES as N, json as Nt, readBaseline as O, matchesGlob as Ot, TokenIndex as P, plural$1 as Pt, DEFAULT_TEST_FOLDERS as Q, toDtcg as R, readProjectConfig as Rt, applyBaseline as S, isDesignSystemName as St, goneFiles as T, workspacePatterns as Tt, parseCssTokens as U, parseDtcgTokens as V, attachDocs as W, DEFAULT_SEVERITY as X, DEFAULT_DOCS as Y, DEFAULT_TEST_EXCLUDE as Z, formatDiagnostics as _, PACKAGE_FIELD as _t, fingerprint as a, defineConfig as at, BASELINE_FILE as b, detectProject as bt, silentLogger as c, loadConfig as ct, descriptionOf as d, formatPx as dt, FALLBACK_TOKENS as et, searchComponents as f, findVariantDefinitions as ft, escapeData as g, notReadYet as gt, uncheckedNotice as h, libraryTitle as ht, componentFiles as i, configJsonSchema as it, updateBaseline as j, toPosix as jt, rulesRun as k, pathOf as kt, stderrLogger as l, loadConfigWith as lt, checkSource as m, LIBRARY_IDS as mt, DesignSystemHost as n, PROJECT_MARKERS as nt, loadDesignSystem as o, excludedBy as ot, applyFixes as p, LIBRARIES as pt, CONFIG_FILES as q, buildModel as r, RULE_IDS as rt, tokenFiles as s, hasOwnConfig as st, DesignSystem as t, LEGACY_CONFIG_FILES as tt, buildSearchIndex as u, rulesFor as ut, NAME as v, PackageFinder as vt, findMoves as w, workspacePackageDirs as wt, LEGACY_BASELINE_FILE as x, findDesignSystemPackage as xt, VERSION as y, declaredConfig as yt, TOKEN_CATEGORIES as z };
|
package/dist/eslint-worker.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { h as DesignSystemModel, i as ResolvedConfig } from "./config-
|
|
1
|
+
import { h as DesignSystemModel, i as ResolvedConfig } from "./config-JaNAiR9Z.js";
|
|
2
2
|
import { MessagePort } from "node:worker_threads";
|
|
3
|
-
//#region src/eslint/worker.d.ts
|
|
4
3
|
export interface LoadRequest {
|
|
5
4
|
/** ESLint's working directory: where `check` would run from. */
|
|
6
5
|
cwd: string;
|
|
@@ -32,5 +31,4 @@ export interface Call {
|
|
|
32
31
|
signal: Int32Array;
|
|
33
32
|
port: MessagePort;
|
|
34
33
|
}
|
|
35
|
-
export declare function load(request: LoadRequest): Promise<LoadResponse>;
|
|
36
|
-
//#endregion
|
|
34
|
+
export declare function load(request: LoadRequest): Promise<LoadResponse>;
|
package/dist/eslint-worker.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as loadTarget } from "./workspace-
|
|
1
|
+
import { At as relativePath, i as componentFiles, ot as excludedBy, r as buildModel } from "./design-system-rl__N6tw.js";
|
|
2
|
+
import { r as loadTarget } from "./workspace-INef0Yqt.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { parentPort } from "node:worker_threads";
|
|
6
|
-
|
|
6
|
+
// src/eslint/worker.ts
|
|
7
7
|
/**
|
|
8
8
|
* The ESLint plugin's loader, in a worker thread. ESLint rules run synchronously, and finding a
|
|
9
9
|
* project's design system does not (config files written in code, globs, the extraction
|
|
@@ -89,5 +89,4 @@ parentPort?.on("message", ({ request, signal, port }) => {
|
|
|
89
89
|
reply({ error: error.message });
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
|
-
//#endregion
|
|
93
92
|
export { load };
|
package/dist/eslint.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Linter, Rule } from "eslint";
|
|
2
|
-
//#region src/eslint/index.d.ts
|
|
3
2
|
/** `settings.onsystem`: where the project and its config are, when finding them from ESLint's cwd is not right. */
|
|
4
3
|
export interface Settings {
|
|
5
4
|
/** The project root, relative to ESLint's working directory (`check --root`). */
|
|
@@ -19,5 +18,4 @@ declare const plugin: {
|
|
|
19
18
|
recommended: Linter.Config;
|
|
20
19
|
};
|
|
21
20
|
};
|
|
22
|
-
//#endregion
|
|
23
21
|
export { plugin as default };
|
package/dist/eslint.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { N as RULES, Q as DEFAULT_TEST_FOLDERS, X as DEFAULT_SEVERITY, Z as DEFAULT_TEST_EXCLUDE,
|
|
1
|
+
import { At as relativePath, N as RULES, Q as DEFAULT_TEST_FOLDERS, X as DEFAULT_SEVERITY, Z as DEFAULT_TEST_EXCLUDE, t as DesignSystem, v as NAME, y as VERSION } from "./design-system-rl__N6tw.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { MessageChannel, Worker, receiveMessageOnPort } from "node:worker_threads";
|
|
4
|
-
|
|
4
|
+
// src/eslint/bridge.ts
|
|
5
5
|
/**
|
|
6
6
|
* Calls the loader worker (`worker.ts`) synchronously: posts the request, blocks on a shared
|
|
7
7
|
* flag until the worker has answered, and takes the answer off the port. The worker is
|
|
@@ -39,8 +39,7 @@ function loadSync(request) {
|
|
|
39
39
|
port1.close();
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
//#region src/eslint/index.ts
|
|
42
|
+
// src/eslint/index.ts
|
|
44
43
|
/**
|
|
45
44
|
* onsystem's rules as an ESLint plugin (ESLint 9 and 10, flat config):
|
|
46
45
|
*
|
|
@@ -229,5 +228,4 @@ plugin.configs.recommended = {
|
|
|
229
228
|
plugins: { onsystem: plugin },
|
|
230
229
|
rules: Object.fromEntries(RULES.map((rule) => [`onsystem/${rule.id}`, DEFAULT_SEVERITY[rule.id]]))
|
|
231
230
|
};
|
|
232
|
-
//#endregion
|
|
233
231
|
export { plugin as default };
|