-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tokens): add tooling for EDS theming (#1738)
Tickets: [EDS-996, EDS-746, EDS-747, EDS-749] - handle initializing token override file from base - handle configuration for local paths to use - handle comparison to base in package for checksum - handle updates to themes when base has changed - apply updates to prepare for introduction to EDS - update naming for consistency - add in better ordering of commands and exception handling - sync changes to style-dictionary - add documentation for using EDS commands - update README to link to new documentation Tested with tag `13.2.0-alpha.0`
- Loading branch information
1 parent
2b0855e
commit 91497bf
Showing
9 changed files
with
357 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
module.exports = { | ||
/** | ||
* Fetch the EDS config from the project using the lilconfig hierarchy. | ||
* This can be from package.json, or from various separate non-YAML files. | ||
* | ||
* @see https://github.com/antonk52/lilconfig#usage | ||
* @returns nullable config object returned from lilconfig | ||
*/ | ||
getConfig: async function () { | ||
const { lilconfig } = require('lilconfig'); | ||
|
||
// read in the config from config file, package json "eds", etc. | ||
const settings = await lilconfig('eds').search(); | ||
|
||
// If no config exists, fail | ||
if (!settings) { | ||
throw new Error( | ||
'Please add EDS config to your project before continuing (specify "json" and "css" target paths)', | ||
); | ||
} | ||
|
||
return settings.config; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#!/usr/bin/env node | ||
(async function () { | ||
const StyleDictionary = require('style-dictionary'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const { getConfig } = require('./_util'); | ||
|
||
let packageRootPath; | ||
try { | ||
packageRootPath = | ||
path.dirname(require.resolve('@chanzuckerberg/eds')) + '/tokens/json/'; | ||
} catch (e) { | ||
console.error('EDS package not installed. Using local path...'); | ||
packageRootPath = | ||
path.dirname(require.main.path) + '/src/tokens-dist/json/'; | ||
} | ||
|
||
// Read the config to sort out where to read JSON from and where to write the CSS file | ||
const config = await getConfig(); | ||
|
||
// read and parse JSON files on disk | ||
const localTheme = JSON.parse( | ||
fs.readFileSync(`${config.json}app-theme.json`, 'utf8'), | ||
); | ||
const baseTheme = JSON.parse( | ||
fs.readFileSync(`${packageRootPath}theme-base.json`, 'utf8'), | ||
); | ||
|
||
// define the header to use in the resulting CSS file so people know not to edit it directly | ||
StyleDictionary.registerFileHeader({ | ||
name: 'cssOverrideHeader', | ||
fileHeader: (defaultMessage) => [ | ||
...defaultMessage, | ||
'To update, edit app-theme.json, then run `npx eds-apply-theme`', | ||
], | ||
}); | ||
|
||
const EDSStyleDictionary = StyleDictionary.extend({ | ||
source: [config.json + 'app-theme.json'], | ||
platforms: { | ||
css: { | ||
transforms: [...StyleDictionary.transformGroup.css, 'name/cti/kebab'], | ||
buildPath: config.css, | ||
files: [ | ||
{ | ||
format: 'css/variables', | ||
destination: 'app-theme.css', | ||
options: { | ||
fileHeader: 'cssOverrideHeader', | ||
}, | ||
filter: function (token) { | ||
// don't allow theming on legacy tokens | ||
return token.attributes.category !== 'legacy'; | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
}); | ||
|
||
/** | ||
* Determine if the given theme file is a subset of what's in the base theme file. | ||
* If it isnt, throw an error: | ||
* - If keys are in base that are missing in the theme file, that's OK (no need to override everything) | ||
* - If keys are in theme that aren't in base, throw (you can't theme tokens that don't exist in EDS) | ||
* @param {object} base The tokens theme file stored in the EDS project | ||
* @param {object} theme The project theme file stored in the app code (same format as bas) | ||
* @param {Array} path The base path, stored as an array of object key names (default []) | ||
* @throws Error when there are tokens in theme that aren't in base | ||
*/ | ||
function isStrictSubset(base, theme, path = []) { | ||
for (const name in theme) { | ||
if (typeof theme[name] === 'object') { | ||
if (base[name] === undefined) { | ||
throw new Error( | ||
`Local themeable value does not exist in base theme: --${path.join( | ||
'-', | ||
)}.${name}"`, | ||
); | ||
} | ||
isStrictSubset(base[name], theme[name], path.concat(name)); | ||
} | ||
} | ||
} | ||
|
||
try { | ||
// Keys in the theme file must be a strict subset of those in the base file | ||
isStrictSubset(baseTheme, localTheme); | ||
EDSStyleDictionary.buildAllPlatforms(); | ||
} catch (error) { | ||
// TODO: if theme has things not in base, error showing where the conflict | ||
console.error('EDS theming error:', error.message); | ||
return; | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#!/usr/bin/env node | ||
(async function () { | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { getConfig } = require('./_util'); | ||
|
||
let packageRootPath; | ||
try { | ||
packageRootPath = | ||
path.dirname(require.resolve('@chanzuckerberg/eds')) + '/tokens/json/'; | ||
} catch (e) { | ||
console.error('EDS package not installed. Using local path...'); | ||
packageRootPath = | ||
path.dirname(require.main.path) + '/src/tokens-dist/json/'; | ||
} | ||
|
||
// read in the config from config file, package json "eds", etc. | ||
const config = await getConfig(); | ||
|
||
// take the packaged token file and place a copy in the project's 'json' specified path | ||
if (config) { | ||
try { | ||
fs.copyFileSync( | ||
packageRootPath + 'theme-base.json', | ||
`${config.json}app-theme.json`, | ||
fs.constants.COPYFILE_EXCL, | ||
); | ||
} catch (error) { | ||
console.error('The local theme file already exists. Exiting.'); | ||
return 1; | ||
} | ||
|
||
console.log( | ||
'File copy completed! Please use `npx eds-apply-theme` to generate theme tokens (CSS Variables).', | ||
); | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.