@ bridge-ds/ core (中文(简体) )
Bridge的纯设计-托肯逻辑:负载 DTCG 2025.10 符号跨层,解决每个品牌的别名,
主题和密度, 请检查 WCAG 对比度, diff 三个版本的符号集, 编辑 *.tokens.json 文件
在不重排它们的情况下,构建牵引请求(body, risk level, changet)并与 GitHub 交谈.
主条目中没有 Figma API 、 没有 DOM 、 没有节点的 API( 节点助手居住) @bridge-ds/core/node: 它运行在 Figma 插件沙盒、 浏览器、 节点或 MCP 中
服务器。 DS Bridge Figma 插件 (apps/figma-plugin) 在其上; 一个 CLI 和一个 MCP 服务器可以是
我也一样。 这里没有硬码存储器: 呼叫者通过一个 BridgeConfig (通常情况) bridge.config.json) (中文(简体) ).
import { loadConfig, buildTokenSet, layoutOptions, validateSet, parseContrastChecks } from '@bridge-ds/core';
已出版的建造船舶ES模块和类型声明 dist/ (单位:千美元)npm run build:packages) (中文(简体) ). 里面这个
单曲 source 导出条件解决了 TypeScript 源, 所以不需要构建
先说 测试 : npx vitest run --project core (部分为根) npm test) (中文(简体) ).
类型检查 : npx tsc --noEmit -p packages/core。 。 。 .
等级
| 级别 | 文件( 下) tokens.root(中文(简体) ) | 模式 | 5月别名 |
|---|---|---|---|
primitive | primitives/*.tokens.json | 单身("value"(中文(简体) ) | 原始人 |
brand | brands/<brand>.tokens.json | 每个品牌一个 | 原始人 |
base | semantic/base.tokens.json | 单人 | 原始人(允许的识字) |
semantic | semantic/<theme>.tokens.json | 每个主题一个 | 颜色 : palette.* (或 color.alpha.*其他:品牌角色或原始人 |
density | density/<density>.tokens.json | 一个密度 | 原始人 |
component | components/*.tokens.json | 单人 | 语义、基础、密度、品牌角色、原始尺度步骤;从不调色板角色或原始颜色 |
| 覆盖 | brands/<brand>.<theme>.tokens.json | 品牌 x 主题 | 与语义相同; 必须覆盖已存在的语义符号 |
配置
bridge.config.json 在寄存器根: 1 文件 和一个 schema ()packages/core/bridge.config.schema.json, (中文(简体) ),
也导出为 @bridge-ds/core/bridge.config.schema.json)用于插件、文件站点、CLI和MCP
服务器。 条形: repo, (中文(简体) ), tokens (单位:千美元)root, (中文(简体) ), include, (中文(简体) ), exclude, (中文(简体) ), tiers,命令 layers 与 {mode}
占位符和 optional, (中文(简体) ), modes (名称 - > { values, default, parity }, (中文(简体) ), contrast (单位:千美元)path, (中文(简体) ), modes, (中文(简体) ),
components, (中文(简体) ), docs, (中文(简体) ), changesets, (中文(简体) ), cssVar, (中文(简体) ), governance (单位:千美元)protectedBranches, (中文(简体) ), branchPrefix, (中文(简体) ), labels, (中文(简体) ),
guardrails, (中文(简体) ), owners: { design, tech }, (中文(简体) ), changes (单位:千美元)"suggest",默认值,或 "direct"和 storybook
(单位:千美元){ url },https) (中文(简体) ). 较旧的平面形式(tokens.primitives, (中文(简体) ), modes.brands.)仍载.
const CONFIG_FILE = 'bridge.config.json';
interface BridgeConfig {
repo: { owner; name; defaultBranch } | undefined;
tokens: TokenPaths & { include; exclude; tiers: Record<string, string[]>; layers: { files; optional }[] };
axes: Record<string, { values; default; parity }>; // canonical modes
modes: { brands; themes; densities; defaults }; // brand/theme/density view for the tier model
contrast: { path; modes? } | undefined;
components?: { dir; docsSuffix; styleSuffix; reference?; index? };
docs; changesets: { dir; package } | undefined; changeset?: { package };
cssVar: { prefix; separator };
governance: { protectedBranches; branchPrefix; labels; guardrails; owners: { design: string[]; tech: string[] } };
changes: 'suggest' | 'direct'; // how changes reach the code (default 'suggest')
storybook?: { url: string };
}
function defineConfig(input): BridgeConfig; function loadConfig(source): BridgeConfig; // ConfigError { problems }
function toConfigJson(config): object; // canonical JSON (what `bridge init` writes)
function protectedBranchesOf(config); function baseBranchOf(config); function tokensPath(config, rel?);
function changesMode(config): 'suggest' | 'direct'; function storybookUrl(config): string | undefined; // storybook.url, else previews.production.storybook
施政
function assertSafeBranch(branch, { protectedBranches?, base?, branchPrefix? }): void; // ProtectedBranchError
const DEFAULT_PROTECTED_BRANCHES = ['main', 'master'];
GitHub客户端和当地的git作家都称它:没有Bridge表面写给受保护的分支.
分层集(CLI和MCP)
new LayeredTokenSet(config, files: Map<relPath, text>); // combos(), view(combo), resolve(path, combo), tierOf(path), cssVarName(path)
function validateLayered(set): LayerIssue[]; // DTCG shapes, names, aliases per combo, missing layers, mode parity
function runLayeredContrast(set, pairs, modes?); function contrastDelta(before, after);
function applyTokenEdits(set, edits: TokenEdit[]): { files; touched; notes }; // set, add, remove, rename; minimal diffs
function coerceValue(input, type?, existing?); // "#ff5500", "12px", "150ms" -> the repo's DTCG form
function diffLayered(before, after); function layeredImpact(before, after, changes);
function classifyLayered(changes, otherFiles?, config?); // classifyRisk underneath
function composeProposalBody(input); function changeTable(changes); function contrastDeltaTable(deltas);
@bridge-ds/core/node (仅节点): git, (中文(简体) ), isGitRepo, (中文(简体) ), currentBranch, (中文(简体) ), branchExists, (中文(简体) ), showFile, (中文(简体) ), listFilesAt, (中文(简体) ),
originRepo, (中文(简体) ), commitToNewLocalBranch (在新分行上投放;工作树、指数和结账没有改变),
fsSource(root, ref?) 财务报告和审定财务报表 localRepoRef(root) 联合国 RepoSource 在一次退票时,见repo模型.
类型
type Tier = 'primitive' | 'brand' | 'base' | 'semantic' | 'density' | 'component';
const TIER_ORDER: Tier[]; // dependency order
const TIER_AXIS: Record<Tier, 'brand' | 'theme' | 'density' | undefined>;
const TIER_NAMES: Record<Tier, string>; // "Primitives", "Brand", "Base", "Semantic", "Density", "Component"
const SINGLE_MODE = 'value'; // mode key of single-mode tiers (alias PRIMITIVE_MODE)
interface LogicalToken { id; path; type; tier; values: Record<mode, unknown>; description; scopes; files: Record<mode, file> }
interface ThemeOverride { brand; theme; path; type; value; file }
interface RepoLayout { primitiveFiles; brands; baseFiles; themes; overrides; densities; componentFiles }
function isMultiMode(tier: Tier): boolean;
function modeDisplayName(mode: string): string; // "light" -> "Light"
json-ast和dtcg-codec(最小编辑)
保留格式的 JSON 解析器: 未激活的文件序列化字节为字节; 编辑过的符号保存密钥 顺序、缩进、内线或多行布局和数字拼写.
function parseJson(text: string): JsonDocument;
function serializeJson(doc: JsonDocument): string;
function parseTokenFile(file: string, text: string): TokenDocument;
function serializeTokenFile(doc: TokenDocument): string;
function flattenTokens(doc: TokenDocument): FlatToken[]; // $type inherited from groups
function readTokenAt(doc, path): FlatToken | undefined;
function upsertToken(doc, path, fields: { type; value; description; extensions? }, template?): boolean; // false when nothing changed
function removeToken(doc, path): boolean; // prunes empty groups
function moveToken(doc, from, to): boolean; // keeps every field
function emptyTokenFile(file): TokenDocument;
数值和范围
function isAlias(v): v is string; function aliasTarget(v: string): string; function toAlias(path): string;
function parseColor(v): Rgba | undefined; function rgbaToDtcg(c: Rgba): object; function rgbaToHex(c): string;
function parseDimension(v): { value: number; unit: string } | undefined;
function valuesEqual(type, a, b): boolean; // colors by 8-bit hex + alpha, numbers to 1e-4
function formatValue(type, v): string; // "palette.primary.600", "#4b5562", "16px"
function defaultScopes(path, type, tier): string[]; // Figma scopes inferred from path and type
function effectiveScopes(t): string[];
符号集( 装入量)
function buildTokenSet(files: Record<relPath, text>, options?: LayoutOptions): TokenSet;
function layoutOptions(config: BridgeConfig): LayoutOptions; // tier folders + mode order from the config
function detectLayout(files: string[], options?: LayoutOptions): RepoLayout;
function modesOf(layout, tier): string[]; // ["bridge", "ocean"], ["light", "dark"], ["value"]...
function modeFile(layout, tier, mode): string | undefined;
function defaultFile(tier, path, dirs?): string; // where a new single-mode token goes
function defaultContext(set): ResolveContext; // first brand, theme, density, with overrides
function contextFor(set, tier, mode): ResolveContext;
interface TokenSet { tokens; byPath; docs; layout; options; overrides: ThemeOverride[]; overrideIndex; problems: string[] }
解析器(跨层级的异名)
interface ResolveContext { brand?; theme?; density?; overrides?: Map<string, unknown> }
function resolve(index: Map<path, LogicalToken>, path, ctx): { value?; chain: string[]; via: ('token' | 'override')[]; error?: 'cycle' | 'broken' | 'missing-mode'; at? };
function valueIn(t: LogicalToken, ctx): { value; via };
function findReferenceProblems(index, axes: { brand?: string[]; theme?: string[]; density?: string[] }): ReferenceProblem[];
语义符号在上下文的"品牌x"主题有"一"时取出"一"的"一"字.
wcag (续)
const CONTRAST_CHECKS_FILE = 'contrast.checks.json';
function parseContrastChecks(text): ContrastPair[]; // { pairs: [[fg, bg, min], ...] }; kind = min >= 4.5 ? 'text' : 'ui'
function contrastScope(set): ContrastScope; // every brand x theme, default density, overrides
function evaluatePairs(index, pairs, scope): ContrastResult[]; // { pair, brand, theme, ratio, level, error?, steps }
function contrastRatio(fg, bg): number; function contrastLevel(ratio, kind, min?): 'AAA' | 'AA' | 'fail';
function renderedColor(v): Rgba | undefined; // hex wins over components, like tokens.css
function contextLabel(r): string; // "Ocean dark"
function pairKey(r): string;
steps 列出两种颜色都解开的每个符号,这就是一个变化是如何找到对的
影响(见 affectedContrast) (中文(简体) ).
验证器(护栏)
function validateSet(set, pairs): { issues: Issue[]; contrast: ContrastResult[] };
function validateProposal(proposed, head, pairs, typeChanges?): { blocking; warnings; contrastBefore; contrastAfter };
function shadowedEdits(set, edits: { path; tier; modes }[]): Issue[]; // semantic edits a brand override hides
type IssueCode = 'file-problem' | 'raw-value' | 'alias-tier' | 'broken-reference' | 'alias-cycle' | 'all-scopes'
| 'missing-mode' | 'override-orphan' | 'override-shadowed' | 'contrast' | 'contrast-unresolved' | 'type-change';
基础分支上已经存在的问题作为警告再次出现,所以只有变化会带出块.
id-map and diff-engine (三道diff) 互联网档案馆的存檔,存档日期2013-12-21
function threeWayDiff(base?: Map<id, LogicalToken>, edited: Map, head: Map): { local; remote; conflicts; unchanged };
function toMap(tokens): Map<id, LogicalToken>;
function fieldChanges(a, b): FieldChange[];
function reconcileIds(edited: LogicalToken[], git: LogicalToken[]): { tokens; adoptedByName; suggestions: RenameSuggestion[] };
function applyConfirmedRenames(tokens, confirmed): LogicalToken[];
function idExtensionFor(t): string | undefined; // "com.dsbridge.id" only after a rename
作曲( 回写更改)
interface AcceptedChange { target?: LogicalToken; current?: LogicalToken } // target undefined = remove
function composeFiles(head: TokenSet, originals: Record<relPath, text>, changes): { files; allFiles };
每个值都转到其分级和模式的文件;只返回已更改的文件.
风险
type RiskTier = 1 | 2 | 3;
function classifyRisk(input: { tokenChanges?; files?: { path; status? }[]; config? }): { tier; label; reasons: string[]; bump?: 'patch' | 'minor' | 'major' };
function tokenBump(changes); function isGuardrail(path, config?);
const RISK_LABELS: Record<RiskTier, string>;
插件的分类器,Docs站点,CLI和MCP服务器的分类器. 规则(从
docs/GOVERNANCE.md,最高胜负):第3级,用于任何已添加、已更改的令牌(价值、类型、范围)、更名或
在任何一级或任何一级被删除, *.tokens.json 文档,当其符号更改未知时,则守护符
文档(governance.guardrails对比检查, bridge.config.json, (中文(简体) ), .github/**) (中文(简体) ). 第二级组件
来源 components.dir 和未知源文件。 仅用于描述符号编辑的第1级, Docs,
*.md故事, 说:, *.docs.json测试和更改。 弹出:清除和重命名 major,其他符号
变动 minor,仅说明 patch。鼠标更改可以是 AcceptedChanges 或 (简体中文) { kind, path, descriptionOnly? } 总结.
pr- 组合和更改
function composePrBody(input: { changes; head; proposed; validation; baseBranch; headSha; baseSha; origin: PrOrigin; title; notes; upstreamPaths; resolvedConflicts }): string;
interface PrOrigin { tool: string; surface: string; location?: string; authoredBy: string }
function affectedContrast(change, before: ContrastResult[], after: ContrastResult[]): { before?; after? }[];
function changedModes(change): Set<string> | undefined;
function defaultTitle(changes): string; function branchName(slug, date): string; function slugify(text, max?): string;
function commitMessage(title, changes, footer?): string;
function changesetBump(changes): 'minor' | 'major';
function composeChangeset(changes, { title, branch, packageName, source? }): { path; content };
主体有一个变化表(按下、分级、旧 - > 每个模式的新,对比度在 - > 之后),对比度
影响表、护栏清单和风险等级。 当一对已更改的符号
前景或背景在品牌x主题中直接或通过该符号或别名解决
使用已更改模式的地方(PR # 4回归: 正在更改) color.bg.default 列出其中的每一对.
github 客户端
new GitHubClient(repo: 'owner/name', token: string, fetchImpl?: FetchLike, retry?: RetryPolicy);
// refs and git data
getRepo(); getBranchSha(branch); getCommitTree(sha); getTree(treeSha, recursive?); getBlobText(sha);
createBlob(text); createTree(baseTree, files); createCommit(message, tree, parents); createBranch(name, sha); updateBranch(name, sha);
compare(base, head);
// contents API
getFileText(path, ref?): Promise<string | undefined>; putFile({ path, content, branch, message, sha? }): Promise<commitSha>;
// pull requests, reviews, checks, labels
createPullRequest({ title, head, base, body, draft }); getPullRequest(n); findOpenPullRequest(branch); updatePullRequest(n, patch);
listPullRequestFiles(n); listReviews(n); createReview(n, { event, body });
listCheckRuns(ref); createCheckRun({ name, headSha, status?, conclusion?, output? }); // check runs need a GitHub App token
addLabels(n, labels); removeLabel(n, label); addComment(n, body);
// whole token set at a commit, honoring bridge.config.json in the repo
loadRepoFiles(client, commitSha, fallbackTokensPath): Promise<{ files; contrastChecks; config?; tokensPath; warnings }>;
读取和内容地址重试网络错误, 5xx和二次费率限制; 错误
变成 GitHubError { status, message, detail } 有简单语言的信息.
建议(建议t、建议审查t、建议github.ts)
作为 GitHub 问题而不是分支存档的更改,所以所有者只需写出问题 。 可读 Markdown, 然后是 a
jSON 载荷bridge.suggestion/1以标记表示其犬形的sha256;符号变化是
编辑(路径和值),其他文件全部内容,前后使用 git blob shas 。 不适合的内容
主体(65,536个字符)到继续评论,最多8个。 评论是与有效载荷sha绑定的
并且只从指定的所有者中计数.
composeSuggestionIssue(payload, { labels?, assignees?, state?, details? }): { title; body; labels; assignees; parts: string[]; sha };
parseSuggestionIssue(body, { comments?, author? }): { ok: true; payload; sha; markedSha; edited; parts } | { ok: false; reason; message };
suggestionPayloadSha(payload); canonicalJson(value); sha256Hex(text); gitBlobSha(text);
suggestionLabels(payload, { state?, labels? }); suggestionIssueTitle(payload); suggestionStatus({ state, stateReason?, linkedPrs?, review?, applied?, outdated? });
suggestionPathProblems(payload, config): string[]; unsafePathProblem(path): string | null;
summarizeSuggestionApprovals(comments, { owners, rights?, teams?, soloOwnerCanApproveBoth? }, { payloadSha, author? }); suggestionReviewState(tier, approvals);
composeSuggestionReviewComment(record); parseSuggestionReviewComment(body); composeSuggestionAppliedComment(record); parseSuggestionAppliedComment(body);
// GitHub (Issues read and write only)
createSuggestionOnGitHub(gh, payload, opts); listSuggestionsOnGitHub(gh, { state? }); getSuggestionOnGitHub(gh, n, gov, { outdated? });
reviewSuggestionOnGitHub(gh, n, { event, role?, message?, payloadSha? }, gov); linkSuggestionPrOnGitHub(gh, n, { pr?, branch?, commit?, payloadSha });
declineSuggestionOnGitHub(gh, n, reason, by?); syncSuggestionStateLabel(gh, n, labels, status);
故事书(故事书.ts)
读取一个已部署或已建的故事书,而无需重写: index.json (v4为"故事集"7,v5为"8"并后作"),其他
stories.json (v3) (英语). 条目按标题归类为组件( name = 最后一个标题段); 测试条目退出
联 合 国 stories。一个404,一个HTML的回答,来自一个返回到 index.html,或者没有条目的天体移动到
下一个文件。 错误带有代码 : invalid-url, (中文(简体) ), not-found, (中文(简体) ), not-json, (中文(简体) ), private (署名墙壁,色谱登录)
答复,第401/403号, empty, (中文(简体) ), http, (中文(简体) ), network。纯净,注射 fetch· ; @bridge-ds/visual 使用解析器
storybook-static/index.json 和用于捕获的 iframe URL 构建器.
fetchStorybookIndex(base, { fetch?, signal? }): Promise<{ version; source: 'index.json' | 'stories.json'; entries; components }>;
parseStorybookIndex(json, source?); groupStorybookComponents(entries): { title; name; group; stories; docs; tags }[];
normalizeStorybookUrl(pasted): string; // https only (http on localhost), drops ?path=, /index.html, /iframe.html
storybookIframeUrl(base, id, { viewMode?, globals?, args? }); storybookManagerUrl(base, id, viewMode?); storybookIndexUrls(base);
repo模型(repo-source.ts,repo-model.ts,指代-row.ts,对比-模型.ts,组件-scan.ts)
所有文件网站和工作室 从一个设计系统检索到的 RepoSource因此,建筑(当地建筑)
取出)和浏览器(任何团队在GitHub上的回放)运行相同的代码. bridge.config.json 解析一次; 每
文件夹来自它( e)tokens.root 和分级的文件夹, contrast.path, (中文(简体) ), components.dir|index|specs, (中文(简体) ),
tokens.usage),以此repo的前路径作为默认路径(REPO_MODEL_DEFAULTS) (中文(简体) ). Repo 内容从未丢出: 不好
配置、 docs.json 或别名, 或一个文件, 来源拒绝作为太大的 (413), 降落在 problems; 利率限制或
网络出错仍会丢出,以便调用者可以重试.
interface RepoSource { ref: { owner; repo; sha }; list(prefix?): Promise<string[]>; text(path): Promise<string | null> }
memorySource(files, ref?); readRepoTexts(source, paths, concurrency?, onError?); // fsSource(root, ref?) in @bridge-ds/core/node
// gitHubSource(client, sha, opts?) (repo-source-github.ts) is the same RepoSource over GitHub; every list() is sorted.
loadRepoModel(source, { components?, href?, concurrency? }): Promise<RepoModel>;
// RepoModel: { ref, configText, config, site: SiteRepo, problems, tokens: { root, files, rows, usage },
// contrast: { path, specs, pairs }, components: { dir, index, families, list } | null, specs: { path, file, coverage } }
siteRepoFromConfig(config, raw?, fallback?); parseModelConfig(text);
buildTokenRows(config, readText, listFiles); tokenRowIndex(rows); tokenRowAxes(config, readText?); tokenRowFiles(config);
parseContrastSpecs(text); evaluateContrastPairs(specs, rows); hexContrastRatio(a, b);
scanComponents(input); parseComponentTsx(name, src); parseComponentCss(src, labels, describeVar);
parseComponentStories(src); parseComponentFamilies(indexSrc, componentsRel?); resolveInheritedTokens(list);
历史沿革 (历史沿革,历史沿革,历史沿革)
代号上的变化,何时,谁改变了,为什么,如何安全地解除.
// model
interface HistoryEntry { id; sha; baseSha?; date; author; title; why; pr?; changes: LayeredChange[]; counts; tier; bump; breaking; reasons; changesets; version?; bulk?; demo? }
function buildHistoryEntry({ config, commit, before, after, changesets? }): HistoryEntry | null;
function collectHistory(config, backend: HistoryBackend, { ref, limit }): Promise<HistoryEntry[]>;
// backends: GitHub REST (browser or Node) and local git (Node, @bridge-ds/core/node)
function gitHubHistoryBackend(client, config); function loadGitHubHistory(client, config, { ref?, limit? }): Promise<HistoryReport>;
function localGitHistoryBackend(root, config); function loadLocalHistory(root, config, { ref?, limit? }): Promise<HistoryReport>;
// versions: CHANGELOG sections and tags; the timeline of design system versions
function parseChangelog(text); function releasesFromTags(tags, pkg?); function assignVersions(entries, releases); function versionTimeline(entries, releases?);
// reading
function filterHistory(entries, { token?, author?, tier?, version?, breaking?, since?, until?, query? });
function tokenHistory(entries, path, config?): TokenHistoryItem[]; // every change of one token, renames followed
function fileModes(config, file); function modeLabel(modes); // semantic/dark.tokens.json -> { theme: "dark" } -> "Dark"
// planning (never writes)
function planRevert({ current, entry, later?, pairs?, resolutions? }): ChangePlan;
function planRestore({ current, path, file?, value, label?, item?, pairs? }): ChangePlan;
function planToJson(plan); // a patch-like JSON for people without a token
function demoHistory(config, currentFiles): HistoryReport; // fixture entries, flagged demo, never real
本地历史跟随裁判的第一个父,所以合并的分支是一条目(合并承诺针对 gitHub 历史向每个承诺询问其拉动请求,并显示 PR 的合并承诺. 批量条目(超过60个令牌更改:导入或重组)被标记.
归来不是瞎子 git revert。 。 。 . planRevert 根据当前基准计算反向符号编辑
分支 : 后期再次更改的符号( s)changed-later页:1removed-later回来
(单位:千美元)recreated-later),移动(renamed-later)或者其他代名词(still-referenced是一种冲突,
与后面的改动一起列出,这些改动解释并保持原样,除非 resolutions[key] 实值 "use-before"。 。 。 .
已撤销的更改被跳过 。 剩下的都过去了 applyTokenEdits (最小diffs),验证
对比门, classifyRisk 和任何提议一样 status 实值 ready, (中文(简体) ), blocked (新设)
验证错误或失败的对比对)或 nothing-to-do。公关机构从“Reverts #n”开始
冲突表.
审计@bridge-ds/core/audit(中文(简体) )
设计系统采用并漂移在一个消耗DS的产品编码库中. 纯 (文件文本输入, 报告)
它读取 TSX/JSX, 以及Astro、 Vue 和 Svelte 文件的前题和脚本, 有 TypeScript
编译器 API(只使用语法),这就是为什么它是自己的条目,而Figma插件从不加载它. @bridge-ds/core/node 添加磁盘侧.
import { DesignSystemIndex, buildAuditReport, compareWithBaseline, auditMarkdown, planCssFixes, auditFile } from '@bridge-ds/core/audit';
import { loadDesignSystem, runAudit, collectAuditFiles, fixCss, findDesignSystemRoot, loadAllowlist } from '@bridge-ds/core/node';
const ds = loadDesignSystem('/path/to/ds-repo'); // bridge.config.json: tokens in every mode, components, packages
const report = runAudit('apps/admin/src', { ds: ds.root, label: 'admin', baseline }); // AuditReport, schemaVersion 1
- 扫描: CSS、SCSS、减分CSS模块;
style,毛里求斯sx, (中文(简体) ),styled(), (中文(简体) ),makeStyles, (中文(简体) ),createTheme和主题 对象, 有样式的组件/ 情感模板; Tailwind类字符串(className, (中文(简体) ),cn(), (中文(简体) ),clsx(), (中文(简体) ),cva(), (中文(简体) ),@apply); 代码中的任何颜色文字. Astro、Vue和Svelte文件:前题和<script>块为 TS, (中文(简体) ),<style>块作为 CSS/SCSS/Less,以及模板标记(tags,style财务报告和审定财务报表class属性,静态style="...", (中文(简体) ),style={{ ... }}单:style,斯维尔特style:prop,颜色属性,例如fill="#...") (中文(简体) ). - 硬码值: 颜色(hex, rgb, hsl, 命名, 赤裸 HSL 通道), 间隔, 大小, 弧度, 边框宽度,
影相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相 每个都得到最接近的标志:
在 OKLab 中以 deltaE 为单位的颜色, 跨越每个模式( 符合属性的语义符号和符号赢得了近五十个),
长度按最接近的尺度级,并带有置信度(
exact, (中文(简体) ),high, (中文(简体) ),medium, (中文(简体) ),low) (中文(简体) ). - 调用引用数字 :
var(--x)的 DS 符号( 也用 Tailwind 任意值)。 其他变量, MUI 调色板 路径,theme.spacing()和 Tailwind Stale 类算作对另一个主题的引用,而不是硬码. - 构成部分: 从DS包中导入的JSX实例(
audit.packages,默认值:components.dir附加时@bridge-ds/react对外国UI库(MUI,反应-admin,Atd,Chakra,Radix, 无头UI,Mantine,Shadcn/ui本地组件.),应该为DS组件的本地组件 (单位:千美元)button, (中文(简体) ),input, (中文(简体) ),select, (中文(简体) ),textarea, (中文(简体) ),dialog, (中文(简体) ),table, (中文(简体) ),a与href, (中文(简体) ),img),路由器链接(反应-路由器, 半径LinkBase,下个/链接),除非作为DS组件通过render元素,图表库(目录, Nivo, Chart.js.: 外相而无DS等同)和以DS组件命名的本地组件. 供应商和 其他非视觉部分从不计数,包括DS部分。 在Astro、Vue和Svelte模板中,标签是一个DS组件 当前题或<script>从DS软件包中导入( Vue kebab 例)<ds-button>包括);当地Button.astro, (中文(简体) ),Button.vue或者说Button.svelte是重新创建的 DS 组件.<input type="hidden">,锚 无href里面的东西<noscript>非UI 实例. - 逃生舱数字 :
bridge-audit-ignore-next-line: reason在任何评论中<!-- -->, (中文(简体) ),{/* */}, (中文(简体) ),/* */, (中文(简体) ),//)将下行的定论从计数中留出. 需要说明理由:没有理由,或 下一行没有找到, 没有忽略任何东西, 文件将它列在下面ignoreErrors许可列表 (单位:千美元)runAudit(..., { allowlist: loadAllowlist(path) }), (中文(简体) ),{ "entries": [{ "file", "line", "what"?, "reason" }] }已经 对已知文件的相同: 线性违规。 被忽略的项目保留在报表中( E)files[].ignored, (中文(简体) ),ignored.items, (中文(简体) ), ; 无匹配的允许列表条目在ignored.staleAllowlist。 。 。 . - 计量: 符号采纳 = 符号引用 / (收录引用 + 硬码值); 组件采纳 = DS 实例 / 所有UI 实例 。 按类别,顶部文件,顶部修正,每个文件的发现有行号.
- 基线数字 :
compareWithBaseline(report, previous)每公吨、类别和文件增加三角洲,并携带 历史.auditMarkdown(report)作总结.planCssFixes(text, lang, ds)是安全的自定义 : CSS 值等于一个符号var(--token)。 。 。 .
报告计划是 packages/core/audit-report.schema.json (也导出为
@bridge-ds/core/audit-report.schema.json) (中文(简体) ). bridge.config.json 选择 audit 节:
packages, (中文(简体) ), foreignLibraries, (中文(简体) ), nativeElements, (中文(简体) ), exclude。 。 。 .
组件规格( e)component-spec.ts,生成器在 @bridge-ds/core/node(中文(简体) )
对设计工具可以重建的编码组件的宣告性描述:可变轴,TEXT和BOOLEAN 属性、部件(框架、文本、带有自动布局的图标)以及每个变体,每个填充、中键、, 半径、 粘贴、 间隙、 大小和文本属性 。 DS Bridge Figma 插件将它牵引为组件集绑定在变量上.
import { parseComponentSpecs, variantKeyOf, type ComponentSpec } from '@bridge-ds/core';
import { generateRepoComponentSpecs, serializeComponentSpecs } from '@bridge-ds/core/node';
const file = generateRepoComponentSpecs('/path/to/repo', ['Button']); // reads bridge.config.json, tokens, TSX, CSS modules
从代码中衍生出来,从未手持: npm run specs 写入 packages/react/component-specs.json (路径 :
components.specs 在图文中,和 packages/core/test/component-specs.test.ts 过期时失败 .
生成器使用 TypeScript 解析器读取组件( props 接口, 默认, 它返回给定的 JSX)
道具,象图标等嵌入式DS组件并运行一个小型CSS级联(spec-css.ts: 类,属性, :hover, (中文(简体) ),
:active, (中文(简体) ), :not(), (中文(简体) ), :has()组合器, @media (hover: hover),特异性,继承,风俗财产).
改变样式的联盟道具成为轴; a State 轴列表显示的状态( Hover、 按住、 已禁用)
不一样 非符号值( A)calc()它不抽取的道具和道具列于 unmapped。 。 。 .
可移动部件携带a swap (INSTANCE SWAP 属性名称,默认组件,选项)和每个变体列出
显示于 slots数字 :
- 图标部件
LucideIcon道具)默认图标预览文件,然后是AllStates故事,传到 道具(else Plus,用于徽章的信息). 档案icons区域持有 24x24 SVG (stroke="currentColor"(中文(简体) ) 每个图标的插槽默认,每个图标组件的文档和故事参考,以及一个通用的集 (单位:千美元)COMMON_ICONS),从安装中读取lucide-react;一个Lucide图标的别名会折叠成所见的第一个名字.iconStyle命名图标组件本身的符号(大小、中风颜色、中风宽度). - 复合部分的文本, 代码在某个变体中画出全血( 无内嵌活字: 卡
padding="none"是一个 内容槽 :Slot/<Component> <part> text或者说Slot/Media媒体的血流成河 这个slots节 描述两个组件.