Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/style-dictionary-token-output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hebilicious/cssforge": minor
---

Add Style Dictionary-compatible token JSON output with CSS variable metadata, resolved values, reference paths, and CLI support through `--mode style-dictionary` and `--style-dictionary`.
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ import { cssForge } from "./.cssforge/output.ts";
export { cssForge };
```

5. Use the Style Dictionary-compatible token JSON in token-aware tools:

CSS Forge can also generate token JSON where each leaf keeps the CSS variable reference
as `value`, the fully resolved value as `$resolvedValue`, and provenance metadata under
`attributes`. This is useful for tools such as Musea that scan component styles for
`var(--token)` usage while still needing resolved values for labels and swatches.

```bash
pnpm run cssforge -- --mode style-dictionary --style-dictionary ./.cssforge/tokens.sd.json
```

## Configuration

### Colors
Expand Down Expand Up @@ -1027,19 +1038,25 @@ pnpm run cssforge
# Watch mode
pnpm run cssforge -- --watch

# Custom paths and output
pnpm run cssforge -- --config ./foo/bar/custom-path.ts --css ./dist/design-tokens.css --ts ./dist/design-tokens.ts --json ./dist/design-tokens.json --mode all
# Custom paths and output
pnpm run cssforge -- --config ./foo/bar/custom-path.ts --css ./dist/design-tokens.css --ts ./dist/design-tokens.ts --json ./dist/design-tokens.json --style-dictionary ./dist/design-tokens.sd.json --mode all

# Style Dictionary-compatible JSON only
pnpm run cssforge -- --mode style-dictionary --style-dictionary ./dist/design-tokens.sd.json
```

## Programmatic Usage

You can also use CSS Forge programmatically:

```typescript
import { generateCSS } from "jsr:@hebilicious/cssforge";
import { generateCSS, generateStyleDictionaryJSON } from "jsr:@hebilicious/cssforge";

// Generate CSS string
const css = generateCSS(config);

// Generate Style Dictionary-compatible token JSON
const tokens = generateStyleDictionaryJSON(config);
```

## Agentic usage
Expand Down
23 changes: 20 additions & 3 deletions packages/cssforge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ import { cssForge } from "./.cssforge/output.ts";
export { cssForge };
```

5. Use the Style Dictionary-compatible token JSON in token-aware tools:

CSS Forge can also generate token JSON where each leaf keeps the CSS variable reference
as `value`, the fully resolved value as `$resolvedValue`, and provenance metadata under
`attributes`. This is useful for tools such as Musea that scan component styles for
`var(--token)` usage while still needing resolved values for labels and swatches.

```bash
pnpm run cssforge -- --mode style-dictionary --style-dictionary ./.cssforge/tokens.sd.json
```

## Configuration

### Colors
Expand Down Expand Up @@ -1027,19 +1038,25 @@ pnpm run cssforge
# Watch mode
pnpm run cssforge -- --watch

# Custom paths and output
pnpm run cssforge -- --config ./foo/bar/custom-path.ts --css ./dist/design-tokens.css --ts ./dist/design-tokens.ts --json ./dist/design-tokens.json --mode all
# Custom paths and output
pnpm run cssforge -- --config ./foo/bar/custom-path.ts --css ./dist/design-tokens.css --ts ./dist/design-tokens.ts --json ./dist/design-tokens.json --style-dictionary ./dist/design-tokens.sd.json --mode all

# Style Dictionary-compatible JSON only
pnpm run cssforge -- --mode style-dictionary --style-dictionary ./dist/design-tokens.sd.json
```

## Programmatic Usage

You can also use CSS Forge programmatically:

```typescript
import { generateCSS } from "jsr:@hebilicious/cssforge";
import { generateCSS, generateStyleDictionaryJSON } from "jsr:@hebilicious/cssforge";

// Generate CSS string
const css = generateCSS(config);

// Generate Style Dictionary-compatible token JSON
const tokens = generateStyleDictionaryJSON(config);
```

## Agentic usage
Expand Down
32 changes: 29 additions & 3 deletions packages/cssforge/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ import type { CommandDef } from "citty";
*/
import { defineCommand, runMain } from "citty";
import type { CSSForgeConfig } from "./config.ts";
import { generateCSS, generateJSON, generateTS } from "./generator.ts";
import {
generateCSS,
generateJSON,
generateStyleDictionaryJSON,
generateTS,
} from "./generator.ts";

const writeFileRecursive = (path: string, data: string) =>
fs
Expand All @@ -28,11 +33,13 @@ export interface BuildOptions {
/** Path to the configuration file. */
config: string;
/** The output mode. */
mode: "css" | "json" | "ts" | "all";
mode: "css" | "json" | "ts" | "style-dictionary" | "all";
/** Path for the CSS output file. */
cssOutput: string;
/** Path for the JSON output file. */
jsonOutput: string;
/** Path for the Style Dictionary-compatible JSON output file. */
styleDictionaryOutput: string;
/** Path for the TypeScript output file. */
tsOutput: string;
}
Expand All @@ -47,12 +54,14 @@ export async function build({
tsOutput,
cssOutput,
jsonOutput,
styleDictionaryOutput,
mode,
}: BuildOptions): Promise<{ success: boolean; error?: unknown }> {
try {
const absoluteconfig = resolve(process.cwd(), config);
const absoluteCssOutput = resolve(process.cwd(), cssOutput);
const absoluteJsonOutput = resolve(process.cwd(), jsonOutput);
const absoluteStyleDictionaryOutput = resolve(process.cwd(), styleDictionaryOutput);
const absoluteTsOutput = resolve(process.cwd(), tsOutput);

// Import config with cache busting
Expand All @@ -75,6 +84,16 @@ export async function build({
console.log(`✔ Generated JSON written to ${jsonOutput}`);
}

if (mode === "style-dictionary" || mode === "all") {
await writeFileRecursive(
absoluteStyleDictionaryOutput,
generateStyleDictionaryJSON(userConfig.default as CSSForgeConfig),
);
console.log(
`✔ Generated Style Dictionary JSON written to ${styleDictionaryOutput}`,
);
}

if (mode === "ts" || mode === "all") {
await writeFileRecursive(
absoluteTsOutput,
Expand Down Expand Up @@ -147,7 +166,7 @@ const mainCommand = defineCommand({
},
mode: {
type: "string",
description: "Output mode (css, json, ts, all)",
description: "Output mode (css, json, ts, style-dictionary, all)",
alias: "m",
default: "all",
},
Expand All @@ -161,6 +180,11 @@ const mainCommand = defineCommand({
description: "Optional path for an output JSON file",
default: "./.cssforge/output.json",
},
"style-dictionary": {
type: "string",
description: "Path for the Style Dictionary-compatible JSON output file",
default: "./.cssforge/tokens.sd.json",
},
css: {
type: "string",
description: "Path for the output CSS file",
Expand All @@ -174,13 +198,15 @@ const mainCommand = defineCommand({
},
async run({ args }) {
const { watch: shouldWatch, config, css, json, ts, mode, prefix } = args;
const styleDictionary = args["style-dictionary"];
const realPath = (p: string) => resolve(prefix, p);
const settings = {
mode,
config: realPath(config),
cssOutput: realPath(css),
tsOutput: realPath(ts),
jsonOutput: realPath(json),
styleDictionaryOutput: realPath(styleDictionary),
} as BuildOptions;
if (shouldWatch) {
const cleanup = await watch(settings);
Expand Down
Loading
Loading