@design-parity/baseline 0.1.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 +60 -0
- package/dist/artifacts.d.ts +9 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +15 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/bootstrap.d.ts +59 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +94 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/checks.d.ts +13 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +8 -0
- package/dist/checks.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +3 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +149 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cmp.d.ts +75 -0
- package/dist/cmp.d.ts.map +1 -0
- package/dist/cmp.js +126 -0
- package/dist/cmp.js.map +1 -0
- package/dist/detect.d.ts +42 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +150 -0
- package/dist/detect.js.map +1 -0
- package/dist/direction.d.ts +14 -0
- package/dist/direction.d.ts.map +1 -0
- package/dist/direction.js +10 -0
- package/dist/direction.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/seed.d.ts +25 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +128 -0
- package/dist/seed.js.map +1 -0
- package/dist/tokens.d.ts +16 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +57 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +34 -0
package/dist/cmp.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose Multiplatform (CMP) capability detection (Principle 6).
|
|
3
|
+
*
|
|
4
|
+
* The candidate side is cheapest to render when the UI is Compose
|
|
5
|
+
* Multiplatform: a CMP component renders on the JVM/desktop — and, increasingly,
|
|
6
|
+
* a headless browser via Compose for Web / wasm — with no Android emulator. So
|
|
7
|
+
* the bot *prefers* the CMP render path when a project supports it, and
|
|
8
|
+
* *promotes* CMP to projects that don't. This module supplies the deterministic
|
|
9
|
+
* half of that: scan committed Gradle build files for CMP signals and report a
|
|
10
|
+
* `cmpCapable` verdict plus the evidence behind it.
|
|
11
|
+
*
|
|
12
|
+
* This is detection + advisory only. It NEVER gates: plain Jetpack Compose stays
|
|
13
|
+
* fully supported, and a non-CMP repo gets a suggestion, not a failure
|
|
14
|
+
* (Principle 6). Detection is a bounded, deterministic, offline file scan — no
|
|
15
|
+
* model calls, no network, no toolchain — matching {@link detectMaturity}.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Build files worth scanning for CMP signals. Kept narrow and deterministic:
|
|
19
|
+
* Gradle build scripts (Groovy + Kotlin DSL), settings scripts, and the Gradle
|
|
20
|
+
* version catalog where plugins/deps are commonly declared.
|
|
21
|
+
*/
|
|
22
|
+
const BUILD_FILE_RE = /^(build\.gradle(\.kts)?|settings\.gradle(\.kts)?|libs\.versions\.toml)$/;
|
|
23
|
+
/** True if `name` is a build file this module scans. */
|
|
24
|
+
export function isCmpBuildFile(name) {
|
|
25
|
+
return BUILD_FILE_RE.test(name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Signal patterns. Each entry maps a regex to the {@link CmpSignalKind} it
|
|
29
|
+
* proves. Order is the scan order, so a file's signals come out
|
|
30
|
+
* plugin-before-target-before-dependency for a stable, readable audit trail.
|
|
31
|
+
*
|
|
32
|
+
* The patterns are intentionally tolerant of Groovy and Kotlin DSL syntax:
|
|
33
|
+
* - plugin alias `id "org.jetbrains.compose"`, `id("org.jetbrains.compose")`,
|
|
34
|
+
* `alias(libs.plugins.compose...)`, or a `[plugins]` catalog entry;
|
|
35
|
+
* - `kotlin("multiplatform")` and the bare `org.jetbrains.kotlin.multiplatform`
|
|
36
|
+
* plugin id;
|
|
37
|
+
* - a non-Android KMP target block: `jvm()`, `js(...)`, `wasmJs(...)`, or a
|
|
38
|
+
* `desktop`/`jvm` source-set / target reference;
|
|
39
|
+
* - a `compose-multiplatform` / `org.jetbrains.compose` dependency coordinate.
|
|
40
|
+
*/
|
|
41
|
+
const PATTERNS = [
|
|
42
|
+
{
|
|
43
|
+
kind: "compose-plugin",
|
|
44
|
+
// org.jetbrains.compose plugin via id(...)/id "..." or a libs.plugins.compose alias.
|
|
45
|
+
re: /org\.jetbrains\.compose|(?:alias\([^)]*|libs\.plugins\.)compose(?:[-_.]multiplatform)?\b/,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
kind: "kotlin-multiplatform",
|
|
49
|
+
// kotlin("multiplatform"), the bare plugin id, or a kotlin-multiplatform catalog coordinate.
|
|
50
|
+
re: /kotlin\(\s*["']multiplatform["']\s*\)|org\.jetbrains\.kotlin\.multiplatform|kotlin[-.]multiplatform/,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
kind: "jvm-target",
|
|
54
|
+
// A non-Android KMP target/source-set that can host a headless render:
|
|
55
|
+
// jvm()/desktop, or a wasmJs/js target in call or trailing-lambda form.
|
|
56
|
+
re: /\bjvm\s*\(\s*\)|\bdesktop\b|\bwasmJs\s*[({]|\bjs\s*[({]/,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
kind: "compose-dependency",
|
|
60
|
+
// A compose-multiplatform dependency coordinate / version-catalog key.
|
|
61
|
+
re: /compose[-.]multiplatform|org\.jetbrains\.compose:/,
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Classify the contents of a single build file into CMP signals (pure).
|
|
66
|
+
*
|
|
67
|
+
* Comment lines (`//`, `#`) are skipped so a commented-out plugin block never
|
|
68
|
+
* trips a false positive. At most one signal per kind per file is reported, so
|
|
69
|
+
* the evidence stays compact.
|
|
70
|
+
*
|
|
71
|
+
* @param path repo-relative path, echoed back on each signal for the audit trail
|
|
72
|
+
* @param contents the file's text
|
|
73
|
+
*/
|
|
74
|
+
export function classifyBuildFile(path, contents) {
|
|
75
|
+
const out = [];
|
|
76
|
+
const seen = new Set();
|
|
77
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
78
|
+
const line = rawLine.trim();
|
|
79
|
+
if (line === "" || line.startsWith("//") || line.startsWith("#"))
|
|
80
|
+
continue;
|
|
81
|
+
for (const { kind, re } of PATTERNS) {
|
|
82
|
+
if (seen.has(kind))
|
|
83
|
+
continue;
|
|
84
|
+
const m = re.exec(line);
|
|
85
|
+
if (m) {
|
|
86
|
+
seen.add(kind);
|
|
87
|
+
out.push({ kind, path, match: m[0] });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Emit in PATTERNS order for a stable, readable audit trail.
|
|
92
|
+
return out.sort((a, b) => PATTERNS.findIndex((p) => p.kind === a.kind) -
|
|
93
|
+
PATTERNS.findIndex((p) => p.kind === b.kind));
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Fold a set of per-file signals into a {@link CmpCapability} verdict.
|
|
97
|
+
*
|
|
98
|
+
* A repo is CMP-capable on *any* signal — the CMP plugin, the KMP plugin, a
|
|
99
|
+
* JVM/desktop/wasm/js target, or a compose-multiplatform dependency. The
|
|
100
|
+
* threshold is deliberately permissive: this is an advisory promote/prefer hint,
|
|
101
|
+
* never a gate, so a false positive merely skips a suggestion and a false
|
|
102
|
+
* negative merely shows one (Principle 6).
|
|
103
|
+
*/
|
|
104
|
+
export function summarizeCmp(signals) {
|
|
105
|
+
return { cmpCapable: signals.length > 0, signals };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The promotion suggestion shown to Android-only (non-CMP) projects. Returns a
|
|
109
|
+
* non-blocking advisory string when `capability.cmpCapable` is false, and
|
|
110
|
+
* `undefined` when the repo is already CMP-capable (nothing to promote).
|
|
111
|
+
*
|
|
112
|
+
* This is the "promote CMP, never require it" half of Principle 6: advisory
|
|
113
|
+
* only, surfaced in the bootstrap output and (where relevant) the PR comment —
|
|
114
|
+
* never a gate.
|
|
115
|
+
*/
|
|
116
|
+
export function cmpSuggestion(capability) {
|
|
117
|
+
if (capability.cmpCapable)
|
|
118
|
+
return undefined;
|
|
119
|
+
return ("This project looks Android-only (Jetpack Compose); no Compose Multiplatform " +
|
|
120
|
+
"signal was found. Compose Multiplatform would let design-parity render " +
|
|
121
|
+
"candidates on the JVM/desktop — and potentially a headless browser via " +
|
|
122
|
+
"Compose for Web / wasm — with no Android emulator, making parity faster, " +
|
|
123
|
+
"more portable, and easier to run unattended. Consider adopting it. " +
|
|
124
|
+
"(Advisory only — plain Jetpack Compose stays fully supported.)");
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=cmp.js.map
|
package/dist/cmp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cmp.js","sourceRoot":"","sources":["../src/cmp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA8BH;;;;GAIG;AACH,MAAM,aAAa,GACjB,yEAAyE,CAAC;AAE5E,wDAAwD;AACxD,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,QAAQ,GAAuD;IACnE;QACE,IAAI,EAAE,gBAAgB;QACtB,qFAAqF;QACrF,EAAE,EAAE,0FAA0F;KAC/F;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,6FAA6F;QAC7F,EAAE,EAAE,qGAAqG;KAC1G;IACD;QACE,IAAI,EAAE,YAAY;QAClB,uEAAuE;QACvE,wEAAwE;QACxE,EAAE,EAAE,yDAAyD;KAC9D;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,uEAAuE;QACvE,EAAE,EAAE,mDAAmD;KACxD;CACF,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IAC9D,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;IAEtC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAE3E,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,CAAC,EAAE,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACf,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,OAAO,GAAG,CAAC,IAAI,CACb,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC;QAC5C,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAC/C,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,UAAyB;IACrD,IAAI,UAAU,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,CACL,8EAA8E;QAC9E,yEAAyE;QACzE,yEAAyE;QACzE,2EAA2E;QAC3E,qEAAqE;QACrE,gEAAgE,CACjE,CAAC;AACJ,CAAC"}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { MaturityRung } from "@design-parity/core";
|
|
2
|
+
import type { CmpCapability } from "./cmp.js";
|
|
3
|
+
/** One piece of evidence found during the scan. */
|
|
4
|
+
export interface MaturitySignal {
|
|
5
|
+
/** What kind of evidence, e.g. `"code-connect"`, `"design-map"`, `"tokens"`. */
|
|
6
|
+
kind: "code-connect" | "design-map" | "tokens";
|
|
7
|
+
/** Repo-relative path to the file that matched. */
|
|
8
|
+
path: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MaturityResult {
|
|
11
|
+
rung: MaturityRung;
|
|
12
|
+
/** Short human label for the rung. */
|
|
13
|
+
label: string;
|
|
14
|
+
/** A Figma Code Connect machine link was found (drives `machine-link`). */
|
|
15
|
+
hasCodeConnect: boolean;
|
|
16
|
+
/** A `design-map.json` manifest was found. */
|
|
17
|
+
hasDesignMap: boolean;
|
|
18
|
+
/** Design-token / design-system files were found (no machine link). */
|
|
19
|
+
hasTokens: boolean;
|
|
20
|
+
/** Every signal found, in scan order. */
|
|
21
|
+
signals: MaturitySignal[];
|
|
22
|
+
/**
|
|
23
|
+
* Whether the repo is Compose Multiplatform capable (Principle 6). Convenience
|
|
24
|
+
* mirror of {@link MaturityResult.cmp}.cmpCapable, hoisted onto the result for
|
|
25
|
+
* the common `if (result.cmpCapable)` check. Orthogonal to the maturity rung:
|
|
26
|
+
* a repo at any rung may or may not be CMP-capable.
|
|
27
|
+
*/
|
|
28
|
+
cmpCapable: boolean;
|
|
29
|
+
/** The full CMP capability verdict + its evidence (drives prefer/promote). */
|
|
30
|
+
cmp: CmpCapability;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Classify `repoRoot` into a maturity rung.
|
|
34
|
+
*
|
|
35
|
+
* Rung 1 wins on any Code Connect signal; rung 2 on a `design-map.json` or a
|
|
36
|
+
* design-token source; rung 3 is the floor. The token baseline this package
|
|
37
|
+
* generates is deliberately *not* treated as a rung-2 signal — that is what a
|
|
38
|
+
* bootstrapped rung-3 repo produces, so detection ignores files it would write
|
|
39
|
+
* (see {@link BASELINE_ARTIFACTS}).
|
|
40
|
+
*/
|
|
41
|
+
export declare function detectMaturity(repoRoot: string): Promise<MaturityResult>;
|
|
42
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQxD,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,UAAU,CAAC;AAEzD,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,gFAAgF;IAChF,IAAI,EAAE,cAAc,GAAG,YAAY,GAAG,QAAQ,CAAC;IAC/C,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAC;IACxB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;IACtB,uEAAuE;IACvE,SAAS,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,GAAG,EAAE,aAAa,CAAC;CACpB;AA2CD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CA2BzB"}
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maturity detection — classify a repo into one of three rungs (Principle 3).
|
|
3
|
+
*
|
|
4
|
+
* `machine-link`: design system + machine link (Figma Code Connect),
|
|
5
|
+
* `manifest`: design system, no machine link (`design-map.json` / tokens),
|
|
6
|
+
* `bootstrap`: no design system.
|
|
7
|
+
*
|
|
8
|
+
* Detection is a bounded, deterministic scan of committed files — no model
|
|
9
|
+
* calls, no network. It reports the evidence that drove the classification so
|
|
10
|
+
* the bootstrap CLI can explain itself and a human can audit the verdict.
|
|
11
|
+
*/
|
|
12
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
13
|
+
import { join, relative } from "node:path";
|
|
14
|
+
import { TOKENS_FILE } from "./artifacts.js";
|
|
15
|
+
import { classifyBuildFile, isCmpBuildFile, summarizeCmp, } from "./cmp.js";
|
|
16
|
+
const RUNG_LABELS = {
|
|
17
|
+
"machine-link": "design system + machine link (Figma Code Connect)",
|
|
18
|
+
manifest: "design system, no machine link (manifest / tokens)",
|
|
19
|
+
bootstrap: "no design system",
|
|
20
|
+
};
|
|
21
|
+
/** Directories never worth descending into. */
|
|
22
|
+
const IGNORE_DIRS = new Set([
|
|
23
|
+
"node_modules",
|
|
24
|
+
".git",
|
|
25
|
+
"dist",
|
|
26
|
+
"build",
|
|
27
|
+
"out",
|
|
28
|
+
".next",
|
|
29
|
+
".gradle",
|
|
30
|
+
".idea",
|
|
31
|
+
"vendor",
|
|
32
|
+
"coverage",
|
|
33
|
+
]);
|
|
34
|
+
/** Bound the walk so detection stays fast on large repos. */
|
|
35
|
+
const MAX_DEPTH = 6;
|
|
36
|
+
/** Figma Code Connect config files (presence ⇒ a machine link is wired). */
|
|
37
|
+
const CODE_CONNECT_CONFIGS = new Set(["figma.config.json"]);
|
|
38
|
+
/** Code Connect component definitions, e.g. `Button.figma.tsx`. */
|
|
39
|
+
const CODE_CONNECT_RE = /\.figma\.(tsx?|jsx?|kt|swift)$/;
|
|
40
|
+
/** A manifest correspondence file. */
|
|
41
|
+
const DESIGN_MAP_RE = /(^|[./])design-map\.json$/;
|
|
42
|
+
/**
|
|
43
|
+
* Design-token / design-system files that indicate a design system *without* a
|
|
44
|
+
* machine link. Style Dictionary, Tokens Studio, and DTCG `.tokens.json` all
|
|
45
|
+
* land here, as does a conventional `tokens/` tree.
|
|
46
|
+
*/
|
|
47
|
+
const TOKEN_FILE_RE = /(^|[./])(design-)?tokens\.json$|\.tokens\.json$|(^|[./])(sd|style-dictionary)\.config\.(json|js|cjs|mjs)$/;
|
|
48
|
+
const TOKEN_DIRS = new Set(["tokens", "design-tokens"]);
|
|
49
|
+
/**
|
|
50
|
+
* Classify `repoRoot` into a maturity rung.
|
|
51
|
+
*
|
|
52
|
+
* Rung 1 wins on any Code Connect signal; rung 2 on a `design-map.json` or a
|
|
53
|
+
* design-token source; rung 3 is the floor. The token baseline this package
|
|
54
|
+
* generates is deliberately *not* treated as a rung-2 signal — that is what a
|
|
55
|
+
* bootstrapped rung-3 repo produces, so detection ignores files it would write
|
|
56
|
+
* (see {@link BASELINE_ARTIFACTS}).
|
|
57
|
+
*/
|
|
58
|
+
export async function detectMaturity(repoRoot) {
|
|
59
|
+
const signals = [];
|
|
60
|
+
const buildFiles = [];
|
|
61
|
+
await walk(repoRoot, repoRoot, 0, signals, buildFiles);
|
|
62
|
+
const hasCodeConnect = signals.some((s) => s.kind === "code-connect");
|
|
63
|
+
const hasDesignMap = signals.some((s) => s.kind === "design-map");
|
|
64
|
+
const hasTokens = signals.some((s) => s.kind === "tokens");
|
|
65
|
+
const rung = hasCodeConnect
|
|
66
|
+
? "machine-link"
|
|
67
|
+
: hasDesignMap || hasTokens
|
|
68
|
+
? "manifest"
|
|
69
|
+
: "bootstrap";
|
|
70
|
+
const cmp = await detectCmp(repoRoot, buildFiles);
|
|
71
|
+
return {
|
|
72
|
+
rung,
|
|
73
|
+
label: RUNG_LABELS[rung],
|
|
74
|
+
hasCodeConnect,
|
|
75
|
+
hasDesignMap,
|
|
76
|
+
hasTokens,
|
|
77
|
+
signals,
|
|
78
|
+
cmpCapable: cmp.cmpCapable,
|
|
79
|
+
cmp,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read each discovered build file and fold its CMP signals into a verdict. The
|
|
84
|
+
* directory walk only records build-file *paths* (cheap); content reads happen
|
|
85
|
+
* here, bounded to that small set. Unreadable files are skipped, never fatal —
|
|
86
|
+
* detection degrades to "no signal", matching the walk's tolerance.
|
|
87
|
+
*/
|
|
88
|
+
async function detectCmp(repoRoot, buildFiles) {
|
|
89
|
+
const signals = [];
|
|
90
|
+
for (const rel of buildFiles) {
|
|
91
|
+
let contents;
|
|
92
|
+
try {
|
|
93
|
+
contents = await readFile(join(repoRoot, rel), "utf8");
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
continue; // unreadable build file: skip, don't fail the scan
|
|
97
|
+
}
|
|
98
|
+
signals.push(...classifyBuildFile(rel, contents));
|
|
99
|
+
}
|
|
100
|
+
return summarizeCmp(signals);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The token baseline this package writes is the only artifact that looks like a
|
|
104
|
+
* design-system signal, so exclude it — a bootstrapped repo must not detect its
|
|
105
|
+
* own output as a pre-existing design system on a re-run.
|
|
106
|
+
*/
|
|
107
|
+
const BASELINE_ARTIFACTS = new Set([TOKENS_FILE]);
|
|
108
|
+
async function walk(repoRoot, dir, depth, out, buildFiles) {
|
|
109
|
+
if (depth > MAX_DEPTH)
|
|
110
|
+
return;
|
|
111
|
+
let entries;
|
|
112
|
+
try {
|
|
113
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return; // unreadable dir: skip, don't fail the whole scan
|
|
117
|
+
}
|
|
118
|
+
for (const entry of entries) {
|
|
119
|
+
const full = join(dir, entry.name);
|
|
120
|
+
const rel = relative(repoRoot, full);
|
|
121
|
+
if (entry.isDirectory()) {
|
|
122
|
+
if (IGNORE_DIRS.has(entry.name) || entry.name.startsWith("."))
|
|
123
|
+
continue;
|
|
124
|
+
if (TOKEN_DIRS.has(entry.name)) {
|
|
125
|
+
out.push({ kind: "tokens", path: rel });
|
|
126
|
+
}
|
|
127
|
+
await walk(repoRoot, full, depth + 1, out, buildFiles);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (!entry.isFile())
|
|
131
|
+
continue;
|
|
132
|
+
const name = entry.name;
|
|
133
|
+
if (CODE_CONNECT_CONFIGS.has(name) || CODE_CONNECT_RE.test(name)) {
|
|
134
|
+
out.push({ kind: "code-connect", path: rel });
|
|
135
|
+
}
|
|
136
|
+
else if (DESIGN_MAP_RE.test(name)) {
|
|
137
|
+
out.push({ kind: "design-map", path: rel });
|
|
138
|
+
}
|
|
139
|
+
else if (TOKEN_FILE_RE.test(name) && !BASELINE_ARTIFACTS.has(name)) {
|
|
140
|
+
out.push({ kind: "tokens", path: rel });
|
|
141
|
+
}
|
|
142
|
+
// CMP detection is orthogonal to the rung: record build files for a
|
|
143
|
+
// content scan (see {@link detectCmp}). A file can be both a token source
|
|
144
|
+
// and a build file, so this is not part of the rung if/else chain.
|
|
145
|
+
if (isCmpBuildFile(name)) {
|
|
146
|
+
buildFiles.push(rel);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Materialize the parity direction from a maturity rung (Principle 5).
|
|
3
|
+
*
|
|
4
|
+
* The resolution itself lives in `@design-parity/policy` — setup and the
|
|
5
|
+
* Action's late fallback must agree, so there's exactly one implementation.
|
|
6
|
+
* Baseline just applies it at bootstrap time and commits the concrete result,
|
|
7
|
+
* so steady state never carries `auto`.
|
|
8
|
+
*/
|
|
9
|
+
import type { MaturityRung, ParityConfig, ResolvedDirection } from "@design-parity/core";
|
|
10
|
+
/** The concrete direction a given rung materializes to (via `policy`). */
|
|
11
|
+
export declare function directionForRung(rung: MaturityRung): ResolvedDirection;
|
|
12
|
+
/** Build the committed {@link ParityConfig} for a rung — never leaves `auto`. */
|
|
13
|
+
export declare function parityConfigForRung(rung: MaturityRung): ParityConfig;
|
|
14
|
+
//# sourceMappingURL=direction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"direction.d.ts","sourceRoot":"","sources":["../src/direction.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGzF,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,iBAAiB,CAEtE;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAEpE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defaultParityConfig, materializeDirection, resolveAuto } from "@design-parity/policy";
|
|
2
|
+
/** The concrete direction a given rung materializes to (via `policy`). */
|
|
3
|
+
export function directionForRung(rung) {
|
|
4
|
+
return resolveAuto(rung);
|
|
5
|
+
}
|
|
6
|
+
/** Build the committed {@link ParityConfig} for a rung — never leaves `auto`. */
|
|
7
|
+
export function parityConfigForRung(rung) {
|
|
8
|
+
return materializeDirection(defaultParityConfig(), rung);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=direction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"direction.js","sourceRoot":"","sources":["../src/direction.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE/F,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,IAAkB;IACjD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,mBAAmB,CAAC,IAAkB;IACpD,OAAO,oBAAoB,CAAC,mBAAmB,EAAE,EAAE,IAAI,CAAC,CAAC;AAC3D,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@design-parity/baseline` — maturity detection + opinionated bootstrap.
|
|
3
|
+
*
|
|
4
|
+
* Used at setup/bootstrap time (interactive only) to classify a repo's
|
|
5
|
+
* design-system maturity, materialize a concrete parity direction, and — for a
|
|
6
|
+
* repo with no design system — generate a committed baseline (tokens, starter
|
|
7
|
+
* design-map, check config). Nothing here runs on the unattended Action path.
|
|
8
|
+
*/
|
|
9
|
+
export { detectMaturity } from "./detect.js";
|
|
10
|
+
export type { MaturitySignal, MaturityResult } from "./detect.js";
|
|
11
|
+
export { classifyBuildFile, isCmpBuildFile, summarizeCmp, cmpSuggestion, } from "./cmp.js";
|
|
12
|
+
export type { CmpSignal, CmpSignalKind, CmpCapability, } from "./cmp.js";
|
|
13
|
+
/** Re-exported for convenience; the canonical definition lives in `core`. */
|
|
14
|
+
export type { MaturityRung } from "@design-parity/core";
|
|
15
|
+
export { directionForRung, parityConfigForRung, } from "./direction.js";
|
|
16
|
+
export { materialBaselineTokens } from "./tokens.js";
|
|
17
|
+
export { defaultCheckConfig } from "./checks.js";
|
|
18
|
+
export { discoverCodeComponents, seedDesignMap, } from "./seed.js";
|
|
19
|
+
export type { DiscoveredComponent } from "./seed.js";
|
|
20
|
+
export { CONFIG_FILE, TOKENS_FILE, CHECKS_FILE, DESIGN_MAP_FILE, } from "./artifacts.js";
|
|
21
|
+
export { planBootstrap, applyBootstrap, } from "./bootstrap.js";
|
|
22
|
+
export type { PlannedArtifact, BootstrapPlan, PlanOptions, ApplyOptions, ApplyResult, } from "./bootstrap.js";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,SAAS,EACT,aAAa,EACb,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,6EAA6E;AAC7E,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EACL,sBAAsB,EACtB,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,aAAa,EACb,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@design-parity/baseline` — maturity detection + opinionated bootstrap.
|
|
3
|
+
*
|
|
4
|
+
* Used at setup/bootstrap time (interactive only) to classify a repo's
|
|
5
|
+
* design-system maturity, materialize a concrete parity direction, and — for a
|
|
6
|
+
* repo with no design system — generate a committed baseline (tokens, starter
|
|
7
|
+
* design-map, check config). Nothing here runs on the unattended Action path.
|
|
8
|
+
*/
|
|
9
|
+
export { detectMaturity } from "./detect.js";
|
|
10
|
+
export { classifyBuildFile, isCmpBuildFile, summarizeCmp, cmpSuggestion, } from "./cmp.js";
|
|
11
|
+
export { directionForRung, parityConfigForRung, } from "./direction.js";
|
|
12
|
+
export { materialBaselineTokens } from "./tokens.js";
|
|
13
|
+
export { defaultCheckConfig } from "./checks.js";
|
|
14
|
+
export { discoverCodeComponents, seedDesignMap, } from "./seed.js";
|
|
15
|
+
export { CONFIG_FILE, TOKENS_FILE, CHECKS_FILE, DESIGN_MAP_FILE, } from "./artifacts.js";
|
|
16
|
+
export { planBootstrap, applyBootstrap, } from "./bootstrap.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,UAAU,CAAC;AASlB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EACL,sBAAsB,EACtB,aAAa,GACd,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,aAAa,EACb,cAAc,GACf,MAAM,gBAAgB,CAAC"}
|
package/dist/seed.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DesignMap } from "@design-parity/core";
|
|
2
|
+
/** One UI component discovered by name convention. Always low confidence. */
|
|
3
|
+
export interface DiscoveredComponent {
|
|
4
|
+
/** Code handle in `design-map` form, e.g. `ui/Button.kt#PrimaryButton`. */
|
|
5
|
+
code: string;
|
|
6
|
+
/** The component symbol, e.g. `PrimaryButton`. */
|
|
7
|
+
symbol: string;
|
|
8
|
+
/** Repo-relative source file. */
|
|
9
|
+
file: string;
|
|
10
|
+
/** Convention matches are always low confidence (Correspondence contract). */
|
|
11
|
+
confidence: "low";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Scan `repoRoot` for UI components by name convention. Deterministic: results
|
|
15
|
+
* are sorted by code handle and de-duplicated.
|
|
16
|
+
*/
|
|
17
|
+
export declare function discoverCodeComponents(repoRoot: string): Promise<DiscoveredComponent[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Build the starter design-map. A greenfield repo has no design source, so the
|
|
20
|
+
* committed manifest is an empty scaffold; the discovered components live in the
|
|
21
|
+
* bootstrap report as review items. The `$schema` points at the schema shipped
|
|
22
|
+
* by `@design-parity/core` so editors validate the file in-place.
|
|
23
|
+
*/
|
|
24
|
+
export declare function seedDesignMap(): DesignMap;
|
|
25
|
+
//# sourceMappingURL=seed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,UAAU,EAAE,KAAK,CAAC;CACnB;AA2CD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAKhC;AA8DD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAMzC"}
|
package/dist/seed.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convention seeding for the starter `design-map.json`.
|
|
3
|
+
*
|
|
4
|
+
* A greenfield repo has no design source to link against, so the committed
|
|
5
|
+
* `design-map.json` is emitted as a valid, empty scaffold. The value here is the
|
|
6
|
+
* *review list*: a best-effort, name-convention scan of the repo's UI
|
|
7
|
+
* components, every entry flagged low-confidence, that a human wires to a design
|
|
8
|
+
* reference once they adopt a design tool. This is the same convention matching
|
|
9
|
+
* the resolver (#7) does; baseline runs a lightweight in-package version until
|
|
10
|
+
* that package is available.
|
|
11
|
+
*/
|
|
12
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
13
|
+
import { join, relative } from "node:path";
|
|
14
|
+
const IGNORE_DIRS = new Set([
|
|
15
|
+
"node_modules",
|
|
16
|
+
".git",
|
|
17
|
+
"dist",
|
|
18
|
+
"build",
|
|
19
|
+
"out",
|
|
20
|
+
".next",
|
|
21
|
+
".gradle",
|
|
22
|
+
".idea",
|
|
23
|
+
"vendor",
|
|
24
|
+
"coverage",
|
|
25
|
+
"test",
|
|
26
|
+
"tests",
|
|
27
|
+
"__tests__",
|
|
28
|
+
]);
|
|
29
|
+
const MAX_DEPTH = 8;
|
|
30
|
+
const MAX_FILES = 2000;
|
|
31
|
+
/** Per-extension convention matchers producing capitalized component symbols. */
|
|
32
|
+
const MATCHERS = [
|
|
33
|
+
{
|
|
34
|
+
// Jetpack Compose / Compose Multiplatform.
|
|
35
|
+
ext: /\.kt$/,
|
|
36
|
+
symbols: [/@Composable[\s\S]{0,200}?\bfun\s+([A-Z]\w*)\s*\(/g],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
// React / Compose-for-Web style function & const components.
|
|
40
|
+
ext: /\.[jt]sx$/,
|
|
41
|
+
symbols: [
|
|
42
|
+
/export\s+(?:default\s+)?function\s+([A-Z]\w*)\s*\(/g,
|
|
43
|
+
/export\s+const\s+([A-Z]\w*)\s*[:=]\s*(?:\([^)]*\)|[A-Za-z]\w*)\s*=>/g,
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
// SwiftUI views.
|
|
48
|
+
ext: /\.swift$/,
|
|
49
|
+
symbols: [/\bstruct\s+([A-Z]\w*)\s*:\s*[^{]*\bView\b/g],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Scan `repoRoot` for UI components by name convention. Deterministic: results
|
|
54
|
+
* are sorted by code handle and de-duplicated.
|
|
55
|
+
*/
|
|
56
|
+
export async function discoverCodeComponents(repoRoot) {
|
|
57
|
+
const found = new Map();
|
|
58
|
+
const budget = { files: 0 };
|
|
59
|
+
await walk(repoRoot, repoRoot, 0, budget, found);
|
|
60
|
+
return [...found.values()].sort((a, b) => a.code.localeCompare(b.code));
|
|
61
|
+
}
|
|
62
|
+
async function walk(repoRoot, dir, depth, budget, out) {
|
|
63
|
+
if (depth > MAX_DEPTH || budget.files >= MAX_FILES)
|
|
64
|
+
return;
|
|
65
|
+
let entries;
|
|
66
|
+
try {
|
|
67
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
if (budget.files >= MAX_FILES)
|
|
74
|
+
return;
|
|
75
|
+
const full = join(dir, entry.name);
|
|
76
|
+
if (entry.isDirectory()) {
|
|
77
|
+
if (IGNORE_DIRS.has(entry.name) || entry.name.startsWith("."))
|
|
78
|
+
continue;
|
|
79
|
+
await walk(repoRoot, full, depth + 1, budget, out);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (!entry.isFile())
|
|
83
|
+
continue;
|
|
84
|
+
const matcher = MATCHERS.find((m) => m.ext.test(entry.name));
|
|
85
|
+
if (!matcher)
|
|
86
|
+
continue;
|
|
87
|
+
budget.files += 1;
|
|
88
|
+
let text;
|
|
89
|
+
try {
|
|
90
|
+
text = await readFile(full, "utf8");
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const rel = relative(repoRoot, full);
|
|
96
|
+
for (const symbol of extractSymbols(text, matcher.symbols)) {
|
|
97
|
+
const code = `${rel}#${symbol}`;
|
|
98
|
+
if (!out.has(code)) {
|
|
99
|
+
out.set(code, { code, symbol, file: rel, confidence: "low" });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function extractSymbols(text, patterns) {
|
|
105
|
+
const symbols = new Set();
|
|
106
|
+
for (const pattern of patterns) {
|
|
107
|
+
pattern.lastIndex = 0;
|
|
108
|
+
let m;
|
|
109
|
+
while ((m = pattern.exec(text)) !== null) {
|
|
110
|
+
if (m[1])
|
|
111
|
+
symbols.add(m[1]);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return symbols;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Build the starter design-map. A greenfield repo has no design source, so the
|
|
118
|
+
* committed manifest is an empty scaffold; the discovered components live in the
|
|
119
|
+
* bootstrap report as review items. The `$schema` points at the schema shipped
|
|
120
|
+
* by `@design-parity/core` so editors validate the file in-place.
|
|
121
|
+
*/
|
|
122
|
+
export function seedDesignMap() {
|
|
123
|
+
return {
|
|
124
|
+
$schema: "./node_modules/@design-parity/core/schema/design-map.schema.json",
|
|
125
|
+
components: [],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=seed.js.map
|
package/dist/seed.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.js","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The opinionated token baseline for a repo with no design system (rung 3).
|
|
3
|
+
*
|
|
4
|
+
* Material 3 + WCAG AA by construction: the foreground/background color pairs
|
|
5
|
+
* below are the M3 baseline roles, chosen so each on-* color clears AA (4.5:1)
|
|
6
|
+
* against its container. The spacing, radius, and type scales are the M3
|
|
7
|
+
* defaults. This is a *starting point* a human reviews and commits — not a
|
|
8
|
+
* decision re-made on every run (Principle 1).
|
|
9
|
+
*/
|
|
10
|
+
import type { DesignTokens } from "@design-parity/core";
|
|
11
|
+
/**
|
|
12
|
+
* Generate the baseline {@link DesignTokens}. Returns a fresh object each call
|
|
13
|
+
* so callers can safely mutate before writing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function materialBaselineTokens(): DesignTokens;
|
|
16
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,YAAY,CAmDrD"}
|