@stilhq/core
v0.6.3
Published
Design token, component, and text QA pipeline for Stil
Maintainers
Readme
@stilhq/core
Design token and component pipeline for Stil. Normalize, validate, and build design tokens and components from Figma.
Install
npm install @stilhq/coreUsage
Basic Usage
import { buildThemeTokens, normalizeFromFigmaSemantics, validateMapping } from "@stilhq/core";
// Normalize raw Figma Variables
const rawTree = normalizeFromFigmaSemantics(figmaVariablesJson);
// Validate mapping
const result = validateMapping(mapping, rawTree);
// Build theme tokens
const tokens = buildThemeTokens(rawTree, mapping);Working with Unknown Tokens
import { buildThemeTokensWithMeta, normalizeWithWarnings } from "@stilhq/core";
// Normalize with warnings collection
const { tree, warnings } = normalizeWithWarnings(figmaVariablesJson);
// Build with metadata (unknown tokens, warnings, stats)
const { tokens, meta } = buildThemeTokensWithMeta(tree, mapping);
console.log(`Unknown tokens: ${meta.stats.unknownTokens}`);
console.log(`Warnings:`, meta.warnings);
// Unknown tokens are preserved in meta.unknown
// Known tokens are in tokens (existing contract maintained)Token Type Configuration
Token types are defined in src/config/token-types.default.json. This configuration maps root-level keys in token trees to semantic types:
{
"types": {
"color": {
"keys": ["color", "colours", "colors"],
"description": "Color tokens (hex, rgb, rgba, hsl, etc.)"
},
"spacing": {
"keys": ["spacing", "space", "gap", "margin", "padding"],
"description": "Spacing and dimension tokens (px, rem, em, etc.)"
}
}
}Unknown tokens (types not in this config) are:
- Preserved in
theme.meta.jsonwith warnings - Excluded from
theme.tokens.json(keeping existing contract) - Never dropped or lost
Workspace Override (Future Feature - v2)
In future versions, workspace repositories will be able to override token type mappings by placing a custom token-types.json in .stil/tokens/config/:
workspace_repo/
├── .stil/
│ └── tokens/
│ └── config/
│ ├── stil.config.json (existing: theme mapping)
│ └── token-types.json (future: custom type mappings)Priority: workspace config > core default
Component Processing
Basic Usage
import { buildComponentsWithMeta, normalizeComponents } from "@stilhq/core";
// Load component snapshot from Figma Plugin
const snapshot = JSON.parse(fs.readFileSync(".stil/components/snapshots/components.json"));
// Build with validation and metadata
const { components, meta } = buildComponentsWithMeta(snapshot);
// components.dist.json - valid components only
fs.writeFileSync("components.dist.json", JSON.stringify(components, null, 2));
// components.meta.json - validation warnings and stats
fs.writeFileSync("components.meta.json", JSON.stringify(meta, null, 2));Validation Rules (v1)
Components are validated with minimal rules:
- Component must have a name
- Component must have a variants array
- Variant must have a name
- Variant props are optional (warning only)
Invalid components/variants are:
- Excluded from
components.dist.json - Recorded in
components.meta.jsonwith reasons - Displayed in Storybook Warnings panel
- Non-fatal: CI passes even with validation issues
Component Metadata
type ComponentMeta = {
unknown: {
invalidComponents: Array<{ name: string; reason: string; nodeId?: string }>;
invalidVariants: Array<{
component: string;
variant: string;
reason: string;
nodeId?: string;
}>;
};
warnings: string[];
stats: {
totalComponents: number;
validComponents: number;
invalidComponents: number;
totalVariants: number;
validVariants: number;
invalidVariants: number;
};
};Text QA
Basic Usage
import { buildTextWithMeta, normalizeTextList } from "@stilhq/core";
// Load text snapshot from Figma Plugin
const snapshot = JSON.parse(fs.readFileSync(".stil/text/snapshots/textlist.json"));
// Build with QA validation and metadata
const { text, meta } = buildTextWithMeta(snapshot);
// textlist.dist.json - validated text items
fs.writeFileSync("textlist.dist.json", JSON.stringify(text, null, 2));
// textlist.meta.json - QA issues/warnings/stats
fs.writeFileSync("textlist.meta.json", JSON.stringify(meta, null, 2));QA Rules (v1)
Text items are validated with the following rules:
- Empty text: Text is empty or whitespace-only (Error)
- Duplicates: Same text appears in multiple locations (Info)
- Too long: Text exceeds 500 characters (Warning)
- Too short: Single character text (Info)
- Invalid characters: Contains control characters except tab/newline (Warning)
QA issues are:
- Recorded in
textlist.meta.jsonwith details - Displayed in Storybook QA report
- Non-fatal: CI passes even with issues (v1 policy)
Text Metadata
type TextMeta = {
issues: {
emptyText: Array<{ nodeId: string; nodePath?: string }>;
duplicates: Array<{
text: string;
count: number;
locations: Array<{ nodeId: string; nodePath?: string }>;
}>;
tooLong: Array<{ nodeId: string; text: string; length: number }>;
tooShort: Array<{ nodeId: string; text: string }>;
invalidChars: Array<{ nodeId: string; text: string; issue: string }>;
};
warnings: string[];
stats: {
totalItems: number;
validItems: number;
itemsWithIssues: number;
uniqueTexts: number;
emptyCount: number;
duplicateCount: number;
};
};Status
0.x — API is not yet stable. Breaking changes may occur in minor versions.
License
BUSL-1.1 — See LICENSE for details.
