@usefragments/core 1.4.0 → 1.5.1
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/{chunk-CBSNXFOD.js → chunk-AOG4FTV6.js} +146 -6
- package/dist/chunk-AOG4FTV6.js.map +1 -0
- package/dist/{chunk-57QDBEHQ.js → chunk-ZHS52OT4.js} +3 -9
- package/dist/chunk-ZHS52OT4.js.map +1 -0
- package/dist/codes/index.d.ts +2 -2
- package/dist/codes/index.js +2 -2
- package/dist/compiled-types/index.d.ts +1 -1
- package/dist/generate/index.d.ts +1 -1
- package/dist/{governance-DxdJV6lx.d.ts → governance-B88uR3Zq.d.ts} +229 -1
- package/dist/{index-0lmh0Lbo.d.ts → index-DbkPE46t.d.ts} +48 -8
- package/dist/index.d.ts +779 -158
- package/dist/index.js +674 -127
- package/dist/index.js.map +1 -1
- package/dist/react-types.d.ts +1 -1
- package/dist/registry.d.ts +18 -18
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/test-utils.d.ts +1 -1
- package/package.json +1 -1
- package/src/agent-format.test.ts +1 -0
- package/src/canonical-bridge.ts +46 -0
- package/src/canonical-direction.ts +118 -0
- package/src/codes/codes.ts +18 -0
- package/src/conform.ts +5 -0
- package/src/contract/preimage.test.ts +40 -0
- package/src/contract/preimage.ts +20 -0
- package/src/effective-governance-inputs.test.ts +52 -0
- package/src/effective-governance-inputs.ts +106 -0
- package/src/facts/builders.ts +70 -2
- package/src/facts/compile.ts +20 -2
- package/src/facts/fact-index.ts +4 -0
- package/src/facts/facts.test.ts +30 -0
- package/src/facts/index.ts +6 -0
- package/src/facts/types.ts +86 -7
- package/src/governance-integrity.test.ts +22 -0
- package/src/governance-integrity.ts +10 -4
- package/src/governance.test.ts +93 -0
- package/src/governance.ts +76 -0
- package/src/identity/classify.test.ts +185 -0
- package/src/identity/classify.ts +257 -0
- package/src/identity/component-key.test.ts +32 -0
- package/src/identity/component-key.ts +35 -0
- package/src/identity/usage.ts +39 -0
- package/src/index.ts +48 -0
- package/src/rules/__tests__/fix-emission-invariant.test.ts +35 -4
- package/src/rules/components-prefer-library.test.ts +151 -0
- package/src/rules/components-prefer-library.ts +46 -4
- package/src/rules/components-shadow-component.test.ts +145 -0
- package/src/rules/components-shadow-component.ts +81 -0
- package/src/rules/fix-availability.ts +2 -0
- package/src/rules/index.ts +14 -0
- package/src/rules/jsx-preferred-import-path.ts +45 -9
- package/src/rules/rules.test.ts +202 -6
- package/src/rules/spacing-resolution.ts +2 -2
- package/src/rules/styles-no-raw-color.test.ts +6 -1
- package/src/rules/styles-no-raw-color.ts +3 -2
- package/src/rules/styles-no-raw-dimensions.ts +5 -7
- package/src/rules/styles-no-raw-spacing.ts +5 -2
- package/src/rules/styles-no-raw-typography.ts +7 -4
- package/src/rules/taxonomy.test.ts +19 -1
- package/src/rules/tiers.ts +9 -5
- package/src/rules/token-candidates.ts +36 -0
- package/src/rules/tokens-require-dual-fallback.ts +2 -1
- package/src/rules/tokens-upstream-drift.test.ts +111 -0
- package/src/rules/tokens-upstream-drift.ts +57 -0
- package/src/rules/utils.ts +22 -14
- package/src/schema.ts +28 -0
- package/src/schemas/index.ts +5 -8
- package/src/token-types.ts +71 -1
- package/src/types.ts +18 -0
- package/dist/chunk-57QDBEHQ.js.map +0 -1
- package/dist/chunk-CBSNXFOD.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
bridgeSourceViolations,
|
|
50
50
|
byCode,
|
|
51
51
|
byRuleId,
|
|
52
|
+
canonicalBridgeV1Schema,
|
|
52
53
|
canonicalJson,
|
|
53
54
|
compileComponentFacts,
|
|
54
55
|
compileGlobalGovernanceFacts,
|
|
@@ -71,6 +72,8 @@ import {
|
|
|
71
72
|
makeClassNameDynamicFact,
|
|
72
73
|
makeClassNameLiteralFact,
|
|
73
74
|
makeComponentCapabilityFact,
|
|
75
|
+
makeComponentDefinitionFact,
|
|
76
|
+
makeComponentIdentityFact,
|
|
74
77
|
makeComponentMetadataFact,
|
|
75
78
|
makeContractTokenFact,
|
|
76
79
|
makeJsxComponentPreferredFact,
|
|
@@ -109,7 +112,7 @@ import {
|
|
|
109
112
|
ownedImportsEqual,
|
|
110
113
|
resolveComponentGovernance,
|
|
111
114
|
scaleGovernanceRecordSchema
|
|
112
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-AOG4FTV6.js";
|
|
113
116
|
import {
|
|
114
117
|
AGENT_FORMAT_SCHEMA_VERSION,
|
|
115
118
|
agentErrorEnvelopeSchema,
|
|
@@ -134,7 +137,7 @@ import {
|
|
|
134
137
|
suppressionDirectiveSchema,
|
|
135
138
|
validatorResultSchema,
|
|
136
139
|
violationSchema
|
|
137
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-ZHS52OT4.js";
|
|
138
141
|
import {
|
|
139
142
|
OWNED_PACKAGE_IDENTITY_EPOCH,
|
|
140
143
|
OWNED_PACKAGE_IDENTITY_SOURCE_SHA256,
|
|
@@ -1685,6 +1688,14 @@ var tokenConfigSchema = z4.object({
|
|
|
1685
1688
|
// vocabulary seeds the known-token set (#7c). A packages-only tokens block
|
|
1686
1689
|
// is valid — see the superRefine below.
|
|
1687
1690
|
packages: z4.array(z4.string().min(1)).optional(),
|
|
1691
|
+
aliases: z4.record(z4.string().min(1)).optional(),
|
|
1692
|
+
upstream: z4.array(
|
|
1693
|
+
z4.object({
|
|
1694
|
+
packageName: z4.string().min(1),
|
|
1695
|
+
version: z4.string().min(1).optional(),
|
|
1696
|
+
digest: z4.string().regex(/^[a-f0-9]{64}$/u).optional()
|
|
1697
|
+
})
|
|
1698
|
+
).optional(),
|
|
1688
1699
|
exclude: z4.array(repoRelativePathSchema).optional(),
|
|
1689
1700
|
themeSelectors: z4.record(z4.string()).optional(),
|
|
1690
1701
|
enabled: z4.boolean().optional(),
|
|
@@ -1776,7 +1787,18 @@ var fragmentsConfigSchema = z4.object({
|
|
|
1776
1787
|
})
|
|
1777
1788
|
).optional()
|
|
1778
1789
|
}).optional(),
|
|
1779
|
-
recognizedClassHelpers: z4.array(z4.string().min(1)).optional()
|
|
1790
|
+
recognizedClassHelpers: z4.array(z4.string().min(1)).optional(),
|
|
1791
|
+
identity: z4.object({
|
|
1792
|
+
decisions: z4.array(
|
|
1793
|
+
z4.object({
|
|
1794
|
+
component: z4.string().min(1),
|
|
1795
|
+
kind: z4.enum(["sanction", "reject", "dismiss"]),
|
|
1796
|
+
canonicalTarget: z4.string().min(1).optional(),
|
|
1797
|
+
reason: z4.string().optional(),
|
|
1798
|
+
decisionId: z4.string().min(1).optional()
|
|
1799
|
+
})
|
|
1800
|
+
).optional()
|
|
1801
|
+
}).optional()
|
|
1780
1802
|
});
|
|
1781
1803
|
var compositionMetadataSchema = z4.object({
|
|
1782
1804
|
pattern: z4.enum(["compound", "simple", "controlled", "wrapper"]).optional(),
|
|
@@ -4762,13 +4784,20 @@ function isExemptColor(value, except) {
|
|
|
4762
4784
|
}
|
|
4763
4785
|
return false;
|
|
4764
4786
|
}
|
|
4765
|
-
function tokenReference(
|
|
4766
|
-
if (
|
|
4767
|
-
|
|
4768
|
-
|
|
4787
|
+
function tokenReference(token) {
|
|
4788
|
+
if (token.referenceFormat === "css-var") {
|
|
4789
|
+
const cssVarName = [token.name, ...token.sourceNames ?? []].find(
|
|
4790
|
+
(name) => name.startsWith("--")
|
|
4791
|
+
);
|
|
4792
|
+
return cssVarName ? `var(${cssVarName})` : token.name;
|
|
4793
|
+
}
|
|
4794
|
+
if (token.referenceFormat === "scss-var") {
|
|
4795
|
+
return [token.name, ...token.sourceNames ?? []].find((name) => name.startsWith("$")) ?? (token.name.startsWith("--") ? `$${token.name.slice(2)}` : token.name);
|
|
4796
|
+
}
|
|
4797
|
+
return token.sourceNames?.[0] ?? token.name;
|
|
4769
4798
|
}
|
|
4770
4799
|
function isApplicableTokenReference(referenceFormat) {
|
|
4771
|
-
return referenceFormat ===
|
|
4800
|
+
return referenceFormat === "css-var" || referenceFormat === "scss-var";
|
|
4772
4801
|
}
|
|
4773
4802
|
|
|
4774
4803
|
// src/rules/a11y-required-accessible-name.ts
|
|
@@ -4925,6 +4954,77 @@ function isEnforceableHtmlEquivalent(args) {
|
|
|
4925
4954
|
return builtIn !== null && builtIn.canonical === args.canonical;
|
|
4926
4955
|
}
|
|
4927
4956
|
|
|
4957
|
+
// src/canonical-direction.ts
|
|
4958
|
+
function projectCanonicalDirectionConflicts(ix, canonicalSources) {
|
|
4959
|
+
const npmSources = canonicalSources.filter(
|
|
4960
|
+
(source) => source.kind === "npm"
|
|
4961
|
+
);
|
|
4962
|
+
if (npmSources.length === 0) return [];
|
|
4963
|
+
const identityByComponent = new Map(
|
|
4964
|
+
ix.byKind("component_identity").map((identity) => [identity.componentKey, identity])
|
|
4965
|
+
);
|
|
4966
|
+
const conflicts = [];
|
|
4967
|
+
for (const definition of ix.byKind("component_definition")) {
|
|
4968
|
+
if (!definition.exported || definition.renderRoot.resolution !== "canonical") continue;
|
|
4969
|
+
const target = npmTarget(definition.renderRoot.canonical, npmSources);
|
|
4970
|
+
if (!target) continue;
|
|
4971
|
+
const identity = identityByComponent.get(definition.componentKey);
|
|
4972
|
+
if (identity?.decisionId && decisionTargetsExport(identity.canonicalTarget, target.exportName)) {
|
|
4973
|
+
if (identity.state === "shadow") continue;
|
|
4974
|
+
if (identity.state === "variant" && identity.confidence === "confirmed") {
|
|
4975
|
+
conflicts.push({
|
|
4976
|
+
...target,
|
|
4977
|
+
wrapperComponentKey: definition.componentKey,
|
|
4978
|
+
wrapperFile: definition.file,
|
|
4979
|
+
wrapperExportName: definition.exportName,
|
|
4980
|
+
state: "sanctioned"
|
|
4981
|
+
});
|
|
4982
|
+
continue;
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
conflicts.push({
|
|
4986
|
+
...target,
|
|
4987
|
+
wrapperComponentKey: definition.componentKey,
|
|
4988
|
+
wrapperFile: definition.file,
|
|
4989
|
+
wrapperExportName: definition.exportName,
|
|
4990
|
+
state: "unresolved"
|
|
4991
|
+
});
|
|
4992
|
+
}
|
|
4993
|
+
return conflicts.sort(
|
|
4994
|
+
(left, right) => left.packageName.localeCompare(right.packageName) || left.exportName.localeCompare(right.exportName) || left.wrapperComponentKey.localeCompare(right.wrapperComponentKey)
|
|
4995
|
+
);
|
|
4996
|
+
}
|
|
4997
|
+
function canonicalDirectionConflictsTarget(conflicts, importPath, exportName) {
|
|
4998
|
+
if (!importPath) return false;
|
|
4999
|
+
return conflicts.some(
|
|
5000
|
+
(conflict) => ownedImportMatchesRoot(importPath, conflict.packageName) && conflict.exportName === exportName
|
|
5001
|
+
);
|
|
5002
|
+
}
|
|
5003
|
+
function npmTarget(canonicalTarget, sources) {
|
|
5004
|
+
const separator = canonicalTarget.lastIndexOf("#");
|
|
5005
|
+
if (separator <= 0 || separator === canonicalTarget.length - 1) return null;
|
|
5006
|
+
const importPath = canonicalTarget.slice(0, separator);
|
|
5007
|
+
const imported = canonicalTarget.slice(separator + 1).split(".").at(-1);
|
|
5008
|
+
if (!imported) return null;
|
|
5009
|
+
for (const source of sources) {
|
|
5010
|
+
if (!ownedImportMatchesRoot(importPath, source.specifier)) continue;
|
|
5011
|
+
const subpath = packageSubpath(importPath, source.specifier);
|
|
5012
|
+
const exportName = imported === "default" ? subpath.split("/").filter(Boolean).at(-1) : imported;
|
|
5013
|
+
if (!exportName) continue;
|
|
5014
|
+
if (source.exclude?.includes(exportName)) continue;
|
|
5015
|
+
if (source.include && !source.include.includes(exportName)) continue;
|
|
5016
|
+
return { packageName: source.specifier, exportName };
|
|
5017
|
+
}
|
|
5018
|
+
return null;
|
|
5019
|
+
}
|
|
5020
|
+
function packageSubpath(importPath, packageName) {
|
|
5021
|
+
return importPath === packageName ? "" : importPath.slice(packageName.length + 1);
|
|
5022
|
+
}
|
|
5023
|
+
function decisionTargetsExport(target, exportName) {
|
|
5024
|
+
if (!target) return true;
|
|
5025
|
+
return target === exportName || target.split("#").at(-1)?.split(".").at(-1) === exportName;
|
|
5026
|
+
}
|
|
5027
|
+
|
|
4928
5028
|
// src/rules/components-prefer-library.ts
|
|
4929
5029
|
var RULE_ID2 = "components/prefer-library";
|
|
4930
5030
|
var RULE_VERSION2 = "1";
|
|
@@ -5068,8 +5168,12 @@ function findClassNameReimpl(node, classTokensByNode, targets) {
|
|
|
5068
5168
|
function ruleComponentsPreferLibrary(ix) {
|
|
5069
5169
|
const policy = ix.policy.ruleConfig(RULE_ID2);
|
|
5070
5170
|
if (!policy?.enabled) return [];
|
|
5071
|
-
const
|
|
5072
|
-
const
|
|
5171
|
+
const configuredSources = canonicalSourcesFromPolicy(policy.options?.canonicalSources);
|
|
5172
|
+
const conflicts = projectCanonicalDirectionConflicts(ix, configuredSources);
|
|
5173
|
+
const sources = configuredSources.map((source) => suppressConflictedExports(source, conflicts));
|
|
5174
|
+
const mappings = canonicalMappingsFromPolicy(policy.options?.canonicalMappings).filter(
|
|
5175
|
+
(mapping) => !canonicalDirectionConflictsTarget(conflicts, mapping.importPath, mapping.name)
|
|
5176
|
+
);
|
|
5073
5177
|
if (sources.length === 0 && mappings.length === 0) return [];
|
|
5074
5178
|
const importsByFileAndLocal = indexImportsByFileAndLocal(ix);
|
|
5075
5179
|
const propsByNode = indexPropsByNodeId(ix);
|
|
@@ -5077,12 +5181,14 @@ function ruleComponentsPreferLibrary(ix) {
|
|
|
5077
5181
|
const classTokensByNode = indexClassTokensByNode(ix);
|
|
5078
5182
|
const reimplTargets = canonicalReimplTargets(sources, mappings);
|
|
5079
5183
|
const canonicalDirectoryResolvedNodes = indexCanonicalDirectoryResolvedNodes(ix, sources);
|
|
5184
|
+
const shadowRenderRootNodeIds = indexShadowRenderRootNodeIds(ix);
|
|
5080
5185
|
const findings = [];
|
|
5081
5186
|
const seenImportFixes = /* @__PURE__ */ new Set();
|
|
5082
5187
|
for (const node of ix.byKind("usage_node")) {
|
|
5083
5188
|
if (isCanonicalSourceImplementationFile(node.file, sources)) continue;
|
|
5084
5189
|
if (node.element.includes(".")) continue;
|
|
5085
5190
|
if (canonicalDirectoryResolvedNodes.has(node.id)) continue;
|
|
5191
|
+
if (shadowRenderRootNodeIds.has(node.id)) continue;
|
|
5086
5192
|
const props = propsByNode.get(node.id) ?? [];
|
|
5087
5193
|
const textChildren = textByNode.get(node.id) ?? [];
|
|
5088
5194
|
const importsForFile = importsByFileAndLocal.get(node.file);
|
|
@@ -5330,6 +5436,28 @@ function ruleComponentsPreferLibrary(ix) {
|
|
|
5330
5436
|
}
|
|
5331
5437
|
return findings;
|
|
5332
5438
|
}
|
|
5439
|
+
function suppressConflictedExports(source, conflicts) {
|
|
5440
|
+
if (source.kind !== "npm") return source;
|
|
5441
|
+
const names = conflicts.filter((conflict) => ownedImportMatchesRoot(source.specifier, conflict.packageName)).map((conflict) => conflict.exportName);
|
|
5442
|
+
if (names.length === 0) return source;
|
|
5443
|
+
const blocked = new Set(names);
|
|
5444
|
+
if (source.include) {
|
|
5445
|
+
return { ...source, include: source.include.filter((name) => !blocked.has(name)) };
|
|
5446
|
+
}
|
|
5447
|
+
return { ...source, exclude: [.../* @__PURE__ */ new Set([...source.exclude ?? [], ...names])].sort() };
|
|
5448
|
+
}
|
|
5449
|
+
function indexShadowRenderRootNodeIds(ix) {
|
|
5450
|
+
const identities = ix.byKind("component_identity");
|
|
5451
|
+
if (identities.length === 0) return /* @__PURE__ */ new Set();
|
|
5452
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
5453
|
+
for (const identity of identities) {
|
|
5454
|
+
if (identity.state !== "shadow") continue;
|
|
5455
|
+
for (const evidenceId of identity.evidence) {
|
|
5456
|
+
if (ix.get(evidenceId)?.kind === "usage_node") nodeIds.add(evidenceId);
|
|
5457
|
+
}
|
|
5458
|
+
}
|
|
5459
|
+
return nodeIds;
|
|
5460
|
+
}
|
|
5333
5461
|
function findBuiltInRawHtmlMatch(node, props, textChildren, inputType) {
|
|
5334
5462
|
if (isIconOnlyButton(node, props, textChildren)) {
|
|
5335
5463
|
return { canonical: "IconButton", tier: "icon-only" };
|
|
@@ -5656,9 +5784,95 @@ function isIdentifier(value) {
|
|
|
5656
5784
|
return /^[A-Za-z_$][\w$]*$/.test(value);
|
|
5657
5785
|
}
|
|
5658
5786
|
|
|
5659
|
-
// src/
|
|
5660
|
-
|
|
5787
|
+
// src/identity/usage.ts
|
|
5788
|
+
function indexComponentIdentityUsage(ix) {
|
|
5789
|
+
const nodesById = new Map(ix.byKind("usage_node").map((node) => [node.id, node]));
|
|
5790
|
+
const nodesByComponent = /* @__PURE__ */ new Map();
|
|
5791
|
+
for (const usage of ix.byKind("usage_component")) {
|
|
5792
|
+
const node = nodesById.get(usage.nodeId);
|
|
5793
|
+
if (!node) continue;
|
|
5794
|
+
const componentKey = String(usage.componentId);
|
|
5795
|
+
const nodes = nodesByComponent.get(componentKey) ?? /* @__PURE__ */ new Map();
|
|
5796
|
+
nodes.set(node.id, node);
|
|
5797
|
+
nodesByComponent.set(componentKey, nodes);
|
|
5798
|
+
}
|
|
5799
|
+
return new Map(
|
|
5800
|
+
[...nodesByComponent].map(([componentKey, nodesByIdForComponent]) => {
|
|
5801
|
+
const nodes = [...nodesByIdForComponent.values()];
|
|
5802
|
+
return [
|
|
5803
|
+
componentKey,
|
|
5804
|
+
{
|
|
5805
|
+
usageCount: nodes.length,
|
|
5806
|
+
blastRadius: new Set(nodes.map((node) => node.file)).size,
|
|
5807
|
+
nodes
|
|
5808
|
+
}
|
|
5809
|
+
];
|
|
5810
|
+
})
|
|
5811
|
+
);
|
|
5812
|
+
}
|
|
5813
|
+
|
|
5814
|
+
// src/rules/components-shadow-component.ts
|
|
5815
|
+
var RULE_ID3 = "components/shadow-component";
|
|
5661
5816
|
var RULE_VERSION3 = "1";
|
|
5817
|
+
function ruleComponentsShadowComponent(ix) {
|
|
5818
|
+
const policy = ix.policy.ruleConfig(RULE_ID3);
|
|
5819
|
+
if (!policy?.enabled) return [];
|
|
5820
|
+
const definitions = new Map(
|
|
5821
|
+
ix.byKind("component_definition").map((definition) => [definition.componentKey, definition])
|
|
5822
|
+
);
|
|
5823
|
+
const usageByComponent = indexComponentIdentityUsage(ix);
|
|
5824
|
+
const findings = [];
|
|
5825
|
+
for (const identity of ix.byKind("component_identity")) {
|
|
5826
|
+
const reviewVariant = identity.state === "variant" && identity.confidence === "review";
|
|
5827
|
+
if (identity.state !== "shadow" && !reviewVariant) continue;
|
|
5828
|
+
const definition = definitions.get(identity.componentKey);
|
|
5829
|
+
if (!definition) continue;
|
|
5830
|
+
const usage = usageByComponent.get(identity.componentKey);
|
|
5831
|
+
const usageCount = usage?.usageCount ?? 0;
|
|
5832
|
+
const blastRadius = usage?.blastRadius ?? 0;
|
|
5833
|
+
findings.push(
|
|
5834
|
+
makeFinding({
|
|
5835
|
+
ruleId: RULE_ID3,
|
|
5836
|
+
ruleVersion: RULE_VERSION3,
|
|
5837
|
+
severity: reviewVariant ? "info" : policy.severity ?? "warn",
|
|
5838
|
+
message: reviewVariant ? `${definition.exportName} wraps ${identity.canonicalTarget ?? "a canonical component"}; sanction it as a variant or consolidate its usages.` : `${definition.exportName} shadows ${identity.canonicalTarget ?? "a canonical component"} across ${usageCount} usage${usageCount === 1 ? "" : "s"}.`,
|
|
5839
|
+
location: definitionLocation(ix, definition, identity),
|
|
5840
|
+
evidence: ix.evidence(identity.evidence),
|
|
5841
|
+
fingerprintIdentity: {
|
|
5842
|
+
componentKey: identity.componentKey,
|
|
5843
|
+
canonicalTarget: identity.canonicalTarget
|
|
5844
|
+
},
|
|
5845
|
+
attributes: {
|
|
5846
|
+
canonicalTarget: identity.canonicalTarget,
|
|
5847
|
+
usageCount,
|
|
5848
|
+
blastRadius,
|
|
5849
|
+
confidence: identity.confidence,
|
|
5850
|
+
state: identity.state,
|
|
5851
|
+
...reviewVariant ? { advisory: true } : {}
|
|
5852
|
+
}
|
|
5853
|
+
})
|
|
5854
|
+
);
|
|
5855
|
+
}
|
|
5856
|
+
return findings;
|
|
5857
|
+
}
|
|
5858
|
+
function definitionLocation(ix, definition, identity) {
|
|
5859
|
+
const evidence = ix.evidence(identity.evidence).map(({ fact }) => fact);
|
|
5860
|
+
const inDefinitionFile = evidence.find(
|
|
5861
|
+
(fact) => "location" in fact && fact.location?.file === definition.file
|
|
5862
|
+
);
|
|
5863
|
+
if (inDefinitionFile && "location" in inDefinitionFile && inDefinitionFile.location) {
|
|
5864
|
+
return inDefinitionFile.location;
|
|
5865
|
+
}
|
|
5866
|
+
const sourceLocated = evidence.find((fact) => "location" in fact && fact.location);
|
|
5867
|
+
if (sourceLocated && "location" in sourceLocated && sourceLocated.location) {
|
|
5868
|
+
return sourceLocated.location;
|
|
5869
|
+
}
|
|
5870
|
+
return { file: definition.file, line: 1, column: 0 };
|
|
5871
|
+
}
|
|
5872
|
+
|
|
5873
|
+
// src/rules/components-forbidden-prop-value.ts
|
|
5874
|
+
var RULE_ID4 = "components/forbidden-prop-value";
|
|
5875
|
+
var RULE_VERSION4 = "1";
|
|
5662
5876
|
function ruleComponentsForbiddenPropValue(ix) {
|
|
5663
5877
|
const findings = [];
|
|
5664
5878
|
const componentByNode = indexComponentByNodeId(ix);
|
|
@@ -5688,8 +5902,8 @@ function ruleComponentsForbiddenPropValue(ix) {
|
|
|
5688
5902
|
} : void 0;
|
|
5689
5903
|
findings.push(
|
|
5690
5904
|
makeFinding({
|
|
5691
|
-
ruleId:
|
|
5692
|
-
ruleVersion:
|
|
5905
|
+
ruleId: RULE_ID4,
|
|
5906
|
+
ruleVersion: RULE_VERSION4,
|
|
5693
5907
|
severity: policy.severity,
|
|
5694
5908
|
message: buildMessage(
|
|
5695
5909
|
node.element,
|
|
@@ -5733,8 +5947,8 @@ function buildMessage(element, prop, value, because, replacement) {
|
|
|
5733
5947
|
}
|
|
5734
5948
|
|
|
5735
5949
|
// src/rules/components-unknown-prop.ts
|
|
5736
|
-
var
|
|
5737
|
-
var
|
|
5950
|
+
var RULE_ID5 = "components/unknown-prop";
|
|
5951
|
+
var RULE_VERSION5 = "1";
|
|
5738
5952
|
function ruleComponentsUnknownProp(ix) {
|
|
5739
5953
|
const policy = ix.policy.jsxUnknownPropsForbidden();
|
|
5740
5954
|
if (!policy) return [];
|
|
@@ -5755,8 +5969,8 @@ function ruleComponentsUnknownProp(ix) {
|
|
|
5755
5969
|
if (knownNames.has(propUsage.prop)) continue;
|
|
5756
5970
|
findings.push(
|
|
5757
5971
|
makeFinding({
|
|
5758
|
-
ruleId:
|
|
5759
|
-
ruleVersion:
|
|
5972
|
+
ruleId: RULE_ID5,
|
|
5973
|
+
ruleVersion: RULE_VERSION5,
|
|
5760
5974
|
severity: policy.severity,
|
|
5761
5975
|
message: `Unknown prop "${propUsage.prop}" on <${node.element}>. Allowed props: ${formatPropList(knownNames)}.`,
|
|
5762
5976
|
location: node.location,
|
|
@@ -5788,7 +6002,7 @@ function formatPropList(names) {
|
|
|
5788
6002
|
// src/rules/composition-pattern.ts
|
|
5789
6003
|
var CARDINALITY_RULE_ID = "composition/cardinality";
|
|
5790
6004
|
var CO_OCCURRENCE_RULE_ID = "composition/co-occurrence";
|
|
5791
|
-
var
|
|
6005
|
+
var RULE_VERSION6 = "1";
|
|
5792
6006
|
function ruleCompositionCardinality(ix) {
|
|
5793
6007
|
return evaluate(ix, CARDINALITY_RULE_ID, "cardinality");
|
|
5794
6008
|
}
|
|
@@ -5856,7 +6070,7 @@ function checkCardinality(ctx, region, pattern, constraint, selected) {
|
|
|
5856
6070
|
const extras = selected.slice(constraint.max);
|
|
5857
6071
|
return makeFinding({
|
|
5858
6072
|
ruleId: ctx.ruleId,
|
|
5859
|
-
ruleVersion:
|
|
6073
|
+
ruleVersion: RULE_VERSION6,
|
|
5860
6074
|
severity: ctx.severity,
|
|
5861
6075
|
message: cardinalityMaxMessage(pattern, constraint.max, count),
|
|
5862
6076
|
location: extras[0].location,
|
|
@@ -5867,7 +6081,7 @@ function checkCardinality(ctx, region, pattern, constraint, selected) {
|
|
|
5867
6081
|
if (constraint.min !== void 0 && count < constraint.min) {
|
|
5868
6082
|
return makeFinding({
|
|
5869
6083
|
ruleId: ctx.ruleId,
|
|
5870
|
-
ruleVersion:
|
|
6084
|
+
ruleVersion: RULE_VERSION6,
|
|
5871
6085
|
severity: ctx.severity,
|
|
5872
6086
|
message: cardinalityMinMessage(pattern, constraint.min, count),
|
|
5873
6087
|
location: region.container.location,
|
|
@@ -5888,7 +6102,7 @@ function checkCoOccurrence(ctx, region, pattern, constraint, selected) {
|
|
|
5888
6102
|
if (satisfied) return null;
|
|
5889
6103
|
return makeFinding({
|
|
5890
6104
|
ruleId: ctx.ruleId,
|
|
5891
|
-
ruleVersion:
|
|
6105
|
+
ruleVersion: RULE_VERSION6,
|
|
5892
6106
|
severity: ctx.severity,
|
|
5893
6107
|
message: coOccurrenceMessage(pattern, constraint),
|
|
5894
6108
|
location: region.container.location,
|
|
@@ -5940,8 +6154,8 @@ function coOccurrenceMessage(pattern, constraint) {
|
|
|
5940
6154
|
}
|
|
5941
6155
|
|
|
5942
6156
|
// src/rules/jsx-preferred-component.ts
|
|
5943
|
-
var
|
|
5944
|
-
var
|
|
6157
|
+
var RULE_ID6 = "components/preferred-component";
|
|
6158
|
+
var RULE_VERSION7 = "1";
|
|
5945
6159
|
function ruleJsxPreferredComponent(ix) {
|
|
5946
6160
|
const policies = ix.policy.jsxComponentPreferred();
|
|
5947
6161
|
if (policies.length === 0) return [];
|
|
@@ -5957,8 +6171,8 @@ function ruleJsxPreferredComponent(ix) {
|
|
|
5957
6171
|
if (!replacement) continue;
|
|
5958
6172
|
findings.push(
|
|
5959
6173
|
makeFinding({
|
|
5960
|
-
ruleId:
|
|
5961
|
-
ruleVersion:
|
|
6174
|
+
ruleId: RULE_ID6,
|
|
6175
|
+
ruleVersion: RULE_VERSION7,
|
|
5962
6176
|
severity: policy.severity,
|
|
5963
6177
|
message: `<${node.element}> should use <${replacement}>.`,
|
|
5964
6178
|
location: node.location,
|
|
@@ -5995,8 +6209,8 @@ function componentNameFromId(componentId2) {
|
|
|
5995
6209
|
}
|
|
5996
6210
|
|
|
5997
6211
|
// src/rules/jsx-preferred-import-path.ts
|
|
5998
|
-
var
|
|
5999
|
-
var
|
|
6212
|
+
var RULE_ID7 = "imports/preferred-path";
|
|
6213
|
+
var RULE_VERSION8 = "1";
|
|
6000
6214
|
function ruleJsxPreferredImportPath(ix) {
|
|
6001
6215
|
const policies = ix.policy.jsxImportPathPreferred();
|
|
6002
6216
|
if (policies.length === 0) return [];
|
|
@@ -6004,6 +6218,18 @@ function ruleJsxPreferredImportPath(ix) {
|
|
|
6004
6218
|
const seen = /* @__PURE__ */ new Set();
|
|
6005
6219
|
for (const usage of ix.byKind("usage_import")) {
|
|
6006
6220
|
const matches = policies.filter((policy) => {
|
|
6221
|
+
if (policy.bridge) {
|
|
6222
|
+
if (policy.bridge.implementationFiles.some((file) => sameRepoPath(file, usage.file))) {
|
|
6223
|
+
return false;
|
|
6224
|
+
}
|
|
6225
|
+
if (!ownedImportMatchesRoot(usage.source, policy.from)) return false;
|
|
6226
|
+
if (ownedImportsEqual(usage.source, policy.from)) {
|
|
6227
|
+
return usage.imported === policy.bridge.underlyingExportName;
|
|
6228
|
+
}
|
|
6229
|
+
const subpath = usage.source.slice(policy.from.length + 1);
|
|
6230
|
+
const leaf = subpath.split("/").at(-1);
|
|
6231
|
+
return leaf === policy.bridge.underlyingExportName && (usage.imported === "default" || usage.imported === policy.bridge.underlyingExportName);
|
|
6232
|
+
}
|
|
6007
6233
|
if (!ownedImportsEqual(policy.from, usage.source)) return false;
|
|
6008
6234
|
if (policy.imported !== void 0 && policy.imported !== usage.imported) return false;
|
|
6009
6235
|
return true;
|
|
@@ -6016,10 +6242,10 @@ function ruleJsxPreferredImportPath(ix) {
|
|
|
6016
6242
|
seen.add(key);
|
|
6017
6243
|
findings.push(
|
|
6018
6244
|
makeFinding({
|
|
6019
|
-
ruleId:
|
|
6020
|
-
ruleVersion:
|
|
6245
|
+
ruleId: RULE_ID7,
|
|
6246
|
+
ruleVersion: RULE_VERSION8,
|
|
6021
6247
|
severity: policy.severity,
|
|
6022
|
-
message: `Import from "${usage.source}" should use "${policy.to}".`,
|
|
6248
|
+
message: policy.bridge ? `Import ${policy.bridge.underlyingExportName} through the confirmed local ${policy.bridge.localExportName} wrapper from "${policy.to}".` : `Import from "${usage.source}" should use "${policy.to}".`,
|
|
6023
6249
|
location: usage.location,
|
|
6024
6250
|
evidence: ix.evidence([usage.id, policy.id]),
|
|
6025
6251
|
fingerprintIdentity: {
|
|
@@ -6030,7 +6256,7 @@ function ruleJsxPreferredImportPath(ix) {
|
|
|
6030
6256
|
line: usage.location.line,
|
|
6031
6257
|
column: usage.location.column
|
|
6032
6258
|
},
|
|
6033
|
-
fix: {
|
|
6259
|
+
fix: policy.bridge ? void 0 : {
|
|
6034
6260
|
kind: "replaceImport",
|
|
6035
6261
|
title: policy.because ?? `Replace import path with "${policy.to}"`,
|
|
6036
6262
|
from: usage.source,
|
|
@@ -6042,7 +6268,14 @@ function ruleJsxPreferredImportPath(ix) {
|
|
|
6042
6268
|
suggestedImport: policy.to,
|
|
6043
6269
|
imported: usage.imported,
|
|
6044
6270
|
local: usage.local,
|
|
6045
|
-
rawValue: usage.source
|
|
6271
|
+
rawValue: usage.source,
|
|
6272
|
+
...policy.bridge ? {
|
|
6273
|
+
canonicalBridge: true,
|
|
6274
|
+
canonicalTarget: policy.bridge.componentKey,
|
|
6275
|
+
suggestedComponent: policy.bridge.localExportName,
|
|
6276
|
+
implementationFiles: policy.bridge.implementationFiles,
|
|
6277
|
+
decisionSource: policy.bridge.decisionSource
|
|
6278
|
+
} : {}
|
|
6046
6279
|
}
|
|
6047
6280
|
})
|
|
6048
6281
|
);
|
|
@@ -6050,12 +6283,18 @@ function ruleJsxPreferredImportPath(ix) {
|
|
|
6050
6283
|
}
|
|
6051
6284
|
return findings;
|
|
6052
6285
|
}
|
|
6286
|
+
function sameRepoPath(left, right) {
|
|
6287
|
+
return normalizeRepoPath(left) === normalizeRepoPath(right);
|
|
6288
|
+
}
|
|
6289
|
+
function normalizeRepoPath(path) {
|
|
6290
|
+
return path.replace(/\\/gu, "/").replace(/^\.\//u, "");
|
|
6291
|
+
}
|
|
6053
6292
|
|
|
6054
6293
|
// src/rules/props-invalid-value.ts
|
|
6055
|
-
var
|
|
6056
|
-
var
|
|
6294
|
+
var RULE_ID8 = "props/invalid-value";
|
|
6295
|
+
var RULE_VERSION9 = "1";
|
|
6057
6296
|
function rulePropsInvalidValue(ix) {
|
|
6058
|
-
const policy = ix.policy.ruleConfig(
|
|
6297
|
+
const policy = ix.policy.ruleConfig(RULE_ID8);
|
|
6059
6298
|
if (!policy?.enabled) return [];
|
|
6060
6299
|
const findings = [];
|
|
6061
6300
|
const componentByNode = indexComponentByNodeId(ix);
|
|
@@ -6084,8 +6323,8 @@ function rulePropsInvalidValue(ix) {
|
|
|
6084
6323
|
} : void 0;
|
|
6085
6324
|
findings.push(
|
|
6086
6325
|
makeFinding({
|
|
6087
|
-
ruleId:
|
|
6088
|
-
ruleVersion:
|
|
6326
|
+
ruleId: RULE_ID8,
|
|
6327
|
+
ruleVersion: RULE_VERSION9,
|
|
6089
6328
|
severity: policy.severity ?? "warn",
|
|
6090
6329
|
message: buildMessage2(node.element, propUsage.prop, propUsage.value, allowedValues),
|
|
6091
6330
|
location: propUsage.location ?? node.location,
|
|
@@ -6260,13 +6499,36 @@ function srgbGamma(linear) {
|
|
|
6260
6499
|
return clamped <= 31308e-7 ? 12.92 * clamped : 1.055 * Math.pow(clamped, 1 / 2.4) - 0.055;
|
|
6261
6500
|
}
|
|
6262
6501
|
|
|
6502
|
+
// src/rules/token-candidates.ts
|
|
6503
|
+
function normalizedTokenValue(token) {
|
|
6504
|
+
const value = token.value.trim();
|
|
6505
|
+
return token.category === "color" ? normalizeColor(value) : value.replace(/\s+/g, " ");
|
|
6506
|
+
}
|
|
6507
|
+
function localTokenCandidates(ix, category) {
|
|
6508
|
+
const all = ix.tokens.list();
|
|
6509
|
+
const upstreamByName = /* @__PURE__ */ new Map();
|
|
6510
|
+
for (const token of all) {
|
|
6511
|
+
if (token.role !== "upstream") continue;
|
|
6512
|
+
const matches = upstreamByName.get(token.name) ?? [];
|
|
6513
|
+
matches.push(token);
|
|
6514
|
+
upstreamByName.set(token.name, matches);
|
|
6515
|
+
}
|
|
6516
|
+
return all.filter((token) => {
|
|
6517
|
+
if (token.role === "upstream" || category !== void 0 && token.category !== category) {
|
|
6518
|
+
return false;
|
|
6519
|
+
}
|
|
6520
|
+
const matches = upstreamByName.get(token.upstreamName ?? token.name) ?? [];
|
|
6521
|
+
return matches.length !== 1 || normalizedTokenValue(token) === normalizedTokenValue(matches[0]);
|
|
6522
|
+
});
|
|
6523
|
+
}
|
|
6524
|
+
|
|
6263
6525
|
// src/rules/styles-no-raw-color.ts
|
|
6264
|
-
var
|
|
6265
|
-
var
|
|
6526
|
+
var RULE_ID9 = "styles/no-raw-color";
|
|
6527
|
+
var RULE_VERSION10 = "1";
|
|
6266
6528
|
function ruleStylesNoRawColor(ix) {
|
|
6267
6529
|
const policy = ix.policy.rawColorPolicy();
|
|
6268
6530
|
if (!policy) return [];
|
|
6269
|
-
const colorTokens = ix
|
|
6531
|
+
const colorTokens = localTokenCandidates(ix, "color");
|
|
6270
6532
|
const preferLabel = policy.prefer === "token" ? "design token" : "CSS variable";
|
|
6271
6533
|
const findings = [];
|
|
6272
6534
|
const advisorySeverity = policy.severity === "error" ? "warn" : policy.severity;
|
|
@@ -6280,8 +6542,8 @@ function ruleStylesNoRawColor(ix) {
|
|
|
6280
6542
|
const evidenceIds = resolution ? [decl.id, policy.id, resolution.token.id] : [decl.id, policy.id];
|
|
6281
6543
|
findings.push(
|
|
6282
6544
|
makeFinding({
|
|
6283
|
-
ruleId:
|
|
6284
|
-
ruleVersion:
|
|
6545
|
+
ruleId: RULE_ID9,
|
|
6546
|
+
ruleVersion: RULE_VERSION10,
|
|
6285
6547
|
severity: policy.severity,
|
|
6286
6548
|
message: colorMessage(color, `\`${decl.property}\``, resolution, preferLabel),
|
|
6287
6549
|
location: decl.location,
|
|
@@ -6316,8 +6578,8 @@ function ruleStylesNoRawColor(ix) {
|
|
|
6316
6578
|
const evidenceIds2 = componentEvidenceId2 ? [node2.id, componentEvidenceId2, inline.id, policy.id] : [node2.id, inline.id, policy.id];
|
|
6317
6579
|
findings.push(
|
|
6318
6580
|
makeFinding({
|
|
6319
|
-
ruleId:
|
|
6320
|
-
ruleVersion:
|
|
6581
|
+
ruleId: RULE_ID9,
|
|
6582
|
+
ruleVersion: RULE_VERSION10,
|
|
6321
6583
|
severity: advisorySeverity,
|
|
6322
6584
|
message: `Runtime-constructed raw color \`${inline.value}\` on inline \`${inline.property}\`. Use a ${preferLabel} instead.`,
|
|
6323
6585
|
location: node2.location,
|
|
@@ -6353,8 +6615,8 @@ function ruleStylesNoRawColor(ix) {
|
|
|
6353
6615
|
const evidenceIds = resolution ? [...baseEvidence, resolution.token.id] : baseEvidence;
|
|
6354
6616
|
findings.push(
|
|
6355
6617
|
makeFinding({
|
|
6356
|
-
ruleId:
|
|
6357
|
-
ruleVersion:
|
|
6618
|
+
ruleId: RULE_ID9,
|
|
6619
|
+
ruleVersion: RULE_VERSION10,
|
|
6358
6620
|
severity: policy.severity,
|
|
6359
6621
|
message: colorMessage(color, `inline \`${inline.property}\``, resolution, preferLabel),
|
|
6360
6622
|
location: node.location,
|
|
@@ -6397,8 +6659,8 @@ function ruleStylesNoRawColor(ix) {
|
|
|
6397
6659
|
const evidenceIds = resolution ? [...baseEvidence, resolution.token.id] : baseEvidence;
|
|
6398
6660
|
findings.push(
|
|
6399
6661
|
makeFinding({
|
|
6400
|
-
ruleId:
|
|
6401
|
-
ruleVersion:
|
|
6662
|
+
ruleId: RULE_ID9,
|
|
6663
|
+
ruleVersion: RULE_VERSION10,
|
|
6402
6664
|
severity: advisorySeverity,
|
|
6403
6665
|
message: colorMessage(color, `\`${prop.prop}\``, resolution, preferLabel),
|
|
6404
6666
|
location: prop.location ?? node.location,
|
|
@@ -6520,7 +6782,7 @@ function normalizeColor2(value) {
|
|
|
6520
6782
|
return lower;
|
|
6521
6783
|
}
|
|
6522
6784
|
function buildTokenFix(property, rawValue, rawColor, match, ix) {
|
|
6523
|
-
const reference = tokenReference(match.token
|
|
6785
|
+
const reference = tokenReference(match.token);
|
|
6524
6786
|
const value = replaceRawColor(rawValue, rawColor, reference);
|
|
6525
6787
|
return emitFix(
|
|
6526
6788
|
{
|
|
@@ -6549,14 +6811,14 @@ function escapeRegExp(value) {
|
|
|
6549
6811
|
}
|
|
6550
6812
|
|
|
6551
6813
|
// src/rules/styles-no-raw-dimensions.ts
|
|
6552
|
-
var
|
|
6553
|
-
var
|
|
6814
|
+
var RULE_ID10 = "styles/no-raw-dimensions";
|
|
6815
|
+
var RULE_VERSION11 = "1";
|
|
6554
6816
|
function ruleStylesNoRawDimensions(ix) {
|
|
6555
6817
|
const policy = ix.policy.rawDimensionPolicy();
|
|
6556
6818
|
if (!policy) return [];
|
|
6557
6819
|
const appliesTo = new Set(policy.appliesTo);
|
|
6558
|
-
const spacingTokens = ix
|
|
6559
|
-
const radiusTokens = ix
|
|
6820
|
+
const spacingTokens = localTokenCandidates(ix, "spacing");
|
|
6821
|
+
const radiusTokens = localTokenCandidates(ix, "radius");
|
|
6560
6822
|
const preferLabel = policy.prefer === "token" ? "design token" : "CSS variable";
|
|
6561
6823
|
const findings = [];
|
|
6562
6824
|
for (const decl of ix.byKind("style_declaration")) {
|
|
@@ -6570,8 +6832,8 @@ function ruleStylesNoRawDimensions(ix) {
|
|
|
6570
6832
|
const fixEmission = dimensionFix(decl.property, resolution, ix);
|
|
6571
6833
|
findings.push(
|
|
6572
6834
|
makeFinding({
|
|
6573
|
-
ruleId:
|
|
6574
|
-
ruleVersion:
|
|
6835
|
+
ruleId: RULE_ID10,
|
|
6836
|
+
ruleVersion: RULE_VERSION11,
|
|
6575
6837
|
severity: policy.severity,
|
|
6576
6838
|
message: dimensionMessage(decl.value, decl.property, preferLabel, resolution, false),
|
|
6577
6839
|
location: decl.location,
|
|
@@ -6612,8 +6874,8 @@ function ruleStylesNoRawDimensions(ix) {
|
|
|
6612
6874
|
const fixEmission = dimensionFix(inline.property, resolution, ix);
|
|
6613
6875
|
findings.push(
|
|
6614
6876
|
makeFinding({
|
|
6615
|
-
ruleId:
|
|
6616
|
-
ruleVersion:
|
|
6877
|
+
ruleId: RULE_ID10,
|
|
6878
|
+
ruleVersion: RULE_VERSION11,
|
|
6617
6879
|
severity: policy.severity,
|
|
6618
6880
|
message: dimensionMessage(inline.value, inline.property, preferLabel, resolution, true),
|
|
6619
6881
|
location: node.location,
|
|
@@ -6767,9 +7029,7 @@ function normalizeDimension(value) {
|
|
|
6767
7029
|
return `${parsed.value}${parsed.unit ?? "px"}`;
|
|
6768
7030
|
}
|
|
6769
7031
|
function tokenVar(token) {
|
|
6770
|
-
|
|
6771
|
-
const cssVarName = token.name.startsWith("--") ? token.name : `--${token.name.replace(/\./g, "-")}`;
|
|
6772
|
-
return `var(${cssVarName})`;
|
|
7032
|
+
return tokenReference(token);
|
|
6773
7033
|
}
|
|
6774
7034
|
|
|
6775
7035
|
// src/rules/spacing-resolution.ts
|
|
@@ -6807,7 +7067,7 @@ function resolveSpacingValue(input) {
|
|
|
6807
7067
|
continue;
|
|
6808
7068
|
}
|
|
6809
7069
|
anyViolation = true;
|
|
6810
|
-
const reference = tokenReference(exactToken
|
|
7070
|
+
const reference = tokenReference(exactToken);
|
|
6811
7071
|
if (!normalized.deterministicFix) allValuePreserving = false;
|
|
6812
7072
|
suggestedParts.push(reference);
|
|
6813
7073
|
if (!firstViolation) {
|
|
@@ -6839,7 +7099,7 @@ function resolveSpacingValue(input) {
|
|
|
6839
7099
|
} else {
|
|
6840
7100
|
const nearestToken = input.tokens.get(Math.abs(nearest));
|
|
6841
7101
|
suggestedToken = nearestToken?.name;
|
|
6842
|
-
suggestedPart = nearestToken ? tokenReference(nearestToken
|
|
7102
|
+
suggestedPart = nearestToken ? tokenReference(nearestToken) : input.bareNumberFix ? `${nearest}` : `${nearest}${input.scale.unit}`;
|
|
6843
7103
|
suggestedParts.push(suggestedPart);
|
|
6844
7104
|
if (!normalized.deterministicFix) reliableSuggestion = false;
|
|
6845
7105
|
}
|
|
@@ -6883,15 +7143,15 @@ function parseLengthParts(raw) {
|
|
|
6883
7143
|
}
|
|
6884
7144
|
|
|
6885
7145
|
// src/rules/styles-no-raw-spacing.ts
|
|
6886
|
-
var
|
|
6887
|
-
var
|
|
7146
|
+
var RULE_ID11 = "styles/no-raw-spacing";
|
|
7147
|
+
var RULE_VERSION12 = "1";
|
|
6888
7148
|
function ruleStylesNoRawSpacing(ix) {
|
|
6889
7149
|
const findings = [];
|
|
6890
7150
|
const lookupCache = /* @__PURE__ */ new Map();
|
|
6891
7151
|
const lookupFor = (scale) => {
|
|
6892
7152
|
let lookup = lookupCache.get(scale.name);
|
|
6893
7153
|
if (!lookup) {
|
|
6894
|
-
lookup = buildSpacingTokenLookup(ix
|
|
7154
|
+
lookup = buildSpacingTokenLookup(localTokenCandidates(ix, "spacing"), scale);
|
|
6895
7155
|
lookupCache.set(scale.name, lookup);
|
|
6896
7156
|
}
|
|
6897
7157
|
return lookup;
|
|
@@ -6926,8 +7186,8 @@ function checkDeclaration(ix, decl, lookupFor) {
|
|
|
6926
7186
|
if (!checked) return null;
|
|
6927
7187
|
const fixEmission = buildSpacingFix(decl.property, checked, ix);
|
|
6928
7188
|
return makeFinding({
|
|
6929
|
-
ruleId:
|
|
6930
|
-
ruleVersion:
|
|
7189
|
+
ruleId: RULE_ID11,
|
|
7190
|
+
ruleVersion: RULE_VERSION12,
|
|
6931
7191
|
severity: policy.severity,
|
|
6932
7192
|
message: spacingMessage(decl.property, decl.value, allowed, scale.unit, checked),
|
|
6933
7193
|
location: decl.location,
|
|
@@ -6981,8 +7241,8 @@ function checkInlineStyle(ix, inline, componentByNode, lookupFor) {
|
|
|
6981
7241
|
const componentEvidenceId = componentByNode.get(node.id)?.id;
|
|
6982
7242
|
const evidenceIds = componentEvidenceId ? [node.id, componentEvidenceId, inline.id, policy.id, scale.id] : [node.id, inline.id, policy.id, scale.id];
|
|
6983
7243
|
return makeFinding({
|
|
6984
|
-
ruleId:
|
|
6985
|
-
ruleVersion:
|
|
7244
|
+
ruleId: RULE_ID11,
|
|
7245
|
+
ruleVersion: RULE_VERSION12,
|
|
6986
7246
|
severity: policy.severity,
|
|
6987
7247
|
message: spacingMessage(inline.property, inline.value, allowed, scale.unit, checked),
|
|
6988
7248
|
location: node.location,
|
|
@@ -7025,7 +7285,7 @@ function buildSpacingFix(property, checked, ix) {
|
|
|
7025
7285
|
deterministic: true
|
|
7026
7286
|
},
|
|
7027
7287
|
{
|
|
7028
|
-
symbols: tokenSymbolsInText(checked.suggestedValue),
|
|
7288
|
+
symbols: checked.matchedToken ? [checked.matchedToken] : tokenSymbolsInText(checked.suggestedValue),
|
|
7029
7289
|
editKind: "replaceStyleValue",
|
|
7030
7290
|
valuePreserving: checked.deterministicFix
|
|
7031
7291
|
},
|
|
@@ -7043,8 +7303,8 @@ function spacingMessage(property, value, allowed, unit, checked) {
|
|
|
7043
7303
|
}
|
|
7044
7304
|
|
|
7045
7305
|
// src/rules/styles-no-raw-typography.ts
|
|
7046
|
-
var
|
|
7047
|
-
var
|
|
7306
|
+
var RULE_ID12 = "styles/no-raw-typography";
|
|
7307
|
+
var RULE_VERSION13 = "1";
|
|
7048
7308
|
var FONT_SIZE_PROPERTIES = /* @__PURE__ */ new Set(["font-size", "fontsize"]);
|
|
7049
7309
|
function ruleStylesNoRawTypography(ix) {
|
|
7050
7310
|
const policy = ix.policy.fontSizeScale();
|
|
@@ -7062,8 +7322,8 @@ function ruleStylesNoRawTypography(ix) {
|
|
|
7062
7322
|
const fixEmission = buildFix(decl.property, checked, ix);
|
|
7063
7323
|
findings.push(
|
|
7064
7324
|
makeFinding({
|
|
7065
|
-
ruleId:
|
|
7066
|
-
ruleVersion:
|
|
7325
|
+
ruleId: RULE_ID12,
|
|
7326
|
+
ruleVersion: RULE_VERSION13,
|
|
7067
7327
|
severity: policy.severity,
|
|
7068
7328
|
message: typographyMessage(decl.property, decl.value, allowed, scale.unit, checked),
|
|
7069
7329
|
location: decl.location,
|
|
@@ -7109,8 +7369,8 @@ function ruleStylesNoRawTypography(ix) {
|
|
|
7109
7369
|
const evidenceIds = componentEvidenceId ? [node.id, componentEvidenceId, inline.id, policy.id, scale.id] : [node.id, inline.id, policy.id, scale.id];
|
|
7110
7370
|
findings.push(
|
|
7111
7371
|
makeFinding({
|
|
7112
|
-
ruleId:
|
|
7113
|
-
ruleVersion:
|
|
7372
|
+
ruleId: RULE_ID12,
|
|
7373
|
+
ruleVersion: RULE_VERSION13,
|
|
7114
7374
|
severity: policy.severity,
|
|
7115
7375
|
message: typographyMessage(inline.property, inline.value, allowed, scale.unit, checked),
|
|
7116
7376
|
location: node.location,
|
|
@@ -7141,7 +7401,7 @@ function ruleStylesNoRawTypography(ix) {
|
|
|
7141
7401
|
}
|
|
7142
7402
|
function buildTypographyTokenLookup(ix, scale) {
|
|
7143
7403
|
const out = /* @__PURE__ */ new Map();
|
|
7144
|
-
for (const token of ix
|
|
7404
|
+
for (const token of localTokenCandidates(ix, "typography")) {
|
|
7145
7405
|
const parsed = parseLengthValue(token.value);
|
|
7146
7406
|
if (!parsed || parsed.unit === null) continue;
|
|
7147
7407
|
const normalized = normalizeLengthForScale(parsed, scale);
|
|
@@ -7163,7 +7423,7 @@ function checkFontSize(raw, allowed, scale, tokens, bareNumberFix = false) {
|
|
|
7163
7423
|
if (matchesScale(normalized.value, allowed)) {
|
|
7164
7424
|
if (!exactToken) return null;
|
|
7165
7425
|
return {
|
|
7166
|
-
suggestedValue: tokenReference(exactToken
|
|
7426
|
+
suggestedValue: tokenReference(exactToken),
|
|
7167
7427
|
fixEmittable: true,
|
|
7168
7428
|
deterministicFix: normalized.deterministicFix,
|
|
7169
7429
|
reason: "token-equivalent",
|
|
@@ -7175,7 +7435,7 @@ function checkFontSize(raw, allowed, scale, tokens, bareNumberFix = false) {
|
|
|
7175
7435
|
return { fixEmittable: false, deterministicFix: false, reason: "off-scale" };
|
|
7176
7436
|
}
|
|
7177
7437
|
const nearestToken = tokens.get(Math.abs(nearest));
|
|
7178
|
-
const suggestedValue = nearestToken ? tokenReference(nearestToken
|
|
7438
|
+
const suggestedValue = nearestToken ? tokenReference(nearestToken) : bareNumberFix ? `${nearest}` : `${nearest}${scale.unit}`;
|
|
7179
7439
|
return {
|
|
7180
7440
|
suggestedValue,
|
|
7181
7441
|
fixEmittable: normalized.deterministicFix,
|
|
@@ -7194,7 +7454,7 @@ function buildFix(property, checked, ix) {
|
|
|
7194
7454
|
deterministic: true
|
|
7195
7455
|
},
|
|
7196
7456
|
{
|
|
7197
|
-
symbols: tokenSymbolsInText(checked.suggestedValue),
|
|
7457
|
+
symbols: checked.matchedToken ? [checked.matchedToken] : tokenSymbolsInText(checked.suggestedValue),
|
|
7198
7458
|
editKind: "replaceStyleValue",
|
|
7199
7459
|
valuePreserving: checked.deterministicFix
|
|
7200
7460
|
},
|
|
@@ -7212,15 +7472,15 @@ function typographyMessage(property, value, allowed, unit, checked) {
|
|
|
7212
7472
|
}
|
|
7213
7473
|
|
|
7214
7474
|
// src/rules/theme-no-theme-coupled-literal.ts
|
|
7215
|
-
var
|
|
7216
|
-
var
|
|
7475
|
+
var RULE_ID13 = "theme/no-theme-coupled-literal";
|
|
7476
|
+
var RULE_VERSION14 = "1";
|
|
7217
7477
|
var COLOR_LITERAL_GLOBAL = /#[0-9a-fA-F]{3,8}\b|\b(?:rgba?|hsla?|oklab|oklch|lab|lch)\(\s*[\d.%\s,\/]+\s*\)/g;
|
|
7218
7478
|
var WHITE_RGBA = /^rgba?\(\s*255\s*,\s*255\s*,\s*255/i;
|
|
7219
7479
|
var BLACK_RGBA = /^rgba?\(\s*0\s*,\s*0\s*,\s*0/i;
|
|
7220
7480
|
var BOX_SHADOW_PROP = /^(?:-webkit-|-moz-)?box-shadow$/i;
|
|
7221
7481
|
var NEUTRAL_SHADOW = /^(?:none|inherit|initial|unset|revert|revert-layer)\s*$/i;
|
|
7222
7482
|
function ruleThemeNoThemeCoupledLiteral(ix) {
|
|
7223
|
-
const policy = ix.policy.ruleConfig(
|
|
7483
|
+
const policy = ix.policy.ruleConfig(RULE_ID13);
|
|
7224
7484
|
if (!policy?.enabled) return [];
|
|
7225
7485
|
const findings = [];
|
|
7226
7486
|
for (const decl of ix.byKind("style_declaration")) {
|
|
@@ -7229,8 +7489,8 @@ function ruleThemeNoThemeCoupledLiteral(ix) {
|
|
|
7229
7489
|
if (!hit) continue;
|
|
7230
7490
|
findings.push(
|
|
7231
7491
|
makeFinding({
|
|
7232
|
-
ruleId:
|
|
7233
|
-
ruleVersion:
|
|
7492
|
+
ruleId: RULE_ID13,
|
|
7493
|
+
ruleVersion: RULE_VERSION14,
|
|
7234
7494
|
severity: policy.severity ?? "warn",
|
|
7235
7495
|
message: hit.message,
|
|
7236
7496
|
location: decl.location,
|
|
@@ -7320,8 +7580,8 @@ function isTokenFile(filePath) {
|
|
|
7320
7580
|
}
|
|
7321
7581
|
|
|
7322
7582
|
// src/rules/tailwind-arbitrary-color.ts
|
|
7323
|
-
var
|
|
7324
|
-
var
|
|
7583
|
+
var RULE_ID14 = "tailwind/arbitrary-color";
|
|
7584
|
+
var RULE_VERSION15 = "1";
|
|
7325
7585
|
var COLOR_UTILITIES = /* @__PURE__ */ new Set([
|
|
7326
7586
|
"accent",
|
|
7327
7587
|
"bg",
|
|
@@ -7363,8 +7623,8 @@ function ruleTailwindArbitraryColor(ix) {
|
|
|
7363
7623
|
const evidenceIds = node ? [node.id, klass.id, policy.id] : [klass.id, policy.id];
|
|
7364
7624
|
findings.push(
|
|
7365
7625
|
makeFinding({
|
|
7366
|
-
ruleId:
|
|
7367
|
-
ruleVersion:
|
|
7626
|
+
ruleId: RULE_ID14,
|
|
7627
|
+
ruleVersion: RULE_VERSION15,
|
|
7368
7628
|
severity: policy.severity,
|
|
7369
7629
|
message: `\`${klass.raw}\` uses arbitrary raw color ${color}. Use a ${policy.prefer === "token" ? "design token" : "CSS variable"} instead.`,
|
|
7370
7630
|
location: klass.location,
|
|
@@ -7395,8 +7655,8 @@ function fingerprintIdentity(klass, color) {
|
|
|
7395
7655
|
}
|
|
7396
7656
|
|
|
7397
7657
|
// src/rules/tailwind-arbitrary-spacing.ts
|
|
7398
|
-
var
|
|
7399
|
-
var
|
|
7658
|
+
var RULE_ID15 = "tailwind/arbitrary-spacing";
|
|
7659
|
+
var RULE_VERSION16 = "1";
|
|
7400
7660
|
var SPACING_UTILITY_TO_PROPERTY = /* @__PURE__ */ new Map([
|
|
7401
7661
|
["m", "margin"],
|
|
7402
7662
|
["mt", "margin"],
|
|
@@ -7442,8 +7702,8 @@ function ruleTailwindArbitrarySpacing(ix) {
|
|
|
7442
7702
|
const fix = buildFix2(klass);
|
|
7443
7703
|
findings.push(
|
|
7444
7704
|
makeFinding({
|
|
7445
|
-
ruleId:
|
|
7446
|
-
ruleVersion:
|
|
7705
|
+
ruleId: RULE_ID15,
|
|
7706
|
+
ruleVersion: RULE_VERSION16,
|
|
7447
7707
|
severity: policy.severity,
|
|
7448
7708
|
message: `\`${klass.raw}\` is an arbitrary spacing value not on the project's spacing scale.`,
|
|
7449
7709
|
location: klass.location,
|
|
@@ -7574,8 +7834,8 @@ function matchesTokenGlob(value, pattern) {
|
|
|
7574
7834
|
}
|
|
7575
7835
|
|
|
7576
7836
|
// src/rules/tailwind-forbidden-palette.ts
|
|
7577
|
-
var
|
|
7578
|
-
var
|
|
7837
|
+
var RULE_ID16 = "tailwind/forbidden-palette";
|
|
7838
|
+
var RULE_VERSION17 = "1";
|
|
7579
7839
|
function ruleTailwindForbiddenPalette(ix) {
|
|
7580
7840
|
const deny = ix.policy.tailwindPaletteDeny();
|
|
7581
7841
|
const allow = ix.policy.tailwindPaletteAllow();
|
|
@@ -7600,8 +7860,8 @@ function ruleTailwindForbiddenPalette(ix) {
|
|
|
7600
7860
|
const evidenceIds = node ? [node.id, klass.id, resolved.id, policy.id] : [klass.id, resolved.id, policy.id];
|
|
7601
7861
|
findings.push(
|
|
7602
7862
|
makeFinding({
|
|
7603
|
-
ruleId:
|
|
7604
|
-
ruleVersion:
|
|
7863
|
+
ruleId: RULE_ID16,
|
|
7864
|
+
ruleVersion: RULE_VERSION17,
|
|
7605
7865
|
severity: policy.severity,
|
|
7606
7866
|
message: messageFor(klass, token, deniedPattern, allow?.patterns ?? []),
|
|
7607
7867
|
location: klass.location,
|
|
@@ -7648,8 +7908,8 @@ function buildFix3(klass) {
|
|
|
7648
7908
|
}
|
|
7649
7909
|
|
|
7650
7910
|
// src/rules/tailwind-off-scale-spacing-token.ts
|
|
7651
|
-
var
|
|
7652
|
-
var
|
|
7911
|
+
var RULE_ID17 = "tailwind/off-scale-spacing-token";
|
|
7912
|
+
var RULE_VERSION18 = "1";
|
|
7653
7913
|
function ruleTailwindOffScaleSpacingToken(ix) {
|
|
7654
7914
|
const resolvedByKey = indexResolvedTailwindTokens(ix);
|
|
7655
7915
|
const findings = [];
|
|
@@ -7675,8 +7935,8 @@ function ruleTailwindOffScaleSpacingToken(ix) {
|
|
|
7675
7935
|
const evidenceIds = node ? [node.id, klass.id, resolved.id, policy.id, scale.id] : [klass.id, resolved.id, policy.id, scale.id];
|
|
7676
7936
|
findings.push(
|
|
7677
7937
|
makeFinding({
|
|
7678
|
-
ruleId:
|
|
7679
|
-
ruleVersion:
|
|
7938
|
+
ruleId: RULE_ID17,
|
|
7939
|
+
ruleVersion: RULE_VERSION18,
|
|
7680
7940
|
severity: policy.severity,
|
|
7681
7941
|
message: `\`${klass.raw}\` resolves to ${formatResolvedValue(signedValue, scale.unit)}, which is not on the project's spacing scale [${allowed.join(", ")}].`,
|
|
7682
7942
|
location: klass.location,
|
|
@@ -7725,8 +7985,8 @@ function buildFix4(raw, utility) {
|
|
|
7725
7985
|
}
|
|
7726
7986
|
|
|
7727
7987
|
// src/rules/tailwind-raw-color-via-token.ts
|
|
7728
|
-
var
|
|
7729
|
-
var
|
|
7988
|
+
var RULE_ID18 = "tailwind/raw-color-via-token";
|
|
7989
|
+
var RULE_VERSION19 = "1";
|
|
7730
7990
|
function ruleTailwindRawColorViaToken(ix) {
|
|
7731
7991
|
const allow = ix.policy.tailwindPaletteAllow();
|
|
7732
7992
|
if (!allow || allow.patterns.length === 0) return [];
|
|
@@ -7746,8 +8006,8 @@ function ruleTailwindRawColorViaToken(ix) {
|
|
|
7746
8006
|
const evidenceIds = node ? [node.id, klass.id, resolved.id, allow.id] : [klass.id, resolved.id, allow.id];
|
|
7747
8007
|
findings.push(
|
|
7748
8008
|
makeFinding({
|
|
7749
|
-
ruleId:
|
|
7750
|
-
ruleVersion:
|
|
8009
|
+
ruleId: RULE_ID18,
|
|
8010
|
+
ruleVersion: RULE_VERSION19,
|
|
7751
8011
|
severity: allow.severity,
|
|
7752
8012
|
message: `\`${klass.raw}\` resolves to raw color \`${color}\` (${sourceLabel2(resolved.resolved.source)}). Project policy requires \`${allow.patterns.join("`, `")}\` palette tokens.`,
|
|
7753
8013
|
location: klass.location,
|
|
@@ -7780,8 +8040,8 @@ function sourceLabel2(source) {
|
|
|
7780
8040
|
}
|
|
7781
8041
|
|
|
7782
8042
|
// src/rules/tailwind-unknown-class.ts
|
|
7783
|
-
var
|
|
7784
|
-
var
|
|
8043
|
+
var RULE_ID19 = "tailwind/unknown-class";
|
|
8044
|
+
var RULE_VERSION20 = "1";
|
|
7785
8045
|
var UNIVERSAL_COLOR_KEYWORDS = /* @__PURE__ */ new Set([
|
|
7786
8046
|
"white",
|
|
7787
8047
|
"black",
|
|
@@ -7802,8 +8062,8 @@ function ruleTailwindUnknownClass(ix) {
|
|
|
7802
8062
|
const evidenceIds2 = node2 ? [node2.id, klass.id, policy.id] : [klass.id, policy.id];
|
|
7803
8063
|
findings.push(
|
|
7804
8064
|
makeFinding({
|
|
7805
|
-
ruleId:
|
|
7806
|
-
ruleVersion:
|
|
8065
|
+
ruleId: RULE_ID19,
|
|
8066
|
+
ruleVersion: RULE_VERSION20,
|
|
7807
8067
|
severity: policy.severity,
|
|
7808
8068
|
message: `\`${klass.raw}\` could not be parsed as a known Tailwind utility.`,
|
|
7809
8069
|
location: klass.location,
|
|
@@ -7837,8 +8097,8 @@ function ruleTailwindUnknownClass(ix) {
|
|
|
7837
8097
|
const evidenceIds = node ? [node.id, klass.id, resolved.id, policy.id] : [klass.id, resolved.id, policy.id];
|
|
7838
8098
|
findings.push(
|
|
7839
8099
|
makeFinding({
|
|
7840
|
-
ruleId:
|
|
7841
|
-
ruleVersion:
|
|
8100
|
+
ruleId: RULE_ID19,
|
|
8101
|
+
ruleVersion: RULE_VERSION20,
|
|
7842
8102
|
severity: policy.severity,
|
|
7843
8103
|
message: `\`${klass.raw}\` did not resolve to any known palette token.`,
|
|
7844
8104
|
location: klass.location,
|
|
@@ -7866,14 +8126,14 @@ function ruleTailwindUnknownClass(ix) {
|
|
|
7866
8126
|
}
|
|
7867
8127
|
|
|
7868
8128
|
// src/rules/tokens-require-dual-fallback.ts
|
|
7869
|
-
var
|
|
7870
|
-
var
|
|
8129
|
+
var RULE_ID20 = "tokens/require-dual-fallback";
|
|
8130
|
+
var RULE_VERSION21 = "1";
|
|
7871
8131
|
var CSS_VAR_WITH_OPTIONAL_FALLBACK = /var\(\s*(--[A-Za-z0-9_-]+)(\s*,\s*[^)]*)?\)/g;
|
|
7872
8132
|
var SASS_FILE = /\.(scss|sass)$/i;
|
|
7873
8133
|
function ruleTokensRequireDualFallback(ix) {
|
|
7874
|
-
const policy = ix.policy.ruleConfig(
|
|
8134
|
+
const policy = ix.policy.ruleConfig(RULE_ID20);
|
|
7875
8135
|
if (!policy?.enabled) return [];
|
|
7876
|
-
const tokensByCssVariable = indexTokensByCssVariable(ix
|
|
8136
|
+
const tokensByCssVariable = indexTokensByCssVariable(localTokenCandidates(ix));
|
|
7877
8137
|
const findings = [];
|
|
7878
8138
|
for (const decl of ix.byKind("style_declaration")) {
|
|
7879
8139
|
if (!SASS_FILE.test(decl.file)) continue;
|
|
@@ -7906,8 +8166,8 @@ function ruleTokensRequireDualFallback(ix) {
|
|
|
7906
8166
|
) : void 0;
|
|
7907
8167
|
findings.push(
|
|
7908
8168
|
makeFinding({
|
|
7909
|
-
ruleId:
|
|
7910
|
-
ruleVersion:
|
|
8169
|
+
ruleId: RULE_ID20,
|
|
8170
|
+
ruleVersion: RULE_VERSION21,
|
|
7911
8171
|
severity: policy.severity ?? "warn",
|
|
7912
8172
|
message: hasScssVariable ? `var(${tokenName}) is missing an SCSS fallback. Use var(${tokenName}, ${scssVar}).` : `var(${tokenName}) is missing a fallback. No matching SCSS variable was found in the token source; add a fallback manually or define ${scssVar}.`,
|
|
7913
8173
|
location: decl.location,
|
|
@@ -7947,8 +8207,8 @@ function indexTokensByCssVariable(tokens) {
|
|
|
7947
8207
|
}
|
|
7948
8208
|
|
|
7949
8209
|
// src/rules/tokens-css-vars-must-be-defined.ts
|
|
7950
|
-
var
|
|
7951
|
-
var
|
|
8210
|
+
var RULE_ID21 = "tokens/css-vars-must-be-defined";
|
|
8211
|
+
var RULE_VERSION22 = "1";
|
|
7952
8212
|
var CSS_VAR_REFERENCE = /var\(\s*(--[A-Za-z0-9_-]+)/gi;
|
|
7953
8213
|
function ruleTokensCssVarsMustBeDefined(ix) {
|
|
7954
8214
|
const policy = ix.policy.cssVarsMustBeDefined();
|
|
@@ -7975,8 +8235,8 @@ function ruleTokensCssVarsMustBeDefined(ix) {
|
|
|
7975
8235
|
seen.add(tokenName);
|
|
7976
8236
|
findings.push(
|
|
7977
8237
|
makeFinding({
|
|
7978
|
-
ruleId:
|
|
7979
|
-
ruleVersion:
|
|
8238
|
+
ruleId: RULE_ID21,
|
|
8239
|
+
ruleVersion: RULE_VERSION22,
|
|
7980
8240
|
severity: policy.severity,
|
|
7981
8241
|
message: `var(${tokenName}) is not in the contract token vocabulary. Use a token defined in your contract's token source files.`,
|
|
7982
8242
|
location: decl.location,
|
|
@@ -8022,6 +8282,57 @@ function skipToCloseParen(value, openParenIndex) {
|
|
|
8022
8282
|
return value.length;
|
|
8023
8283
|
}
|
|
8024
8284
|
|
|
8285
|
+
// src/rules/tokens-upstream-drift.ts
|
|
8286
|
+
var RULE_ID22 = "tokens/upstream-drift";
|
|
8287
|
+
var RULE_VERSION23 = "1";
|
|
8288
|
+
function ruleTokensUpstreamDrift(ix) {
|
|
8289
|
+
const local = ix.tokens.list().filter((token) => token.role !== "upstream");
|
|
8290
|
+
const upstream = ix.tokens.list().filter((token) => token.role === "upstream");
|
|
8291
|
+
const upstreamByName = /* @__PURE__ */ new Map();
|
|
8292
|
+
for (const token of upstream) {
|
|
8293
|
+
const matches = upstreamByName.get(token.name) ?? [];
|
|
8294
|
+
matches.push(token);
|
|
8295
|
+
upstreamByName.set(token.name, matches);
|
|
8296
|
+
}
|
|
8297
|
+
const findings = [];
|
|
8298
|
+
for (const token of local) {
|
|
8299
|
+
const upstreamName = token.upstreamName ?? token.name;
|
|
8300
|
+
const matches = (upstreamByName.get(upstreamName) ?? []).sort(
|
|
8301
|
+
(a, b) => (a.sourceIdentity ?? "").localeCompare(b.sourceIdentity ?? "")
|
|
8302
|
+
);
|
|
8303
|
+
if (matches.length !== 1) continue;
|
|
8304
|
+
const expected = matches[0];
|
|
8305
|
+
if (normalizedTokenValue(token) === normalizedTokenValue(expected)) continue;
|
|
8306
|
+
const location = token.location ?? {
|
|
8307
|
+
file: token.sourceIdentity ?? "tokens",
|
|
8308
|
+
line: 1,
|
|
8309
|
+
column: 1
|
|
8310
|
+
};
|
|
8311
|
+
findings.push(
|
|
8312
|
+
makeFinding({
|
|
8313
|
+
ruleId: RULE_ID22,
|
|
8314
|
+
ruleVersion: RULE_VERSION23,
|
|
8315
|
+
severity: "warn",
|
|
8316
|
+
message: `Local token ${token.name} is ${token.value}, but upstream ${upstreamName} is ${expected.value}.`,
|
|
8317
|
+
location,
|
|
8318
|
+
evidence: ix.evidence([token.id, expected.id]),
|
|
8319
|
+
fingerprintIdentity: {
|
|
8320
|
+
local: token.name,
|
|
8321
|
+
upstream: upstreamName,
|
|
8322
|
+
localSource: token.sourceIdentity,
|
|
8323
|
+
upstreamSource: expected.sourceIdentity
|
|
8324
|
+
},
|
|
8325
|
+
attributes: {
|
|
8326
|
+
local: { name: token.name, value: token.value, location: token.location },
|
|
8327
|
+
upstream: { name: expected.name, value: expected.value, location: expected.location },
|
|
8328
|
+
autoFix: false
|
|
8329
|
+
}
|
|
8330
|
+
})
|
|
8331
|
+
);
|
|
8332
|
+
}
|
|
8333
|
+
return findings;
|
|
8334
|
+
}
|
|
8335
|
+
|
|
8025
8336
|
// src/rules/emit-gate.ts
|
|
8026
8337
|
var BLOCKING_RULE_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
8027
8338
|
"styles/no-raw-color",
|
|
@@ -8056,10 +8367,14 @@ function isDenyEligible(finding, failOnWarnings) {
|
|
|
8056
8367
|
// src/rules/tiers.ts
|
|
8057
8368
|
var RULE_TIER = {
|
|
8058
8369
|
// ---- Tier A — contract vocabulary -------------------------------------
|
|
8370
|
+
"components/shadow-component": "contract",
|
|
8371
|
+
// canonical-component identity drift
|
|
8059
8372
|
"components/prefer-library": "contract",
|
|
8060
8373
|
// canonical-component bypass (FUI1004)
|
|
8061
8374
|
"tokens/css-vars-must-be-defined": "contract",
|
|
8062
8375
|
// token drift (FUI2015)
|
|
8376
|
+
"tokens/upstream-drift": "contract",
|
|
8377
|
+
// authored local/upstream value drift (FUI2017)
|
|
8063
8378
|
// ---- Tier B — generic hygiene -----------------------------------------
|
|
8064
8379
|
"components/unknown-prop": "hygiene",
|
|
8065
8380
|
"components/forbidden-prop-value": "hygiene",
|
|
@@ -8101,8 +8416,10 @@ function hygieneTierRuleIds() {
|
|
|
8101
8416
|
return Object.keys(RULE_TIER).filter((id) => !isContractTierRule(id));
|
|
8102
8417
|
}
|
|
8103
8418
|
var VOCABULARY_ORDER = [
|
|
8419
|
+
"components/shadow-component",
|
|
8104
8420
|
"components/prefer-library",
|
|
8105
|
-
"tokens/css-vars-must-be-defined"
|
|
8421
|
+
"tokens/css-vars-must-be-defined",
|
|
8422
|
+
"tokens/upstream-drift"
|
|
8106
8423
|
];
|
|
8107
8424
|
function vocabularyRank(ruleId) {
|
|
8108
8425
|
const index = VOCABULARY_ORDER.indexOf(ruleId);
|
|
@@ -8161,6 +8478,11 @@ var RULES = [
|
|
|
8161
8478
|
version: "1",
|
|
8162
8479
|
run: ruleComponentsPreferLibrary
|
|
8163
8480
|
},
|
|
8481
|
+
{
|
|
8482
|
+
id: "components/shadow-component",
|
|
8483
|
+
version: "1",
|
|
8484
|
+
run: ruleComponentsShadowComponent
|
|
8485
|
+
},
|
|
8164
8486
|
{
|
|
8165
8487
|
id: "styles/no-raw-color",
|
|
8166
8488
|
version: "1",
|
|
@@ -8221,6 +8543,11 @@ var RULES = [
|
|
|
8221
8543
|
version: "1",
|
|
8222
8544
|
run: ruleTokensCssVarsMustBeDefined
|
|
8223
8545
|
},
|
|
8546
|
+
{
|
|
8547
|
+
id: "tokens/upstream-drift",
|
|
8548
|
+
version: "1",
|
|
8549
|
+
run: ruleTokensUpstreamDrift
|
|
8550
|
+
},
|
|
8224
8551
|
{
|
|
8225
8552
|
id: "theme/no-theme-coupled-literal",
|
|
8226
8553
|
version: "1",
|
|
@@ -8310,19 +8637,23 @@ function evaluateGovernanceIntegrity(input) {
|
|
|
8310
8637
|
policyFamily.reason = "no governance policy resolved";
|
|
8311
8638
|
}
|
|
8312
8639
|
const componentsConfig = configs.get("components/prefer-library");
|
|
8313
|
-
const
|
|
8640
|
+
const confirmedBridges = input.policy?.canonicalBridges ?? [];
|
|
8641
|
+
const componentsArmed = confirmedBridges.length > 0 || componentsConfig?.enabled === true && hasEffectiveComponentVocabulary(componentsConfig.options);
|
|
8314
8642
|
const componentsFamily = {
|
|
8315
8643
|
id: "components",
|
|
8316
8644
|
armed: componentsArmed,
|
|
8317
|
-
rules: [
|
|
8645
|
+
rules: [
|
|
8646
|
+
...confirmedBridges.length > 0 ? ["imports/preferred-path"] : [],
|
|
8647
|
+
...componentsConfig?.enabled === true ? ["components/prefer-library"] : []
|
|
8648
|
+
]
|
|
8318
8649
|
};
|
|
8319
8650
|
if (!componentsArmed) {
|
|
8320
8651
|
if (componentsConfig?.enabled === true) {
|
|
8321
8652
|
componentsFamily.reason = "components/prefer-library enabled but no effective canonical source";
|
|
8322
|
-
componentsFamily.remediation = "add govern.
|
|
8653
|
+
componentsFamily.remediation = "add govern.canonicalBridges for local wrappers, govern.canonicalSources, or designSystem.path/packageName";
|
|
8323
8654
|
} else {
|
|
8324
8655
|
componentsFamily.reason = "components/prefer-library not enabled";
|
|
8325
|
-
componentsFamily.remediation = "add govern.
|
|
8656
|
+
componentsFamily.remediation = "add govern.canonicalBridges for local wrappers, govern.canonicalSources, or designSystem.path/packageName";
|
|
8326
8657
|
}
|
|
8327
8658
|
}
|
|
8328
8659
|
const cssVarsActive = input.cssVarsActive ?? policyDeclaresCssVars(input.policy);
|
|
@@ -8408,6 +8739,74 @@ function evaluateGovernanceIntegrity(input) {
|
|
|
8408
8739
|
};
|
|
8409
8740
|
}
|
|
8410
8741
|
|
|
8742
|
+
// src/canonical-bridge.ts
|
|
8743
|
+
function canonicalBridgeContractMappings(bridges) {
|
|
8744
|
+
return (bridges ?? []).map((bridge) => ({
|
|
8745
|
+
component: `${bridge.underlying.packageName}#${bridge.underlying.exportName}`,
|
|
8746
|
+
canonical: bridge.local.componentKey,
|
|
8747
|
+
status: "confirmed",
|
|
8748
|
+
importPath: bridge.local.moduleSpecifier,
|
|
8749
|
+
bridge: {
|
|
8750
|
+
underlyingPackageName: bridge.underlying.packageName,
|
|
8751
|
+
underlyingExportName: bridge.underlying.exportName,
|
|
8752
|
+
localComponentKey: bridge.local.componentKey,
|
|
8753
|
+
localExportName: bridge.local.exportName,
|
|
8754
|
+
implementationFiles: [...bridge.local.implementationFiles],
|
|
8755
|
+
decisionSource: bridge.decision.source
|
|
8756
|
+
}
|
|
8757
|
+
}));
|
|
8758
|
+
}
|
|
8759
|
+
|
|
8760
|
+
// src/effective-governance-inputs.ts
|
|
8761
|
+
var EFFECTIVE_GOVERNANCE_INPUTS_SCHEMA = "effective-governance-inputs:v1";
|
|
8762
|
+
function compileEffectiveGovernanceInputs(options) {
|
|
8763
|
+
const projection = {
|
|
8764
|
+
schema: EFFECTIVE_GOVERNANCE_INPUTS_SCHEMA,
|
|
8765
|
+
policySource: options.policySource,
|
|
8766
|
+
config: {
|
|
8767
|
+
path: options.configPath ? normalizePath2(options.configPath) : null,
|
|
8768
|
+
digest: options.configDigest
|
|
8769
|
+
},
|
|
8770
|
+
components: {
|
|
8771
|
+
canonicalSources: sortRecords(options.policy?.canonicalSources ?? []),
|
|
8772
|
+
canonicalBridges: sortRecords(options.policy?.canonicalBridges ?? []),
|
|
8773
|
+
definitionFiles: normalizePaths(options.componentDefinitionFiles)
|
|
8774
|
+
},
|
|
8775
|
+
tokens: {
|
|
8776
|
+
declared: normalizePaths(options.tokens.declared),
|
|
8777
|
+
loadedDefinitions: options.tokens.loadedDefinitions,
|
|
8778
|
+
diagnostics: [...options.tokens.diagnostics].sort(),
|
|
8779
|
+
...options.tokens.catalog ? {
|
|
8780
|
+
catalog: {
|
|
8781
|
+
...options.tokens.catalog,
|
|
8782
|
+
configuredSources: normalizePaths(options.tokens.catalog.configuredSources),
|
|
8783
|
+
parsedSources: normalizePaths(options.tokens.catalog.parsedSources),
|
|
8784
|
+
definitions: sortRecords(options.tokens.catalog.definitions),
|
|
8785
|
+
diagnostics: sortRecords(options.tokens.catalog.diagnostics),
|
|
8786
|
+
references: sortRecords(options.tokens.catalog.references),
|
|
8787
|
+
...options.tokens.catalog.sourceStates ? { sourceStates: sortRecords(options.tokens.catalog.sourceStates) } : {}
|
|
8788
|
+
}
|
|
8789
|
+
} : {}
|
|
8790
|
+
},
|
|
8791
|
+
eligibility: {
|
|
8792
|
+
include: normalizePaths(options.eligibility.include),
|
|
8793
|
+
exclude: normalizePaths(options.eligibility.exclude)
|
|
8794
|
+
}
|
|
8795
|
+
};
|
|
8796
|
+
return { ...projection, inputsHash: contractHash(projection) };
|
|
8797
|
+
}
|
|
8798
|
+
function normalizePaths(values) {
|
|
8799
|
+
return [...new Set(values.map(normalizePath2))].sort();
|
|
8800
|
+
}
|
|
8801
|
+
function normalizePath2(value) {
|
|
8802
|
+
return value.replace(/\\/gu, "/").replace(/^\.\//u, "");
|
|
8803
|
+
}
|
|
8804
|
+
function sortRecords(values) {
|
|
8805
|
+
return [...values].sort(
|
|
8806
|
+
(left, right) => canonicalPreimage(left).localeCompare(canonicalPreimage(right))
|
|
8807
|
+
);
|
|
8808
|
+
}
|
|
8809
|
+
|
|
8411
8810
|
// src/contract/preimage.ts
|
|
8412
8811
|
var CONTRACT_DOMAINS = ["components", "tokens", "canonicalMap", "policy"];
|
|
8413
8812
|
var CONTRACT_PREIMAGE_SCHEMA = "fcid-preimage:v1";
|
|
@@ -8463,6 +8862,15 @@ function projectCanonicalMap(mappings) {
|
|
|
8463
8862
|
component: mapping.component,
|
|
8464
8863
|
canonical: mapping.canonical,
|
|
8465
8864
|
importPath: mapping.importPath ? projectV1OwnedImportIdentity(mapping.importPath) : void 0,
|
|
8865
|
+
bridge: mapping.bridge ? {
|
|
8866
|
+
underlyingPackageName: projectV1OwnedImportIdentity(
|
|
8867
|
+
mapping.bridge.underlyingPackageName
|
|
8868
|
+
),
|
|
8869
|
+
underlyingExportName: mapping.bridge.underlyingExportName,
|
|
8870
|
+
localComponentKey: projectV1OwnedComponentId(mapping.bridge.localComponentKey),
|
|
8871
|
+
localExportName: mapping.bridge.localExportName,
|
|
8872
|
+
implementationFiles: [...mapping.bridge.implementationFiles].sort()
|
|
8873
|
+
} : void 0,
|
|
8466
8874
|
resolves: mapping.resolves ? sortCanonical(mapping.resolves) : void 0,
|
|
8467
8875
|
propMapping: mapping.propMapping ? sortCanonical(
|
|
8468
8876
|
mapping.propMapping.map((entry) => ({
|
|
@@ -8755,6 +9163,133 @@ function readPreferLibraryRule(config) {
|
|
|
8755
9163
|
const raw = config?.rules?.["components/prefer-library"];
|
|
8756
9164
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
8757
9165
|
}
|
|
9166
|
+
|
|
9167
|
+
// src/identity/component-key.ts
|
|
9168
|
+
function buildComponentKey({ repoRelativeFile, exportName }) {
|
|
9169
|
+
const file = normalizeRepoRelativeFile(repoRelativeFile);
|
|
9170
|
+
const name = exportName.trim();
|
|
9171
|
+
if (!file) throw new Error("repoRelativeFile must not be empty");
|
|
9172
|
+
if (!name) throw new Error("exportName must not be empty");
|
|
9173
|
+
return `${file}#${name}`;
|
|
9174
|
+
}
|
|
9175
|
+
function normalizeRepoRelativeFile(file) {
|
|
9176
|
+
const slashNormalized = file.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
9177
|
+
const absolute = slashNormalized.startsWith("/");
|
|
9178
|
+
const parts = [];
|
|
9179
|
+
for (const part of slashNormalized.split("/")) {
|
|
9180
|
+
if (!part || part === ".") continue;
|
|
9181
|
+
if (part === ".." && parts.length > 0 && parts.at(-1) !== "..") {
|
|
9182
|
+
parts.pop();
|
|
9183
|
+
continue;
|
|
9184
|
+
}
|
|
9185
|
+
parts.push(part);
|
|
9186
|
+
}
|
|
9187
|
+
return `${absolute ? "/" : ""}${parts.join("/")}`;
|
|
9188
|
+
}
|
|
9189
|
+
|
|
9190
|
+
// src/identity/classify.ts
|
|
9191
|
+
function classifyIdentity(input) {
|
|
9192
|
+
const { definition, renderRoot } = input;
|
|
9193
|
+
if (definition.canonical) return { state: "canonical", confidence: "confirmed" };
|
|
9194
|
+
const decision = input.decisions?.find(
|
|
9195
|
+
(candidate) => candidate.componentKey === definition.componentKey
|
|
9196
|
+
);
|
|
9197
|
+
if (decision?.decision === "sanctioned-wrapper") {
|
|
9198
|
+
return withTarget("variant", "confirmed", decision.canonicalTarget ?? rootTarget(input));
|
|
9199
|
+
}
|
|
9200
|
+
if (decision?.decision === "rejected-wrapper") {
|
|
9201
|
+
return withTarget("shadow", "confirmed", decision.canonicalTarget ?? shadowTarget(input));
|
|
9202
|
+
}
|
|
9203
|
+
if (renderRoot.kind === "canonical") {
|
|
9204
|
+
if ((input.usageCounts?.nestedElements ?? 0) > 0 || (input.usageCounts?.staticTextChildren ?? 0) > 0) {
|
|
9205
|
+
return withTarget("composite", "confirmed", renderRoot.target.componentKey);
|
|
9206
|
+
}
|
|
9207
|
+
const confidence = strongOverlap(input.propSurfaceOverlap) ? "likely" : "review";
|
|
9208
|
+
return withTarget("variant", confidence, renderRoot.target.componentKey);
|
|
9209
|
+
}
|
|
9210
|
+
if (renderRoot.kind === "intrinsic") {
|
|
9211
|
+
return classifyIntrinsic(input, renderRoot);
|
|
9212
|
+
}
|
|
9213
|
+
if (renderRoot.kind === "mixed") {
|
|
9214
|
+
if (renderRoot.canonicalTargets.length > 0) {
|
|
9215
|
+
const target = bestCanonicalReference(
|
|
9216
|
+
definition.exportName,
|
|
9217
|
+
renderRoot.canonicalTargets
|
|
9218
|
+
)?.componentKey;
|
|
9219
|
+
const fullyResolved = renderRoot.externalTargets.length === 0 && renderRoot.unresolvedNames.length === 0;
|
|
9220
|
+
return withTarget("composite", fullyResolved ? "confirmed" : "likely", target);
|
|
9221
|
+
}
|
|
9222
|
+
if (renderRoot.externalTargets.length > 0 && renderRoot.localTargets.length === 0 && renderRoot.unresolvedNames.length === 0) {
|
|
9223
|
+
return { state: "external", confidence: "likely" };
|
|
9224
|
+
}
|
|
9225
|
+
return withTarget("unresolved", "review", rootTarget(input));
|
|
9226
|
+
}
|
|
9227
|
+
if (renderRoot.kind === "external") {
|
|
9228
|
+
return { state: "external", confidence: "confirmed" };
|
|
9229
|
+
}
|
|
9230
|
+
return withTarget("unresolved", "review", rootTarget(input));
|
|
9231
|
+
}
|
|
9232
|
+
function classifyIntrinsic(input, root) {
|
|
9233
|
+
const target = bestCanonicalReference(input.definition.exportName, root.canonicalTargets);
|
|
9234
|
+
if (!target || !root.interactive && !root.hasRole) {
|
|
9235
|
+
return withTarget("unresolved", "review", rootTarget(input));
|
|
9236
|
+
}
|
|
9237
|
+
let confidence = root.precisionTier === "exact-html" || root.precisionTier === "role-reimpl" ? "confirmed" : "likely";
|
|
9238
|
+
if (confidence === "likely" && input.stylingOwnership !== "layout-only" && (strongOverlap(input.propSurfaceOverlap) || input.stylingOwnership === "visual-role")) {
|
|
9239
|
+
confidence = "confirmed";
|
|
9240
|
+
}
|
|
9241
|
+
return { state: "shadow", confidence, canonicalTarget: target.role };
|
|
9242
|
+
}
|
|
9243
|
+
function rootTarget(input) {
|
|
9244
|
+
const { renderRoot } = input;
|
|
9245
|
+
if (renderRoot.kind === "canonical") return renderRoot.target.componentKey;
|
|
9246
|
+
if (renderRoot.kind === "intrinsic") {
|
|
9247
|
+
return bestCanonicalReference(input.definition.exportName, renderRoot.canonicalTargets)?.role;
|
|
9248
|
+
}
|
|
9249
|
+
if (renderRoot.kind === "mixed") {
|
|
9250
|
+
return bestCanonicalReference(input.definition.exportName, renderRoot.canonicalTargets)?.componentKey;
|
|
9251
|
+
}
|
|
9252
|
+
return bestMessageTarget(input.definition.exportName, input.nameSimilarityTargets ?? []);
|
|
9253
|
+
}
|
|
9254
|
+
function shadowTarget(input) {
|
|
9255
|
+
const { renderRoot } = input;
|
|
9256
|
+
if (renderRoot.kind === "canonical") return renderRoot.target.role;
|
|
9257
|
+
if (renderRoot.kind === "intrinsic") {
|
|
9258
|
+
return bestCanonicalReference(input.definition.exportName, renderRoot.canonicalTargets)?.role;
|
|
9259
|
+
}
|
|
9260
|
+
if (renderRoot.kind === "mixed") {
|
|
9261
|
+
return bestCanonicalReference(input.definition.exportName, renderRoot.canonicalTargets)?.role;
|
|
9262
|
+
}
|
|
9263
|
+
return bestMessageTarget(input.definition.exportName, input.nameSimilarityTargets ?? []);
|
|
9264
|
+
}
|
|
9265
|
+
function bestCanonicalReference(definitionName, candidates) {
|
|
9266
|
+
return [...candidates].sort(
|
|
9267
|
+
(left, right) => nameSimilarityScore(definitionName, right.role) - nameSimilarityScore(definitionName, left.role) || left.componentKey.localeCompare(right.componentKey)
|
|
9268
|
+
)[0];
|
|
9269
|
+
}
|
|
9270
|
+
function bestMessageTarget(definitionName, candidates) {
|
|
9271
|
+
return [...candidates].sort(
|
|
9272
|
+
(left, right) => nameSimilarityScore(definitionName, right) - nameSimilarityScore(definitionName, left) || left.localeCompare(right)
|
|
9273
|
+
)[0];
|
|
9274
|
+
}
|
|
9275
|
+
function nameSimilarityScore(definitionName, target) {
|
|
9276
|
+
const definition = normalizeName(definitionName);
|
|
9277
|
+
const candidate = normalizeName(target);
|
|
9278
|
+
if (!candidate) return 0;
|
|
9279
|
+
if (definition === candidate) return 3;
|
|
9280
|
+
if (definition.endsWith(candidate) || definition.startsWith(candidate)) return 2;
|
|
9281
|
+
if (definition.includes(candidate) || candidate.includes(definition)) return 1;
|
|
9282
|
+
return 0;
|
|
9283
|
+
}
|
|
9284
|
+
function normalizeName(value) {
|
|
9285
|
+
return value.split(/[.#/]/).at(-1)?.replace(/[^a-z0-9]/gi, "").toLowerCase() ?? "";
|
|
9286
|
+
}
|
|
9287
|
+
function strongOverlap(overlap) {
|
|
9288
|
+
return overlap !== void 0 && overlap >= 0.7;
|
|
9289
|
+
}
|
|
9290
|
+
function withTarget(state, confidence, canonicalTarget) {
|
|
9291
|
+
return canonicalTarget ? { state, confidence, canonicalTarget } : { state, confidence };
|
|
9292
|
+
}
|
|
8758
9293
|
export {
|
|
8759
9294
|
AGENT_CONTEXT_RELATIVE_PATH,
|
|
8760
9295
|
AGENT_FORMAT_SCHEMA_VERSION,
|
|
@@ -8768,6 +9303,7 @@ export {
|
|
|
8768
9303
|
DEFAULTS,
|
|
8769
9304
|
DEFAULT_ENHANCED_STYLE_PROPERTIES,
|
|
8770
9305
|
DEFAULT_STYLE_PROPERTIES,
|
|
9306
|
+
EFFECTIVE_GOVERNANCE_INPUTS_SCHEMA,
|
|
8771
9307
|
EVIDENCE_ORDER,
|
|
8772
9308
|
EXPLAIN_URL_BASE,
|
|
8773
9309
|
FRAGMENTS_INTERNAL_RULE_IDS,
|
|
@@ -8805,6 +9341,7 @@ export {
|
|
|
8805
9341
|
bridgeSourceViolations,
|
|
8806
9342
|
budgetBar,
|
|
8807
9343
|
buildAgentFormat,
|
|
9344
|
+
buildComponentKey,
|
|
8808
9345
|
buildRegistryArtifact,
|
|
8809
9346
|
buildRegistryFile,
|
|
8810
9347
|
buildRegistryInstallPlan,
|
|
@@ -8821,6 +9358,9 @@ export {
|
|
|
8821
9358
|
byRuleId,
|
|
8822
9359
|
calculateDeltaE,
|
|
8823
9360
|
canBlock,
|
|
9361
|
+
canonicalBridgeContractMappings,
|
|
9362
|
+
canonicalBridgeV1Schema,
|
|
9363
|
+
canonicalDirectionConflictsTarget,
|
|
8824
9364
|
canonicalJson,
|
|
8825
9365
|
canonicalPreimage,
|
|
8826
9366
|
canonicalizeOwnedComponentId,
|
|
@@ -8831,6 +9371,7 @@ export {
|
|
|
8831
9371
|
checkStoryExclusion,
|
|
8832
9372
|
clampMaxPasses,
|
|
8833
9373
|
classifyComplexity,
|
|
9374
|
+
classifyIdentity,
|
|
8834
9375
|
collectRegistryInstallDependencies,
|
|
8835
9376
|
colorSimilarity,
|
|
8836
9377
|
compareByVocabularyRank,
|
|
@@ -8842,6 +9383,7 @@ export {
|
|
|
8842
9383
|
compareStylesWithTokens,
|
|
8843
9384
|
compileBlock,
|
|
8844
9385
|
compileComponentFacts,
|
|
9386
|
+
compileEffectiveGovernanceInputs,
|
|
8845
9387
|
compileFragment,
|
|
8846
9388
|
compileGlobalGovernanceFacts,
|
|
8847
9389
|
compileRecipe,
|
|
@@ -8926,6 +9468,7 @@ export {
|
|
|
8926
9468
|
hashRegistryFileContent,
|
|
8927
9469
|
hexToRgb,
|
|
8928
9470
|
hygieneTierRuleIds,
|
|
9471
|
+
indexComponentIdentityUsage,
|
|
8929
9472
|
inferTokenCategory,
|
|
8930
9473
|
inferTokenGroup,
|
|
8931
9474
|
isColorLike,
|
|
@@ -8952,6 +9495,8 @@ export {
|
|
|
8952
9495
|
makeClassNameDynamicFact,
|
|
8953
9496
|
makeClassNameLiteralFact,
|
|
8954
9497
|
makeComponentCapabilityFact,
|
|
9498
|
+
makeComponentDefinitionFact,
|
|
9499
|
+
makeComponentIdentityFact,
|
|
8955
9500
|
makeComponentMetadataFact,
|
|
8956
9501
|
makeContractTokenFact,
|
|
8957
9502
|
makeFinding,
|
|
@@ -9034,6 +9579,7 @@ export {
|
|
|
9034
9579
|
parseTokenFile,
|
|
9035
9580
|
parseTokens,
|
|
9036
9581
|
portableRepoPathError,
|
|
9582
|
+
projectCanonicalDirectionConflicts,
|
|
9037
9583
|
projectContractPreimage,
|
|
9038
9584
|
projectV1OwnedComponentId,
|
|
9039
9585
|
projectV1OwnedImportIdentity,
|
|
@@ -9076,6 +9622,7 @@ export {
|
|
|
9076
9622
|
ruleA11yRequiredAccessibleName,
|
|
9077
9623
|
ruleComponentsForbiddenPropValue,
|
|
9078
9624
|
ruleComponentsPreferLibrary,
|
|
9625
|
+
ruleComponentsShadowComponent,
|
|
9079
9626
|
ruleComponentsUnknownProp,
|
|
9080
9627
|
ruleJsxPreferredComponent,
|
|
9081
9628
|
ruleJsxPreferredImportPath,
|