Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tokens): add function to generate json file #206

Merged
merged 12 commits into from
Jul 31, 2023
32 changes: 31 additions & 1 deletion packages/tokens/scripts/generate-tokens.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import fs from 'fs'
import { OUTPUT_DIR, TOKENS_DIR, extractTokensFromCss } from './generate-tokens'
import path from 'path'

import {
OUTPUT_DIR,
TOKENS_DIR,
extractTokensFromCss,
generateJsonFile,
} from './generate-tokens'

jest.mock('fs', () => ({
readFileSync: jest.fn().mockReturnValue(`
Expand All @@ -11,6 +18,10 @@ jest.mock('fs', () => ({
}))

describe('Generate Tokens', () => {
afterEach(() => {
jest.clearAllMocks()
})

it('should extract tokens from CSS content', () => {
expect(fs.readFileSync).toHaveBeenCalledWith(TOKENS_DIR, 'utf8')
expect(fs.writeFileSync).toHaveBeenCalledWith(
Expand All @@ -28,4 +39,23 @@ describe('Generate Tokens', () => {
extractTokensFromCss(cssContent, 'color')
expect(tokens).toEqual({})
})

it('should generate JSON file with tokens', () => {
generateJsonFile(`
--color-neutral-black: #000;
--color-contextual-success-dark-1: #106105;
--color-brand-primary-dark-1: #b85000;
--color-neutral-black-rgb: 0 0 0;
--spacing-small: 4px;
--zindex-1: 1;
`)

const expectedTokens = `{\n "spacing-small\": \"4px\",\n "color-neutral-black\": \"#000\",\n "color-contextual-success-dark-1\": \"#106105\",\n "color-brand-primary-dark-1\": \"#b85000\",\n "zindex-1\": \"1\"\n}`

expect(fs.writeFileSync).toHaveBeenCalledWith(
path.join(__dirname, '../../dist/tokens.json'),
expectedTokens,
'utf8'
)
})
})
57 changes: 57 additions & 0 deletions packages/tokens/scripts/generate-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,62 @@ export function generateJavaScriptFile(outputFilePath: string) {
fs.writeFileSync(outputFilePath, jsCode, 'utf8')
}

export function generateJsonFile(cssContent: string) {
const spacingRegex = /--spacing-(\w+):\s*([\d\w.#]+);/g
const colorRegex =
/--color-((?:neutral|brand|contextual)-\w+(?:-\w+)*)(?:-(rgb))?:\s*(#(?:[a-fA-F0-9]{3}){1,2})?;?/g
const zIndexRegex = /--zindex-(\w+):\s*([\d]+);/g

function extractValues(css: string, regex: RegExp) {
const values: Record<string, string> = {}
let match
while ((match = regex.exec(css)) !== null) {
const [, name, value] = match
values[name] = value
}
return values
}

function extractColorValues(css: string, regex: RegExp) {
const values: Record<string, string> = {}
let match
while ((match = regex.exec(css)) !== null) {
const [, name, rgb, value] = match
values[name] = rgb ? `rgb(${value})` : value
}
return values
}

const spacingValues = extractValues(cssContent, spacingRegex)
const zIndexValues = extractValues(cssContent, zIndexRegex)
const colorValues = extractColorValues(cssContent, colorRegex)

const spacingOutput = Object.fromEntries(
Object.entries(spacingValues).map(([name, value]) => [
`spacing-${name}`,
value,
])
)
const colorOutput = Object.fromEntries(
Object.entries(colorValues).map(([name, value]) => [`color-${name}`, value])
)
const zIndexOutput = Object.fromEntries(
Object.entries(zIndexValues).map(([name, value]) => [
`zindex-${name}`,
value,
])
)
const output = {
...spacingOutput,
...colorOutput,
...zIndexOutput,
}

const jsonOutputFileName = 'tokens.json'
RodrigoRVSN marked this conversation as resolved.
Show resolved Hide resolved
const jsonOutputFilePath = path.join(`${OUTPUT_DIR}/dist`, jsonOutputFileName)
fs.writeFileSync(jsonOutputFilePath, JSON.stringify(output, null, 2), 'utf8')
}

function processCssFileByTokenPrefix(cssFilePath: string) {
const cssContent = fs.readFileSync(cssFilePath, 'utf8')

Expand All @@ -44,6 +100,7 @@ function processCssFileByTokenPrefix(cssFilePath: string) {
const outputFilePath = path.join(OUTPUT_DIR, outputFileName)

generateJavaScriptFile(outputFilePath)
generateJsonFile(cssContent)
RodrigoRVSN marked this conversation as resolved.
Show resolved Hide resolved
}

processCssFileByTokenPrefix(TOKENS_DIR)