npm package: @10up/block-renderer-theme-json
Description: Theme.json parser and design token extractor for WordPress themes
Latest version: 0.1.7

# @10up/block-renderer-theme-json

Parse WordPress `theme.json` files and extract design tokens for colors, typography, spacing, and more.

## Installation

```bash
npm install @10up/block-renderer-theme-json
# or
pnpm add @10up/block-renderer-theme-json
```

## Overview

WordPress themes define their design system in `theme.json`. This package:

1. **Parses theme.json** - Supports v2 and v3 schema versions
2. **Extracts design tokens** - Colors, gradients, fonts, spacing, shadows
3. **Loads style variations** - From the `/styles` directory
4. **CSS variable utilities** - Convert between WordPress formats and actual CSS

## Usage

### Parse a Complete Theme

The main entry point - parses theme.json and loads style variations:

```typescript
import { parseTheme } from '@10up/block-renderer-theme-json';

const theme = parseTheme('/path/to/theme');

// Access extracted tokens
console.log(theme.tokens.colors.palette);
// [{ slug: 'primary', color: '#0073aa', name: 'Primary' }, ...]

console.log(theme.tokens.typography.fontSizes);
// [{ slug: 'small', size: '13px', name: 'Small' }, ...]

console.log(theme.tokens.spacing.spacingSizes);
// [{ slug: '50', size: '1.5rem', name: 'Medium' }, ...]

// Access theme styles
console.log(theme.styles.global);
// { color: { background: 'var:preset|color|base' }, ... }

// Access style variations
console.log(theme.variations);
// { 'dark': { global: { color: { ... } } }, ... }

// Access raw theme.json
console.log(theme.raw);
```

### Parse theme.json Directly

If you already have the theme.json content:

```typescript
import { parseThemeJson } from '@10up/block-renderer-theme-json';

const themeJson = {
  version: 3,
  settings: {
    color: {
      palette: [
        { slug: 'primary', color: '#0073aa', name: 'Primary' }
      ]
    }
  }
};

const result = parseThemeJson(themeJson);
console.log(result.tokens);
```

### Extract Tokens Only

```typescript
import { extractTokens } from '@10up/block-renderer-theme-json';

const tokens = extractTokens(themeJson.settings);
console.log(tokens.colors.palette);
console.log(tokens.typography.fontFamilies);
```

### Extract Styles Only

```typescript
import { extractStyles } from '@10up/block-renderer-theme-json';

const styles = extractStyles(themeJson.styles);
console.log(styles.global);     // Global styles
console.log(styles.elements);   // Element styles (h1, p, link, etc.)
console.log(styles.blocks);     // Per-block styles
```

### Load Style Variations

```typescript
import { loadStyleVariations } from '@10up/block-renderer-theme-json';

const variations = loadStyleVariations('/path/to/theme');
// Reads all .json files from /path/to/theme/styles/
// { 'dark': { ... }, 'contrast': { ... } }
```

### Load Section Styles

For themes that define section-specific styles (like hero sections, testimonials, etc.):

```typescript
import { loadSectionStyles } from '@10up/block-renderer-theme-json';

const sectionStyles = loadSectionStyles('/path/to/theme');
// Returns map of section name to styles
```

### Parse Theme Options

```typescript
import { parseTheme } from '@10up/block-renderer-theme-json';
import type { ParseThemeOptions } from '@10up/block-renderer-theme-json';

const options: ParseThemeOptions = {
  loadVariations: true,  // Load style variations (default: true)
  loadSectionStyles: true  // Load section styles (default: true)
};

const theme = parseTheme('/path/to/theme', options);
```

## CSS Variable Utilities

WordPress uses two formats for design token references:

1. **WordPress format**: `var:preset|color|primary` (used in block attributes)
2. **CSS format**: `var(--wp--preset--color--primary)` (actual CSS output)

### Generate WordPress Reference

```typescript
import { generateCssVarReference } from '@10up/block-renderer-theme-json';

generateCssVarReference('color', 'primary');
// 'var:preset|color|primary'

generateCssVarReference('spacing', '50');
// 'var:preset|spacing|50'

generateCssVarReference('font-family', 'heading');
// 'var:preset|font-family|heading'
```

### Generate CSS Custom Property

```typescript
import { generateCssPropertyName, generateCssVarFunction } from '@10up/block-renderer-theme-json';

generateCssPropertyName('color', 'primary');
// '--wp--preset--color--primary'

generateCssVarFunction('color', 'primary');
// 'var(--wp--preset--color--primary)'
```

### Parse References

```typescript
import { parseCssVarReference, isCssVarReference } from '@10up/block-renderer-theme-json';

isCssVarReference('var:preset|color|primary');  // true
isCssVarReference('#ff0000');                   // false

parseCssVarReference('var:preset|color|primary');
// { type: 'color', slug: 'primary' }

parseCssVarReference('var:preset|spacing|50');
// { type: 'spacing', slug: '50' }
```

### Convert to CSS

```typescript
import { convertToActualCss } from '@10up/block-renderer-theme-json';

convertToActualCss('var:preset|color|primary');
// 'var(--wp--preset--color--primary)'

convertToActualCss('#ff0000');  // Returns unchanged if not a reference
// '#ff0000'
```

## Token Utilities

### Get Available Slugs

```typescript
import {
  getColorSlugs,
  getGradientSlugs,
  getFontFamilySlugs,
  getFontSizeSlugs,
  getSpacingSlugs,
  getShadowSlugs,
} from '@10up/block-renderer-theme-json';

const theme = parseTheme('/path/to/theme');

getColorSlugs(theme.tokens);       // ['primary', 'secondary', 'base', ...]
getGradientSlugs(theme.tokens);    // ['vivid-cyan-blue', ...]
getFontFamilySlugs(theme.tokens);  // ['system', 'heading', 'body', ...]
getFontSizeSlugs(theme.tokens);    // ['small', 'medium', 'large', ...]
getSpacingSlugs(theme.tokens);     // ['20', '30', '40', '50', ...]
getShadowSlugs(theme.tokens);      // ['natural', 'deep', 'sharp', ...]
```

### Validate Slugs

```typescript
import { validateSlug } from '@10up/block-renderer-theme-json';

validateSlug(theme.tokens, 'color', 'primary');     // true
validateSlug(theme.tokens, 'color', 'nonexistent'); // false
validateSlug(theme.tokens, 'font-size', 'large');   // true
```

### Get Token Values

```typescript
import { getTokenValue } from '@10up/block-renderer-theme-json';

getTokenValue(theme.tokens, 'color', 'primary');     // '#0073aa'
getTokenValue(theme.tokens, 'font-size', 'large');   // '1.5rem'
getTokenValue(theme.tokens, 'spacing', '50');        // '1.5rem'
getTokenValue(theme.tokens, 'color', 'nonexistent'); // null
```

## Ignite WP Support

Special support for [Ignite WP](https://developer.wordpress.org/) themes with fluid typography:

### Extract Ignite Tokens

```typescript
import {
  extractIgniteTokens,
  extractTypographyPresets,
  extractFluidValues,
  isFluidValue,
  getTypographyPresetClassName,
} from '@10up/block-renderer-theme-json';

// Check if a value uses fluid typography
isFluidValue({ min: '1rem', max: '2rem' });  // true
isFluidValue('1.5rem');                       // false

// Extract fluid values from theme settings
const fluidValues = extractFluidValues(themeJson.settings);

// Extract typography presets (display, heading, body, etc.)
const typographyPresets = extractTypographyPresets(themeJson.settings);
// { display: { fontFamily: '...', fontSize: '...' }, ... }

// Get the CSS class name for a typography preset
getTypographyPresetClassName('display');  // 'has-display-typography'

// Extract all Ignite-specific tokens
const igniteTokens = extractIgniteTokens(themeJson.settings);
// { typographyPresets: {...}, fluidValues: {...} }
```

### Ignite Types

```typescript
interface FluidValue {
  min: string;
  max: string;
}

interface TypographyPreset {
  fontFamily?: string;
  fontSize?: string | FluidValue;
  fontWeight?: string;
  lineHeight?: string;
  letterSpacing?: string;
  textTransform?: string;
}

interface IgniteTokens {
  typographyPresets: Record<string, TypographyPreset>;
  fluidValues: Record<string, FluidValue>;
}
```

## CSS Generator

Generate CSS from theme.json section styles:

```typescript
import {
  generateSectionStyleCss,
  generateAllSectionStylesCss,
  blockTypeToSelector,
  flattenCustomToProperties,
} from '@10up/block-renderer-theme-json';

// Convert a block type to CSS selector
blockTypeToSelector('core/paragraph');  // '.wp-block-paragraph'
blockTypeToSelector('core/group');      // '.wp-block-group'

// Flatten custom properties for CSS
const properties = flattenCustomToProperties({
  spacing: { gap: '1rem' }
});
// { '--wp--custom--spacing--gap': '1rem' }

// Generate CSS for a single section style
const css = generateSectionStyleCss('hero', sectionStyle);

// Generate CSS for all section styles
const allCss = generateAllSectionStylesCss(sectionStyles);
```

## Types

### ThemeTokens

```typescript
interface ThemeTokens {
  colors: {
    palette: ColorPreset[];
    gradients: GradientPreset[];
    duotone: DuotonePreset[];
  };
  typography: {
    fontFamilies: FontFamilyPreset[];
    fontSizes: FontSizePreset[];
  };
  spacing: {
    spacingSizes: SpacingPreset[];
    units: string[];
  };
  shadow: {
    presets: ShadowPreset[];
  };
  layout: {
    contentSize?: string;
    wideSize?: string;
  };
  custom: Record<string, unknown>;
}
```

### Preset Types

```typescript
interface ColorPreset {
  name: string;
  slug: string;
  color: string;
}

interface GradientPreset {
  name: string;
  slug: string;
  gradient: string;
}

interface FontSizePreset {
  name: string;
  slug: string;
  size: string;
  fluid?: { min?: string; max?: string } | boolean;
}

interface FontFamilyPreset {
  name: string;
  slug: string;
  fontFamily: string;
  fontFace?: FontFace[];
}

interface SpacingPreset {
  name: string;
  slug: string;
  size: string;
}

interface ShadowPreset {
  name: string;
  slug: string;
  shadow: string;
}
```

### ParsedTheme

```typescript
interface ParsedTheme {
  version: number;
  tokens: ThemeTokens;
  styles: ThemeStyles;
  variations: Record<string, Partial<ThemeStyles>>;
  raw: ThemeJson;
}
```

### TokenType

```typescript
type TokenType =
  | 'color'
  | 'gradient'
  | 'font-family'
  | 'font-size'
  | 'spacing'
  | 'shadow'
  | 'duotone';
```

## Complete Exports

### Parser Functions

| Function | Description |
|----------|-------------|
| `parseTheme(themePath, options?)` | Parse theme directory, return tokens, styles, variations |
| `parseThemeJson(themeJson)` | Parse theme.json object directly |
| `extractTokens(settings)` | Extract tokens from settings object |
| `extractStyles(styles)` | Extract styles from styles object |
| `loadThemeJson(filePath)` | Load and parse a theme.json file |
| `loadStyleVariations(themePath)` | Load style variations from /styles |
| `loadSectionStyles(themePath)` | Load section styles from theme |

### CSS Variable Functions

| Function | Description |
|----------|-------------|
| `generateCssVarReference(type, slug)` | Generate WordPress var:preset format |
| `generateCssPropertyName(type, slug)` | Generate CSS custom property name |
| `generateCssVarFunction(type, slug)` | Generate var() CSS function |
| `parseCssVarReference(reference)` | Parse var:preset string to components |
| `isCssVarReference(value)` | Check if value is a var:preset reference |
| `convertToActualCss(reference)` | Convert var:preset to actual CSS |

### Token Utility Functions

| Function | Description |
|----------|-------------|
| `getColorSlugs(tokens)` | Get all color slugs |
| `getGradientSlugs(tokens)` | Get all gradient slugs |
| `getFontFamilySlugs(tokens)` | Get all font family slugs |
| `getFontSizeSlugs(tokens)` | Get all font size slugs |
| `getSpacingSlugs(tokens)` | Get all spacing slugs |
| `getShadowSlugs(tokens)` | Get all shadow slugs |
| `validateSlug(tokens, type, slug)` | Check if slug exists in tokens |
| `getTokenValue(tokens, type, slug)` | Get actual value for a token |

### Ignite WP Functions

| Function | Description |
|----------|-------------|
| `isFluidValue(value)` | Check if value is a fluid typography value |
| `extractFluidValues(settings)` | Extract fluid values from theme settings |
| `extractTypographyPresets(settings)` | Extract typography presets |
| `extractIgniteTokens(settings)` | Extract all Ignite-specific tokens |
| `getTypographyPresetClassName(preset)` | Get CSS class for typography preset |

### CSS Generator Functions

| Function | Description |
|----------|-------------|
| `blockTypeToSelector(blockType)` | Convert block type to CSS selector |
| `flattenCustomToProperties(custom)` | Flatten custom properties for CSS |
| `generateSectionStyleCss(name, style)` | Generate CSS for a section style |
| `generateAllSectionStylesCss(styles)` | Generate CSS for all section styles |

### Types

| Type | Description |
|------|-------------|
| `ThemeTokens` | Complete tokens structure |
| `ThemeStyles` | Theme styles structure |
| `SectionStyle` | Section-specific styles |
| `ParsedTheme` | Complete parsed theme data |
| `ParseThemeOptions` | Options for parseTheme function |
| `ThemeJson` | Raw theme.json structure |
| `ThemeJsonSettings` | Settings section type |
| `ColorPreset` | Color token definition |
| `GradientPreset` | Gradient token definition |
| `DuotonePreset` | Duotone filter definition |
| `FontFamilyPreset` | Font family definition |
| `FontFace` | Font face definition |
| `FontSizePreset` | Font size definition |
| `SpacingPreset` | Spacing token definition |
| `ShadowPreset` | Shadow token definition |
| `StyleObject` | Style object for elements/blocks |
| `SidesObject` | Margin/padding sides object |
| `TokenType` | Union of token type strings |
| `FluidValue` | Fluid typography min/max value |
| `TypographyPreset` | Typography preset definition |
| `IgniteTokens` | Ignite WP-specific tokens |

### Zod Schemas

| Schema | Description |
|--------|-------------|
| `colorPresetSchema` | Validate color preset objects |
| `gradientPresetSchema` | Validate gradient preset objects |
| `duotonePresetSchema` | Validate duotone preset objects |
| `fontSizePresetSchema` | Validate font size preset objects |
| `spacingPresetSchema` | Validate spacing preset objects |
| `shadowPresetSchema` | Validate shadow preset objects |

## License

MIT