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

Support Non-Figma Design Systems like CDT #34

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ node_modules/

build

src/build
src/build

theme.generated.json
126 changes: 73 additions & 53 deletions ingest-tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const fs = require( 'fs' ).promises;
const path = require( 'path' );
const cp = require( 'child_process' );
const chalk = require( 'chalk' );
const pathLib = require( '@irrelon/path' );
const styleDictionary = require( './src/style-dictionary/main' );
const utility = require( './src/utility' );

Expand All @@ -13,17 +14,17 @@ const generatedThemeFileName = 'theme.generated.json';
const themeFileName = 'theme.json';

commander
.version( '0.5.0', '-v, --version' )
.description( 'Inject the tokens from the provided Figma export into theme.json' )
.version( '1.0.0', '-v, --version' )
.description( 'Inject the tokens from the provided design system export into theme.json, from either a JSON file/directory when the source is FIGMA or a CSS file when its not FIGMA.' )
.usage( '[OPTIONS]...' )
.requiredOption( '--tokenPath <path>', 'path to token JSON file or directory' )
.requiredOption( '--tokenPath <path>', 'path to token JSON/CSS file or directory of JSON files' )
.requiredOption( '--themePath <path>', 'path to a WordPress theme' )
.option( '--sourceSet <theme-name>', 'NON-PRO PLUGIN OPTION: source set in the token JSON' )
.option( '--sourceSet <theme-name>', '(FIGMA ONLY) NON-PRO PLUGIN OPTION: source set in the token JSON' )
.option(
'--layerSets <theme-name>',
'NON-PRO PLUGIN OPTION: layers built using the source set in token JSON'
'(FIGMA ONLY) NON-PRO PLUGIN OPTION: layers built using the source set in token JSON'
)
.option( '--theme <theme-name>', 'PRO PLUGIN OPTION: selected $themes set in token JSON' )
.option( '--theme <theme-name>', '(FIGMA ONLY) PRO PLUGIN OPTION: selected $themes set in token JSON' )
.option(
'--themeJsonSection <prefix>',
'section to insert tokens into theme.json->settings->custom',
Expand All @@ -39,62 +40,81 @@ async function ingestTokens( options ) {
utility.throwErrorForFileNotExisting( tokenPath, 'No core tokens found for path:' );

const tokenJson = await utility.getTokensFromPath( tokenPath );
const { enabledSets, sourceSets } = utility.getThemeSets(
tokenJson,
options.sourceSet,
options.layerSets,
options.theme
);


const themeDirectory = utility.resolvePath( options.themePath );
const themeJsonPath = path.join( themeDirectory, themeFileName );
utility.throwErrorForFileNotExisting( themeJsonPath, 'No theme.json found for path:' );
utility.throwErrorForFileNotExisting( tokenPath, 'No core tokens found for path:' );

const themeJsonBuffer = await fs.readFile( themeJsonPath );
const themeJson = JSON.parse( themeJsonBuffer.toString() );

const tokenTransformerArgs = [
'token-transformer',
`${ tokenPath }`,
`${ transformerFilePath }`,
'--throwErrorWhenNotResolved',
'--expandTypography=true',
];

// Just the source sets are present
if ( enabledSets && enabledSets.length === 0 ) {
tokenTransformerArgs.push( sourceSets );
let builtTokens = {};
if ( tokenPath.endsWith( '.css' ) ) {
const tokenMapJson = await utility.getJsonFromPath( 'reference-files/token-map.json' );
const rulesFromTokens = tokenJson.stylesheet.rules.filter( rule => rule.type === 'rule' && rule.declarations.length > 0 );

Object.keys(tokenMapJson).forEach(key => {
rulesFromTokens.forEach( rule => {
rule.declarations.forEach( declaration => {
if ( ( typeof declaration.property === 'string' || declaration.property instanceof String ) && declaration.property === tokenMapJson[ key ] ) {
pathLib.set( builtTokens, key, declaration.value);
}
} );
} );
} );

console.log( '\n' + chalk.green( '✔︎ Processed CSS file' ) );
} else {
const selectedSets = [
// Order the source token sets first for use with token-transformer
...sourceSets,
...enabledSets,
];

tokenTransformerArgs.push( selectedSets, sourceSets );
}

const transformResult = cp.spawnSync( 'npx', tokenTransformerArgs );

if ( transformResult.status > 0 ) {
console.log( [ 'npx', ...tokenTransformerArgs ].join( ' ' ) );

let errorString = transformResult.stderr.toString();
console.error( '\n' );
// Assumption is that the massive minified code is dumped first, followed by the actual error
errorString = errorString.substring( errorString.indexOf( 'Error:' ) );
console.error( errorString );
utility.throwError(
'Unable to process the token file provided. Please review any errors logged above, verify that it is valid.'
const { enabledSets, sourceSets } = utility.getThemeSets(
tokenJson,
options.sourceSet,
options.layerSets,
options.theme
);
} else {
console.log( chalk.green( '✔︎ Processed with token-transformer' ) );
}

const builtTokens = await styleDictionary.getProcessedTokens( transformerFilePath );
const tokenTransformerArgs = [
'token-transformer',
`${ tokenPath }`,
`${ transformerFilePath }`,
'--throwErrorWhenNotResolved',
'--expandTypography=true',
];

// Just the source sets are present
if ( enabledSets && enabledSets.length === 0 ) {
tokenTransformerArgs.push( sourceSets );
} else {
const selectedSets = [
// Order the source token sets first for use with token-transformer
...sourceSets,
...enabledSets,
];

tokenTransformerArgs.push( selectedSets, sourceSets );
}

const transformResult = cp.spawnSync( 'npx', tokenTransformerArgs );

if ( transformResult.status > 0 ) {
console.log( [ 'npx', ...tokenTransformerArgs ].join( ' ' ) );

let errorString = transformResult.stderr.toString();
console.error( '\n' );
// Assumption is that the massive minified code is dumped first, followed by the actual error
errorString = errorString.substring( errorString.indexOf( 'Error:' ) );
console.error( errorString );
utility.throwError(
'Unable to process the token file provided. Please review any errors logged above, verify that it is valid.'
);
} else {
console.log( chalk.green( '✔︎ Processed with token-transformer' ) );
}

builtTokens = await styleDictionary.getProcessedTokens( transformerFilePath );

console.log( '\n' + chalk.green( '✔︎ Processed with Style Dictionary' ) );
}

console.log( '\n' + chalk.green( '✔︎ Processed with Style Dictionary' ) );
const themeJsonBuffer = await fs.readFile( themeJsonPath );
const themeJson = JSON.parse( themeJsonBuffer.toString() );

if ( options.themeJsonSection ) {
themeJson.settings.custom[ options.themeJsonSection ] = {
Expand Down
93 changes: 93 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
"description": "Tool to ingest tokens from a design system into the theme.json of a WP Site",
"version": "1.0.0",
"dependencies": {
"@irrelon/path": "^6.0.2",
"chalk": "^4.1.2",
"commander": "^9.1.0",
"css": "^3.0.0",
"style-dictionary": "^3.7.1",
"token-transformer": "^0.0.33"
},
Expand Down
Loading