diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 1320b9a32..000000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env"] -} diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 000000000..e5b6d8d6a --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/angry-balloons-yell.md b/.changeset/angry-balloons-yell.md new file mode 100644 index 000000000..21a8171fa --- /dev/null +++ b/.changeset/angry-balloons-yell.md @@ -0,0 +1,20 @@ +--- +'style-dictionary': major +--- + +BREAKING: +- `usesReference` util function is now `usesReferences` to be consistent plural form like the other reference util functions. +- `getReferences` first and second parameters have been swapped to be consistent with `resolveReferences`, so value first, then the full token object (instead of the entire dictionary instance). +- `getReferences` accepts a third options parameter which can be used to set reference Regex options as well as an unfilteredTokens object which can be used as a fallback when references are made to tokens that have been filtered out. There will be warnings logged for this. +- `format.formatter` removed old function signature of `(dictionary, platform, file)` in favor of `({ dictionary, platform, options, file })`. +- Types changes: + + - Style Dictionary is entirely strictly typed now, and there will be `.d.ts` files published next to every file, this means that if you import from one of Style Dictionary's entrypoints, you automatically get the types implicitly with it. This is a big win for people using TypeScript, as the majority of the codebase now has much better types, with much fewer `any`s. + - There is no more hand-written Style Dictionary module `index.d.ts` anymore that exposes all type interfaces on itself. This means that you can no longer grab types that aren't members of the Style Dictionary class directly from the default export of the main entrypoint. External types such as `Parser`, `Transform`, `DesignTokens`, etc. can be imported from the newly added types entrypoint: + + ```ts + import type { DesignTokens, Transform, Parser } from 'style-dictionary/types'; + ``` + + Please raise an issue if you find anything missing or suddenly broken. + - `Matcher`, `Transformer`, `Formatter`, etc. are still available, although no longer directly but rather as properties on their parents, so `Filter['matcher']`, `Transform['transformer']`, `Format['formatter']` diff --git a/.changeset/big-worms-collect-2.md b/.changeset/big-worms-collect-2.md new file mode 100644 index 000000000..543fc5dde --- /dev/null +++ b/.changeset/big-worms-collect-2.md @@ -0,0 +1,12 @@ +--- +'style-dictionary': minor +--- + +FileSystem that is used by Style Dictionary can now be customized: + +```js +import { setFs } from 'style-dictionary/fs'; +setFs(myFileSystemShim); +``` + +By default, it uses an in-memory filesystem shim `@bundled-es-modules/memfs` in browser context, `node:fs` built-in module in Node context. diff --git a/.changeset/big-worms-collect.md b/.changeset/big-worms-collect.md new file mode 100644 index 000000000..8d6321f0a --- /dev/null +++ b/.changeset/big-worms-collect.md @@ -0,0 +1,10 @@ +--- +'style-dictionary': major +--- + +- The project has been fully converted to [ESM format](https://nodejs.org/api/esm.html), which is also the format that the browser uses. + For users, this means you'll have to either use Style Dictionary in ESM JavaScript code, or dynamically import it into your CommonJS code. +- `StyleDictionary.extend()` method is now asynchronous, which means it returns `Promise` instead of `StyleDictionary.Core`. +- `allProperties` / `properties` was deprecated in v3, and is now removed from `StyleDictionary.Core`, use `allTokens` and `tokens` instead. +- Templates and the method `registerTemplate` were deprecated in v3, now removed. Use Formats instead. +- The package now uses [package entrypoints](https://nodejs.org/api/packages.html), which means that what is importable from the package is locked down to just the specified entrypoints: `style-dictionary` & `style-dictionary/fs`. If more is needed, please raise an issue explaining which file you were importing and why you need it to be public API. \ No newline at end of file diff --git a/.changeset/bright-timers-shout.md b/.changeset/bright-timers-shout.md new file mode 100644 index 000000000..487e45814 --- /dev/null +++ b/.changeset/bright-timers-shout.md @@ -0,0 +1,11 @@ +--- +'style-dictionary': patch +--- + +Allow overriding CSS formatting with commentStyle and commentPosition props. +For commentStyle, options are 'short' or 'long'. +For commentPosition, options are 'above' or 'inline'. + +We also ensure that the right defaults are picked for CSS, SASS/SCSS, Stylus and Less. + +This also contains a fix for ensuring that multi-line comments are automatically put "above" rather than "inline". diff --git a/.changeset/chilled-oranges-drive.md b/.changeset/chilled-oranges-drive.md new file mode 100644 index 000000000..147636634 --- /dev/null +++ b/.changeset/chilled-oranges-drive.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Fix some inconsistencies in some of the templates, usually with regards to spaces/newlines diff --git a/.changeset/chilly-numbers-work.md b/.changeset/chilly-numbers-work.md new file mode 100644 index 000000000..52907ccb0 --- /dev/null +++ b/.changeset/chilly-numbers-work.md @@ -0,0 +1,23 @@ +--- +'style-dictionary': minor +--- + +Allow not throwing fatal errors on broken token references/aliases, but `console.error` instead. + +You can also configure this on global/platform `log` property: + +```json +{ + "log": { + "errors": { + "brokenReferences": "console" + } + } +} +``` + +This setting defaults to `"error"` when not configured. + +`resolveReferences` and `getReferences` `warnImmediately` option is set to `true` which causes an error to be thrown/warned immediately by default, which can be configured to `false` if you know those utils are running in the transform/format hooks respectively, where the errors are collected and grouped, then thrown as 1 error/warning instead of multiple. + +Some minor grammatical improvements to some of the error logs were also done. diff --git a/.changeset/chilly-worms-vanish.md b/.changeset/chilly-worms-vanish.md new file mode 100644 index 000000000..75ddc991d --- /dev/null +++ b/.changeset/chilly-worms-vanish.md @@ -0,0 +1,27 @@ +--- +'style-dictionary': patch +--- + +All formats using `createPropertyFormatter` or `formattedVariables` helpers now respect the `file.options.formatting` option passed by users to customize formatting. + +Example: + +```js +{ + platforms: { + css: { + transformGroup: 'css', + buildPath, + files: [ + { + destination: 'variables.css', + format: 'css/variables', + options: { + formatting: { indentation: ' ' }, + }, + }, + ] + } + } +} +``` diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 000000000..f27cd6e87 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "v4", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.changeset/cuddly-cheetahs-drum.md b/.changeset/cuddly-cheetahs-drum.md new file mode 100644 index 000000000..fd8af976e --- /dev/null +++ b/.changeset/cuddly-cheetahs-drum.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Rename `typeW3CDelegate` utility function to `typeDtcgDelegate`, as using "W3C" is highly discouraged when the standard isn't a W3C standard yet. diff --git a/.changeset/curvy-geckos-exist.md b/.changeset/curvy-geckos-exist.md new file mode 100644 index 000000000..a12466848 --- /dev/null +++ b/.changeset/curvy-geckos-exist.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Conditionally only run dev scripts when CWD is style-dictionary, so our consumers don't run it by accident diff --git a/.changeset/eight-items-cheat.md b/.changeset/eight-items-cheat.md new file mode 100644 index 000000000..62a7357f8 --- /dev/null +++ b/.changeset/eight-items-cheat.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Patch StyleDictionary main type file to export default instead of "export =" which does not work in ESM. diff --git a/.changeset/eleven-llamas-raise.md b/.changeset/eleven-llamas-raise.md new file mode 100644 index 000000000..90f48e37c --- /dev/null +++ b/.changeset/eleven-llamas-raise.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix typeDtcgDelegate util $type property position to be allowed anywhere in the object, not just at the top. diff --git a/.changeset/famous-falcons-join.md b/.changeset/famous-falcons-join.md new file mode 100644 index 000000000..a54444aa5 --- /dev/null +++ b/.changeset/famous-falcons-join.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix outputReferences for DTCG spec tokens, by using token.original.$value instead of token.original.value. diff --git a/.changeset/famous-suns-rule.md b/.changeset/famous-suns-rule.md new file mode 100644 index 000000000..bf51e121f --- /dev/null +++ b/.changeset/famous-suns-rule.md @@ -0,0 +1,15 @@ +--- +'style-dictionary': minor +--- + +Added the following transforms for CSS, and added them to the `scss`, `css` and `less` transformGroups: + +- `fontFamily/css` -> wraps font names with spaces in `'` quotes +- `cubicBezier/css` -> array value, put inside `cubic-bezier()` CSS function +- `strokeStyle/css/shorthand` -> object value, transform to CSS shorthand +- `border/css/shorthand` -> object value, transform to CSS shorthand +- `typography/css/shorthand` -> object value, transform to CSS shorthand +- `transition/css/shorthand` -> object value, transform to CSS shorthand +- `shadow/css/shorthand` -> object value (or array of objects), transform to CSS shorthand + +The main intention here is to ensure that Style Dictionary is compliant with [DTCG draft specification](https://design-tokens.github.io/community-group/format/) out of the box with regards to exporting to CSS, where object-value tokens are not supported without transforming them to shorthands (or expanding them, which is a different feature that was added in `4.0.0-prerelease.27`). diff --git a/.changeset/fifty-dragons-heal.md b/.changeset/fifty-dragons-heal.md new file mode 100644 index 000000000..b8a6ee6a5 --- /dev/null +++ b/.changeset/fifty-dragons-heal.md @@ -0,0 +1,6 @@ +--- +'style-dictionary': minor +--- + +Preprocessors are a new feature added to style-dictionary, which allows you to do any type of processing of the token dictionary **after** parsing, **before** resolving and transforming. +See [preprocessor docs](https://github.com/amzn/style-dictionary/tree/v4/docs/preprocessors.md) for more information. diff --git a/.changeset/fifty-hats-study.md b/.changeset/fifty-hats-study.md new file mode 100644 index 000000000..b97f17435 --- /dev/null +++ b/.changeset/fifty-hats-study.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Expose flattenTokens utility. diff --git a/.changeset/five-crews-hear.md b/.changeset/five-crews-hear.md new file mode 100644 index 000000000..7ae3db260 --- /dev/null +++ b/.changeset/five-crews-hear.md @@ -0,0 +1,36 @@ +--- +'style-dictionary': major +--- + +BREAKING: File headers, when registered, are put inside the `hooks.fileHeaders` property now, as opposed to `fileHeader`. +Note the change from singular to plural form here. + +Before: + +```js +export default { + fileHeader: { + foo: (defaultMessages = []) => [ + 'Ola, planet!', + ...defaultMessages, + 'Hello, World!' + ], + }, +} +``` + +After: + +```js +export default { + hooks: { + fileHeaders: { + foo: (defaultMessages = []) => [ + 'Ola, planet!', + ...defaultMessages, + 'Hello, World!' + ], + }, + }, +} +``` diff --git a/.changeset/five-kangaroos-destroy.md b/.changeset/five-kangaroos-destroy.md new file mode 100644 index 000000000..7c181f432 --- /dev/null +++ b/.changeset/five-kangaroos-destroy.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Re-add and update example basic, fix copySync command in CLI, fix android templates to use $type for DTCG tokens. diff --git a/.changeset/four-fireants-try.md b/.changeset/four-fireants-try.md new file mode 100644 index 000000000..b81ddfb7f --- /dev/null +++ b/.changeset/four-fireants-try.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Pass outputReferenceFallbacks option to the relevant utilities, so the option actually works. diff --git a/.changeset/fuzzy-gorillas-prove.md b/.changeset/fuzzy-gorillas-prove.md new file mode 100644 index 000000000..2b32aa6c8 --- /dev/null +++ b/.changeset/fuzzy-gorillas-prove.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +'size/rem' transform to not transform tokens that already have a unit, such as `"4px"`, this should not be transformed to `"4rem"`. diff --git a/.changeset/gold-countries-own.md b/.changeset/gold-countries-own.md new file mode 100644 index 000000000..84ee791fa --- /dev/null +++ b/.changeset/gold-countries-own.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix parsers async support, use resolved filePath instead of raw. diff --git a/.changeset/gorgeous-lamps-chew.md b/.changeset/gorgeous-lamps-chew.md new file mode 100644 index 000000000..49efca435 --- /dev/null +++ b/.changeset/gorgeous-lamps-chew.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +options.log to be respected in all error logging, including platform specific logs. diff --git a/.changeset/great-trainers-shop.md b/.changeset/great-trainers-shop.md new file mode 100644 index 000000000..302e76bfc --- /dev/null +++ b/.changeset/great-trainers-shop.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow transitive transforms to return undefined, by doing this the transformer can mark itself as "deferred" for that specific token. This is useful when references in properties other than "value" need to be resolved first. diff --git a/.changeset/green-wolves-heal.md b/.changeset/green-wolves-heal.md new file mode 100644 index 000000000..838601546 --- /dev/null +++ b/.changeset/green-wolves-heal.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Escape double quotes for ts outputStringLiterals diff --git a/.changeset/grumpy-peaches-flow.md b/.changeset/grumpy-peaches-flow.md new file mode 100644 index 000000000..280933454 --- /dev/null +++ b/.changeset/grumpy-peaches-flow.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix small issue in type DTCG delegate utility type tracking. diff --git a/.changeset/happy-glasses-teach.md b/.changeset/happy-glasses-teach.md new file mode 100644 index 000000000..84f9c21d7 --- /dev/null +++ b/.changeset/happy-glasses-teach.md @@ -0,0 +1,43 @@ +--- +'style-dictionary': major +--- + +BREAKING: Logging has been redesigned a fair bit and is more configurable now. + +Before: + +```json +{ + "log": "error" // 'error' | 'warn' -> 'warn' is the default value +} +``` + +After: + +```json +{ + "log": { + "warnings": "error", // 'error' | 'warn' -> 'warn' is the default value + "verbosity": "verbose" // 'default' | 'verbose' | 'silent' -> 'default' is the default value + } +} +``` + +Log is now and object and the old "log" option is now "warnings". + +This configures whether the following five warnings will be thrown as errors instead of being logged as warnings: + +- Token value collisions (in the source) +- Token name collisions (when exporting) +- Missing "undo" function for Actions +- File not created because no tokens found, or all of them filtered out +- Broken references in file when using outputReferences, but referring to a token that's been filtered out + +Verbosity configures whether the following warnings/errors should display in a verbose manner: + +- Token collisions of both types (value & name) +- Broken references due to outputReferences & filters +- Token reference errors + +And it also configures whether success/neutral logs should be logged at all. +Using "silent" (or --silent in the CLI) means no logs are shown apart from fatal errors. \ No newline at end of file diff --git a/.changeset/happy-numbers-grab.md b/.changeset/happy-numbers-grab.md new file mode 100644 index 000000000..2c218aa46 --- /dev/null +++ b/.changeset/happy-numbers-grab.md @@ -0,0 +1,18 @@ +--- +'style-dictionary': minor +--- + +Expose a new utility called resolveReferences which takes a value containing references, the dictionary object, and resolves the value's references for you. + +```js +import StyleDictionary from 'style-dictionary'; +import { resolveReferences } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ tokens: { + foo: { value: 'foo' }, + bar: { value: '{foo}' }, + qux: { value: '{bar}' }, +}}); + +console.log(resolveReferences(sd.tokens.qux.value, sd.tokens)); // 'foo' +``` diff --git a/.changeset/happy-vans-end.md b/.changeset/happy-vans-end.md new file mode 100644 index 000000000..ee0827ca6 --- /dev/null +++ b/.changeset/happy-vans-end.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix a couple of spots where DTCG option wasn't properly taken into account, more tests added. diff --git a/.changeset/hip-candles-flow.md b/.changeset/hip-candles-flow.md new file mode 100644 index 000000000..525655361 --- /dev/null +++ b/.changeset/hip-candles-flow.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix logging to be ordered by platform when building or cleaning platforms. This now happens in parallel, resulting in the logs being ordered randomly which was a small regression to the logging experience. diff --git a/.changeset/honest-toes-wink.md b/.changeset/honest-toes-wink.md new file mode 100644 index 000000000..9e7a0e047 --- /dev/null +++ b/.changeset/honest-toes-wink.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow falsy token values for outputReferences, e.g. `0`. diff --git a/.changeset/kind-rats-invite.md b/.changeset/kind-rats-invite.md new file mode 100644 index 000000000..bd36a20bd --- /dev/null +++ b/.changeset/kind-rats-invite.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Improve and test the error handling of standalone usage of reference utilities. diff --git a/.changeset/large-peaches-fetch.md b/.changeset/large-peaches-fetch.md new file mode 100644 index 000000000..ca297758e --- /dev/null +++ b/.changeset/large-peaches-fetch.md @@ -0,0 +1,34 @@ +--- +'style-dictionary': major +--- + +BREAKING: Actions, when registered, are put inside the `hooks.actions` property now, as opposed to `action`. +Note the change from singular to plural form here. + +Before: + +```js +export default { + action: { + 'copy-assets': { + do: () => {} + undo: () => {} + } + }, +}; +``` + +After: + +```js +export default { + hooks: { + actions: { + 'copy-assets': { + do: () => {} + undo: () => {} + } + }, + }, +}; +``` diff --git a/.changeset/light-games-occur.md b/.changeset/light-games-occur.md new file mode 100644 index 000000000..3b2f03743 --- /dev/null +++ b/.changeset/light-games-occur.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': major +--- + +BREAKING: StyleDictionaryInstance.properties & .allProperties have been removed. They were deprecated in v3 in favor of .tokens and .allTokens. diff --git a/.changeset/light-lions-jam.md b/.changeset/light-lions-jam.md new file mode 100644 index 000000000..35cdb7529 --- /dev/null +++ b/.changeset/light-lions-jam.md @@ -0,0 +1,8 @@ +--- +'style-dictionary': minor +--- + +Fixes some noisy warnings still being outputted even when verbosity is set to default. + +We also added log.warning "disabled" option for turning off warnings altogether, meaning you only get success logs and fatal errors. +This option can be used from the CLI as well using the `--no-warn` flag. \ No newline at end of file diff --git a/.changeset/little-mice-pump.md b/.changeset/little-mice-pump.md new file mode 100644 index 000000000..e2d78ef53 --- /dev/null +++ b/.changeset/little-mice-pump.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Pass SD options to fileheaders and filters, to make it easier to use and adjust according to config or options like usesDTCG. diff --git a/.changeset/loud-planets-try.md b/.changeset/loud-planets-try.md new file mode 100644 index 000000000..c02e806b1 --- /dev/null +++ b/.changeset/loud-planets-try.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow using registerHook methods to override hooks that are already registered with the same name. diff --git a/.changeset/lucky-buckets-wave.md b/.changeset/lucky-buckets-wave.md new file mode 100644 index 000000000..32483b3a4 --- /dev/null +++ b/.changeset/lucky-buckets-wave.md @@ -0,0 +1,10 @@ +--- +'style-dictionary': minor +--- + +Some fixes for Expand utility: + +- Array values such as `dashArray` property of `strokeStyle` tokens no longer get expanded unintentionally, `typeof 'object'` check changed to `isPlainObject` check. +- Nested object-value tokens (such as `style` property inside `border` tokens) will now also be expanded. +- When references are involved during expansion, the resolved value is used when the property is an object, if not, then we keep the reference as is. + This is because if the reference is to an object value, the expansion might break the reference. diff --git a/.changeset/mean-panthers-serve.md b/.changeset/mean-panthers-serve.md new file mode 100644 index 000000000..c51e23fed --- /dev/null +++ b/.changeset/mean-panthers-serve.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Added `outputReferencesTransformed` utility function to pass into outputReferences option, which will not output references for values that have been transitively transformed. diff --git a/.changeset/mighty-rings-share.md b/.changeset/mighty-rings-share.md new file mode 100644 index 000000000..be240a724 --- /dev/null +++ b/.changeset/mighty-rings-share.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix for expand utility on platform level to adjust the token's path property. diff --git a/.changeset/neat-zoos-reflect.md b/.changeset/neat-zoos-reflect.md new file mode 100644 index 000000000..330262c05 --- /dev/null +++ b/.changeset/neat-zoos-reflect.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Support the use of "value"/"type"/"description" as token names or token group names, at the sacrifice of now no longer being able to combine non-DTCG and DTCG syntax within the same token dictionary. diff --git a/.changeset/nice-ears-shop.md b/.changeset/nice-ears-shop.md new file mode 100644 index 000000000..04e815c95 --- /dev/null +++ b/.changeset/nice-ears-shop.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow outputReferences to work on non-string values. diff --git a/.changeset/ninety-geckos-build.md b/.changeset/ninety-geckos-build.md new file mode 100644 index 000000000..b08229325 --- /dev/null +++ b/.changeset/ninety-geckos-build.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Expose `typeDtcgDelegate` utility. Don't take `value` into account anymore to determine that it's a design token, use `$value`. diff --git a/.changeset/ninety-ligers-tap.md b/.changeset/ninety-ligers-tap.md new file mode 100644 index 000000000..0784cd306 --- /dev/null +++ b/.changeset/ninety-ligers-tap.md @@ -0,0 +1,19 @@ +--- +'style-dictionary': major +--- + +BREAKING: moved `formatHelpers` away from the StyleDictionary class and export them in `'style-dictionary/utils'` entrypoint instead. + +Before + +```js +import StyleDictionary from 'style-dictionary'; + +const { fileHeader, formattedVariables } = StyleDictionary.formatHelpers; +``` + +After + +```js +import { fileHeader, formattedVariables } from 'style-dictionary/utils'; +``` diff --git a/.changeset/ninety-meals-hug.md b/.changeset/ninety-meals-hug.md new file mode 100644 index 000000000..32839040d --- /dev/null +++ b/.changeset/ninety-meals-hug.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Hotfix to address outputReferencesTransformed util not handling object-value tokens properly. diff --git a/.changeset/old-ants-fix.md b/.changeset/old-ants-fix.md new file mode 100644 index 000000000..9d3a59719 --- /dev/null +++ b/.changeset/old-ants-fix.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Make sure fs-node.js file is published to NPM. diff --git a/.changeset/old-nails-hammer.md b/.changeset/old-nails-hammer.md new file mode 100644 index 000000000..e437f9c80 --- /dev/null +++ b/.changeset/old-nails-hammer.md @@ -0,0 +1,72 @@ +--- +'style-dictionary': major +--- + +Filters, when registered, are put inside the `hooks.filters` property now, as opposed to `filter`. +Note the change from singular to plural form here. + +Before: + +```js +export default { + filter: { + 'colors-only': (token) => token.type === 'color, + }, + platforms: { + css: { + files: [{ + format: 'css/variables', + destination: '_variables.css', + filter: 'colors-only', + }], + }, + }, +}; +``` + +After: + +```js +export default { + hooks: { + filters: { + 'colors-only': (token) => token.type === 'color, + }, + }, + platforms: { + css: { + files: [{ + format: 'css/variables', + destination: '_variables.css', + filter: 'colors-only', + }], + }, + }, +}; +``` + +In addition, when using [`registerFilter`](/reference/api#registerfilter) method, the name of the filter function is now `filter` instead of `matcher`. + +Before: + +```js title="build-tokens.js" del={5} ins={6} +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerFilter({ + name: 'colors-only', + matcher: (token) => token.type === 'color', +}) +``` + +After: + +```js title="build-tokens.js" del={5} ins={6} +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerFilter({ + name: 'colors-only', + filter: (token) => token.type === 'color', +}) +``` + +> These changes also apply for the `filter` function (previously `matcher`) inside `transforms`. diff --git a/.changeset/pink-mangos-divide.md b/.changeset/pink-mangos-divide.md new file mode 100644 index 000000000..b3f94e6d2 --- /dev/null +++ b/.changeset/pink-mangos-divide.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow transformGroup to be combined with transforms, where standalone transforms will be added after the group's transforms. diff --git a/.changeset/polite-laws-reply.md b/.changeset/polite-laws-reply.md new file mode 100644 index 000000000..376e1c4cd --- /dev/null +++ b/.changeset/polite-laws-reply.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Moving the @zip.js/zip.js dependency from a devDependency to a normal dependency. diff --git a/.changeset/poor-parents-cover.md b/.changeset/poor-parents-cover.md new file mode 100644 index 000000000..41dc3369e --- /dev/null +++ b/.changeset/poor-parents-cover.md @@ -0,0 +1,28 @@ +--- +'style-dictionary': major +--- + +BREAKING: Transform groups, when registered, are put inside the `hooks.transformGroups` property now, as opposed to `transformGroup`. + +Before: + +```js +export default { + // register it inline or by SD.registerTransformGroup + transformGroup: { + foo: ['foo-transform'] + }, +}; +``` + +After: + +```js +export default { + hooks: { + transformGroups: { + foo: ['foo-transform'] + }, + }, +}; +``` diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..a477656d7 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,90 @@ +{ + "mode": "pre", + "tag": "prerelease", + "initialVersions": { + "style-dictionary": "3.8.0" + }, + "changesets": [ + "angry-balloons-yell", + "big-worms-collect-2", + "big-worms-collect", + "bright-timers-shout", + "chilled-oranges-drive", + "chilly-numbers-work", + "chilly-worms-vanish", + "cuddly-cheetahs-drum", + "curvy-geckos-exist", + "eight-items-cheat", + "eleven-llamas-raise", + "famous-falcons-join", + "famous-suns-rule", + "fifty-dragons-heal", + "fifty-hats-study", + "five-crews-hear", + "five-kangaroos-destroy", + "four-fireants-try", + "fuzzy-gorillas-prove", + "gold-countries-own", + "gorgeous-lamps-chew", + "great-trainers-shop", + "green-wolves-heal", + "grumpy-peaches-flow", + "happy-glasses-teach", + "happy-numbers-grab", + "happy-vans-end", + "hip-candles-flow", + "honest-toes-wink", + "kind-rats-invite", + "large-peaches-fetch", + "light-games-occur", + "light-lions-jam", + "little-mice-pump", + "loud-planets-try", + "lucky-buckets-wave", + "mean-panthers-serve", + "mighty-rings-share", + "neat-zoos-reflect", + "nice-ears-shop", + "ninety-geckos-build", + "ninety-ligers-tap", + "ninety-meals-hug", + "old-ants-fix", + "old-nails-hammer", + "pink-mangos-divide", + "polite-laws-reply", + "poor-parents-cover", + "pretty-clocks-guess", + "rare-toys-peel", + "rich-pianos-walk", + "rotten-shirts-fail", + "rude-falcons-dream", + "serious-years-jam", + "seven-candles-smile", + "short-jokes-sleep", + "shy-nails-ring", + "small-apes-train", + "smooth-bulldogs-type", + "smooth-jobs-attack", + "spicy-pears-work", + "spotty-sheep-mix", + "stale-teachers-hug", + "strong-tools-draw", + "stupid-deers-call", + "stupid-mangos-explode", + "sweet-toes-fly", + "tall-falcons-explode", + "ten-numbers-lay", + "tender-tips-breathe", + "thick-scissors-admire", + "thirty-cows-exercise", + "tidy-months-brake", + "tough-grapes-agree", + "tricky-snakes-appear", + "two-keys-pump", + "unlucky-cameras-draw", + "wet-sloths-taste", + "wise-phones-eat", + "witty-glasses-hear", + "young-cameras-grin" + ] +} diff --git a/.changeset/pretty-clocks-guess.md b/.changeset/pretty-clocks-guess.md new file mode 100644 index 000000000..889069696 --- /dev/null +++ b/.changeset/pretty-clocks-guess.md @@ -0,0 +1,26 @@ +--- +'style-dictionary': major +--- + +BREAKING: All of our hooks, parsers, preprocessors, transforms, formats, actions, fileHeaders and filters, support async functions as well now. This means that the formatHelpers -> fileHeader helper method is now asynchronous, to support async fileheader functions. + +```js +import StyleDictionary from 'style-dictionary'; + +const { fileHeader } = StyleDictionary.formatHelpers; + +StyleDictionary.registerFormat({ + name: 'custom/css', + // this can be async now, usually it is if you use fileHeader format helper, since that now always returns a Promise + formatter: async function ({ dictionary, file, options }) { + const { outputReferences } = options; + return ( + // this helper is now async! because the user-passed file.fileHeader might be an async function + (await fileHeader({ file })) + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, +}); +``` diff --git a/.changeset/rare-toys-peel.md b/.changeset/rare-toys-peel.md new file mode 100644 index 000000000..4c10089d0 --- /dev/null +++ b/.changeset/rare-toys-peel.md @@ -0,0 +1,11 @@ +--- +'style-dictionary': minor +--- + +Add a couple of utilities for converting a regular Style Dictionary tokens object/file(s) to DTCG formatted tokens: + +- `convertToDTCG` +- `convertJSONToDTCG` +- `convertZIPToDTCG` + +[Documentation of these utilities](https://v4.styledictionary.com/reference/utils/dtcg/) \ No newline at end of file diff --git a/.changeset/rich-pianos-walk.md b/.changeset/rich-pianos-walk.md new file mode 100644 index 000000000..09d4a97a4 --- /dev/null +++ b/.changeset/rich-pianos-walk.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Support Design Token Community Group Draft specification for Design Tokens, by adding support for $value, $type and $description properties. diff --git a/.changeset/rotten-shirts-fail.md b/.changeset/rotten-shirts-fail.md new file mode 100644 index 000000000..4be877a7b --- /dev/null +++ b/.changeset/rotten-shirts-fail.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Only run postinstall scripts when NODE_ENV isn't production (e.g. npm install --production or --omit=dev). To avoid errors running husky/patch-package. diff --git a/.changeset/rude-falcons-dream.md b/.changeset/rude-falcons-dream.md new file mode 100644 index 000000000..e5ae52e1a --- /dev/null +++ b/.changeset/rude-falcons-dream.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Colors that are not recognized by tinycolor2 as valid color formats (e.g. `linear-gradient(...)`) are now ignored by the builtin color transforms filter functions. diff --git a/.changeset/serious-years-jam.md b/.changeset/serious-years-jam.md new file mode 100644 index 000000000..02ad8f135 --- /dev/null +++ b/.changeset/serious-years-jam.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Pass options to all of the filter functions in our built-in transforms, to check for `usesDTCG` and `$type` property. diff --git a/.changeset/seven-candles-smile.md b/.changeset/seven-candles-smile.md new file mode 100644 index 000000000..26d783d30 --- /dev/null +++ b/.changeset/seven-candles-smile.md @@ -0,0 +1,67 @@ +--- +'style-dictionary': major +--- + +BREAKING: Formats, when registered, are put inside the `hooks.formats` property now, as opposed to `format`. +The `formatter` handler function has been renamed to `format` for consistency. + +The importable type interfaces have also been renamed, `Formatter` is now `FormatFn` and `FormatterArguments` is now `FormatFnArguments`. +Note that you can also use `Format['format']` instead of `FormatFn`, or `Parameters` instead of `FormatFnArguments`, so these renames may not matter. + +Before: + +```ts +import StyleDictionary from 'style-dictionary'; +import type { Formatter, FormatterArguments } from 'style-dictionary/types'; + +// register it with register method +StyleDictionary.registerFormat({ + name: 'custom/json', + formatter: ({ dictionary }) => JSON.stringify(dictionary, null, 2), +}) + +export default { + // OR define it inline + format: { + 'custom/json': ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }, + platforms: { + json: { + files: [{ + destination: 'output.json', + format: 'custom/json' + }], + }, + }, +}; +``` + +After: + +```ts +import StyleDictionary from 'style-dictionary'; +import type { FormatFn, FormatFnArguments } from 'style-dictionary/types'; + +// register it with register method +StyleDictionary.registerFormat({ + name: 'custom/json', + format: ({ dictionary }) => JSON.stringify(dictionary, null, 2), +}) + +export default { + // OR define it inline + hooks: { + formats: { + 'custom/json': ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }, + }, + platforms: { + json: { + files: [{ + destination: 'output.json', + format: 'custom/json' + }], + }, + }, +}; +``` \ No newline at end of file diff --git a/.changeset/short-jokes-sleep.md b/.changeset/short-jokes-sleep.md new file mode 100644 index 000000000..ed2c79243 --- /dev/null +++ b/.changeset/short-jokes-sleep.md @@ -0,0 +1,46 @@ +--- +'style-dictionary': major +--- + +BREAKING: preprocessors must now also be explicitly applied on global or platform level, rather than only registering it. This is more consistent with how the other hooks work and allows applying it on a platform level rather than only on the global level. + +`preprocessors` property that contains the registered preprocessors has been moved under a wrapping property called `hooks`. + +Before: + +```js +export default { + // register it inline or by SD.registerPreprocessor + // applies automatically, globally + preprocessors: { + foo: (dictionary) => { + // preprocess it + return dictionary; + } + } +} +``` + +After: + +```js +export default { + // register it inline or by SD.registerPreprocessor + hooks: { + preprocessors: { + foo: (dictionary) => { + // preprocess it + return dictionary; + } + } + }, + // apply it globally + preprocessors: ['foo'], + platforms: { + css: { + // or apply is per platform + preprocessors: ['foo'] + } + } +} +``` diff --git a/.changeset/shy-nails-ring.md b/.changeset/shy-nails-ring.md new file mode 100644 index 000000000..d006fd494 --- /dev/null +++ b/.changeset/shy-nails-ring.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +fix(types): Added missing type exports diff --git a/.changeset/small-apes-train.md b/.changeset/small-apes-train.md new file mode 100644 index 000000000..3ab9c9465 --- /dev/null +++ b/.changeset/small-apes-train.md @@ -0,0 +1,51 @@ +--- +'style-dictionary': minor +--- + +Allow passing a custom FileSystem Volume to your Style Dictionary instances, to ensure input/output files are read/written from/to that specific volume. +Useful in case you want multiple Style Dictionary instances that are isolated from one another in terms of inputs/outputs. + +```js +import { Volume } from 'memfs'; +// You will need a bundler for memfs in browser... +// Or use as a prebundled fork: +import memfs from '@bundled-es-modules/memfs'; +const { Volume } = memfs; + +const vol = new Volume(); + +const sd = new StyleDictionary({ + tokens: { + colors: { + red: { + value: "#FF0000", + type: "color" + } + } + }, + platforms: { + css: { + transformGroup: "css", + files: [{ + destination: "variables.css", + format: "css/variables" + }] + } + } +}, { volume: vol }); + +await sd.buildAllPlatforms(); + +vol.readFileSync('/variables.css'); +/** + * :root { + * --colors-red: #FF0000; + * } + */ +``` + +This also works when using extend: + +```js +const extendedSd = await sd.extend(cfg, { volume: vol }) +``` diff --git a/.changeset/smooth-bulldogs-type.md b/.changeset/smooth-bulldogs-type.md new file mode 100644 index 000000000..3b82a0eb4 --- /dev/null +++ b/.changeset/smooth-bulldogs-type.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix Windows support by using a Linux/Windows + Node/Browser compatible path utility. Upgrade to latest Glob version. Apply posix: true to prevent breaking change glob update. diff --git a/.changeset/smooth-jobs-attack.md b/.changeset/smooth-jobs-attack.md new file mode 100644 index 000000000..0c3dcebd9 --- /dev/null +++ b/.changeset/smooth-jobs-attack.md @@ -0,0 +1,31 @@ +--- +'style-dictionary': major +--- + +BREAKING: `className`, `packageName`, `mapName`, `type`, `name`, `resourceType` and `resourceMap` options for a bunch of built-in formats have been moved from `file` to go inside the `file.options` object, for API consistency reasons. + +Before: + +```json +{ + "files": [{ + "destination": "tokenmap.scss", + "format": "scss/map-deep", + "mapName": "tokens" + }] +} +``` + +After: + +```json +{ + "files": [{ + "destination": "tokenmap.scss", + "format": "scss/map-deep", + "options": { + "mapName": "tokens" + } + }] +} +``` diff --git a/.changeset/spicy-pears-work.md b/.changeset/spicy-pears-work.md new file mode 100644 index 000000000..875987e2d --- /dev/null +++ b/.changeset/spicy-pears-work.md @@ -0,0 +1,50 @@ +--- +'style-dictionary': major +--- + +BREAKING: Transforms, when registered, are put inside the `hooks.transforms` property now, as opposed to `transform`. +The `matcher` property has been renamed to `filter` (to align with the Filter hook change), and the `transformer` handler function has been renamed to `transform` for consistency. + +Before: + +```js +export default { + // register it inline or by SD.registerTransform + transform: { + 'color-transform': { + type: 'value', + matcher: (token) => token.type === 'color', + transformer: (token) => token.value, + }, + }, + platforms: { + css: { + // apply it per platform + transforms: ['color-transform'], + }, + }, +}; +``` + +After + +```js +export default { + // register it inline or by SD.registerTransform + hooks: { + transforms: { + 'color-transform': { + type: 'value', + filter: (token) => token.type === 'color', + transform: (token) => token.value, + }, + }, + }, + platforms: { + css: { + // apply it per platform + transforms: ['color-transform'], + }, + }, +}; +``` diff --git a/.changeset/spotty-sheep-mix.md b/.changeset/spotty-sheep-mix.md new file mode 100644 index 000000000..4e5575e32 --- /dev/null +++ b/.changeset/spotty-sheep-mix.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Pass the original ref path to the `getReferences` util result tokens. diff --git a/.changeset/stale-teachers-hug.md b/.changeset/stale-teachers-hug.md new file mode 100644 index 000000000..5f54e7efb --- /dev/null +++ b/.changeset/stale-teachers-hug.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix issue in browser-bundled glob, bump. diff --git a/.changeset/strong-tools-draw.md b/.changeset/strong-tools-draw.md new file mode 100644 index 000000000..554080fad --- /dev/null +++ b/.changeset/strong-tools-draw.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Handle transition timingFunction prop in cubicBezier/css transform. Handle typography fontFamily prop in fontFamily/css transform. diff --git a/.changeset/stupid-deers-call.md b/.changeset/stupid-deers-call.md new file mode 100644 index 000000000..79e4d0733 --- /dev/null +++ b/.changeset/stupid-deers-call.md @@ -0,0 +1,65 @@ +--- +'style-dictionary': major +--- + +BREAKING: Allow specifying a `function` for `outputReferences`, conditionally outputting a ref or not per token. Also exposes `outputReferencesFilter` utility function which will determine whether a token should be outputting refs based on whether those referenced tokens were filtered out or not. + +If you are maintaining a custom format that allows `outputReferences` option, you'll need to take into account that it can be a function, and pass the correct options to it. + +Before: + +```js +StyleDictionary.registerFormat({ + name: 'custom/es6', + formatter: async (dictionary) => { + const { allTokens, options, file } = dictionary; + const { usesDtcg } = options; + + const compileTokenValue = (token) => { + let value = usesDtcg ? token.$value : token.value; + const originalValue = usesDtcg ? token.original.$value : token.original.value; + + // Look here 👇 + const shouldOutputRefs = outputReferences && usesReferences(originalValue); + + if (shouldOutputRefs) { + // ... your code for putting back the reference in the output + value = ... + } + return value; + } + return `${allTokens.reduce((acc, token) => `${acc}export const ${token.name} = ${compileTokenValue(token)};\n`, '')}`; + }, +}); +``` + +After + +```js +StyleDictionary.registerFormat({ + name: 'custom/es6', + formatter: async (dictionary) => { + const { allTokens, options, file } = dictionary; + const { usesDtcg } = options; + + const compileTokenValue = (token) => { + let value = usesDtcg ? token.$value : token.value; + const originalValue = usesDtcg ? token.original.$value : token.original.value; + + // Look here 👇 + const shouldOutputRefs = + usesReferences(original) && + (typeof options.outputReferences === 'function' + ? outputReferences(token, { dictionary, usesDtcg }) + : options.outputReferences); + + if (shouldOutputRefs) { + // ... your code for putting back the reference in the output + value = ... + } + return value; + } + return `${allTokens.reduce((acc, token) => `${acc}export const ${token.name} = ${compileTokenValue(token)};\n`, '')}`; + }, +}); +``` diff --git a/.changeset/stupid-mangos-explode.md b/.changeset/stupid-mangos-explode.md new file mode 100644 index 000000000..3002bca6a --- /dev/null +++ b/.changeset/stupid-mangos-explode.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Pass dictionary options to preprocessor functions. diff --git a/.changeset/sweet-toes-fly.md b/.changeset/sweet-toes-fly.md new file mode 100644 index 000000000..db454cf5f --- /dev/null +++ b/.changeset/sweet-toes-fly.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': major +--- + +BREAKING: expose getReferences and usesReference utilities as standalone utils rather than requiring them to be bound to dictionary object. This makes it easier to use. diff --git a/.changeset/tall-falcons-explode.md b/.changeset/tall-falcons-explode.md new file mode 100644 index 000000000..f950364ed --- /dev/null +++ b/.changeset/tall-falcons-explode.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Publish the postinstall-dev script to NPM. diff --git a/.changeset/ten-numbers-lay.md b/.changeset/ten-numbers-lay.md new file mode 100644 index 000000000..c09817320 --- /dev/null +++ b/.changeset/ten-numbers-lay.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Add unfilteredAllTokens property in dictionary object for formats, which is an unfiltered version of allTokens property, or a flattened version of the unfilteredTokens property. diff --git a/.changeset/tender-tips-breathe.md b/.changeset/tender-tips-breathe.md new file mode 100644 index 000000000..5b0205662 --- /dev/null +++ b/.changeset/tender-tips-breathe.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': major +--- + +BREAKING: no longer wraps tokens of type asset in double quotes. Rather, we added a transform `asset/url` that will wrap such tokens inside `url("")` statements, this transform is applied to transformGroups scss, css and less. diff --git a/.changeset/thick-scissors-admire.md b/.changeset/thick-scissors-admire.md new file mode 100644 index 000000000..19281042a --- /dev/null +++ b/.changeset/thick-scissors-admire.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Allow expanding tokens on a global or platform-specific level. Supports conditionally expanding per token type, or using a function to determine this per individual token. diff --git a/.changeset/thirty-cows-exercise.md b/.changeset/thirty-cows-exercise.md new file mode 100644 index 000000000..4b20fd51c --- /dev/null +++ b/.changeset/thirty-cows-exercise.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Token merging behavior changed so that upon token collisions, metadata props aren't accidentally merged together. diff --git a/.changeset/tidy-months-brake.md b/.changeset/tidy-months-brake.md new file mode 100644 index 000000000..168523e81 --- /dev/null +++ b/.changeset/tidy-months-brake.md @@ -0,0 +1,8 @@ +--- +'style-dictionary': minor +--- + +Create `formatPlatform` and `formatAllPlatforms` methods. +This will return the outputs and destinations from the format hook for your dictionary, without building these outputs and persisting them to the filesystem. +Additionally, formats can now return any data type instead of requiring it to be a `string` and `destination` property in `files` is now optional. +This allows users to create formats intended for only formatting tokens and letting users do stuff with it during runtime rather than writing to files. diff --git a/.changeset/tough-grapes-agree.md b/.changeset/tough-grapes-agree.md new file mode 100644 index 000000000..914217363 --- /dev/null +++ b/.changeset/tough-grapes-agree.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +fix(types): add missing type keyword for type export from index.d.ts diff --git a/.changeset/tricky-snakes-appear.md b/.changeset/tricky-snakes-appear.md new file mode 100644 index 000000000..eb87e69a6 --- /dev/null +++ b/.changeset/tricky-snakes-appear.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix scenario of passing absolute paths in Node env, do not remove leading slash in absolute paths. diff --git a/.changeset/two-keys-pump.md b/.changeset/two-keys-pump.md new file mode 100644 index 000000000..52359f57c --- /dev/null +++ b/.changeset/two-keys-pump.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix a couple of type imports issues in .d.ts files diff --git a/.changeset/unlucky-cameras-draw.md b/.changeset/unlucky-cameras-draw.md new file mode 100644 index 000000000..a26cf1bb2 --- /dev/null +++ b/.changeset/unlucky-cameras-draw.md @@ -0,0 +1,67 @@ +--- +'style-dictionary': major +--- + +BREAKING: StyleDictionary to be initialized with a new API and have async methods. Use: + +```js +import StyleDictionary from 'style-dictionary'; + +/** + * old: + * const sd = StyleDictionary.extend({ source: ['tokens.json'], platforms: {} }); + * sd.buildAllPlatforms(); + */ +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +await sd.buildAllPlatforms(); +``` + +You can still extend a dictionary instance with an extended config, but `.extend()` is only used for this, it is no longer used to initialize the first instance: + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +const extended = await sd.extend({ + fileHeader: { + myFileHeader: (defaultMessage) => { + return [...defaultMessage, 'hello, world!']; + } + } +}); +``` + +To ensure your initialized StyleDictionary instance is fully ready and has imported all your tokens, you can await `hasInitialized`: + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +await sd.hasInitialized; +console.log(sd.allTokens); +``` + +For error handling and testing purposes, you can also manually initialize the style-dictionary config: + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.js'], platforms: {} }, { init: false }); +try { + await sd.init(); +} catch(e) { + // handle error, e.g. when tokens.js file has syntax errors and cannot be imported +} +console.log(sd.allTokens); +``` + +The main reason for an initialize step after class instantiation is that async constructors are not a thing in JavaScript, and if you return a promise from a constructor to "hack it", TypeScript will eventually trip over it. + +Due to being able to dynamically (asynchronously) import ES Modules rather than synchronously require CommonJS modules, we had to make the APIs asynchronous, so the following methods are now async: + +- extend +- exportPlatform +- buildAllPlatforms & buildPlatform +- cleanAllPlatforms & cleanPlatform + +In a future release, most other methods will be made async or support async as well, such as parsers, transforms, formats etc. diff --git a/.changeset/wet-sloths-taste.md b/.changeset/wet-sloths-taste.md new file mode 100644 index 000000000..765ea5353 --- /dev/null +++ b/.changeset/wet-sloths-taste.md @@ -0,0 +1,41 @@ +--- +'style-dictionary': major +--- + +BREAKING: Parsers, when registered, are put inside the `hooks.parsers` property now, as opposed to `parsers`. +`parsers` property has been repurposed: you will now also need to explicitly apply registered parsers by name in the `parsers` property, they no longer apply by default. +When registering a parser, you must also supply a `name` property just like with all other hooks, and the `parse` function has been renamed to `parser` for consistency. + +Before: + +```js +export default { + // register it inline or by SD.registerPreprocessor + parsers: [ + { + pattern: /\.json5$/, + parse: ({ contents, filePath}) => { + return JSON5.parse(contents); + }, + } + ], +}; +``` + +After: + +```js +export default { + hooks: { + parsers: { + name: 'json5-parser', + pattern: /\.json5$/, + parser: ({ contents, filePath}) => { + return JSON5.parse(contents); + }, + } + }, + // apply it globally by name reference + parsers: ['json5-parser'], +}; +``` diff --git a/.changeset/wise-phones-eat.md b/.changeset/wise-phones-eat.md new file mode 100644 index 000000000..ea30cff59 --- /dev/null +++ b/.changeset/wise-phones-eat.md @@ -0,0 +1,44 @@ +--- +'style-dictionary': major +--- + +Remove reliance on CTI token structure across transforms, actions and formats. + +Breaking changes: + +- Token type will now be determined by "type" (or "$type") property on the token, rather than by checking its CTI attributes. This change has been reflected in all of the format templates as well as transform "matcher" functions that were previously checking `attributes.category` as the token type indicator. +- Types are mostly aligned with [DTCG spec types](https://design-tokens.github.io/community-group/format/#types), although a few additional ones have been added for compatibility reasons: + - asset -> string type tokens where the value is a filepath to an asset + - icon -> content type string tokens where the content resembles an icon, e.g. for icon fonts like [Microsoft codicons](https://github.com/microsoft/vscode-codicons) + - html -> HTML entity strings for unicode characters + - content -> regular string content e.g. text content which sometimes needs to be wrapped in quotes +- Built-in name transforms are now reliant only on the token path, and are renamed from `name/cti/casing` to just `name/casing`. `name/ti/camel` and `name/ti/constant` have been removed. For example `name/cti/kebab` transform is now `name/kebab`. +- Transform `content/icon` has been renamed to `html/icon` since it targets HTML entity strings, not just any icon content. +- `font/objC/literal`, `font/swift/literal` and `font/flutter/literal` have been removed in favor of `font/objC/literal`, `font/swift/literal` and `font/flutter/literal`, as they do he exact same transformations. +- `typescript/module-declarations` format to be updated with current DesignToken type interface. + + +Before: + +```json +{ + "color": { + "red": { + "value": "#FF0000" + } + } +} +``` + +After: + +```json +{ + "color": { // <-- this no longer needs to be "color" in order for the tokens inside this group to be considered of type "color" + "red": { + "value": "#FF0000", + "type": "color" + } + } +} +``` \ No newline at end of file diff --git a/.changeset/witty-glasses-hear.md b/.changeset/witty-glasses-hear.md new file mode 100644 index 000000000..835b3cc26 --- /dev/null +++ b/.changeset/witty-glasses-hear.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow border type tokens to be empty, every property is optional. diff --git a/.changeset/young-cameras-grin.md b/.changeset/young-cameras-grin.md new file mode 100644 index 000000000..7e1b75cd1 --- /dev/null +++ b/.changeset/young-cameras-grin.md @@ -0,0 +1,33 @@ +--- +'style-dictionary': major +--- + +BREAKING: For formats using the `fileHeader` `formatHelpers` utility, it will no longer display a timestamp in the fileHeader output by default. This is now an opt-in by setting `file.formatting.fileHeaderTimestamp` to `true`. The reason for making this opt-in now is that using Style Dictionary in the context of a CI (continuous integration) pipeline is a common use-case, and when running on pull request event, output files always show a diff in git due to the timestamp changing, which often just means that the diff is bloated by redundancy. + +New: + +```json +{ + "platforms": { + "css": { + "files": [{ + "destination": "variables.css", + "format": "css/variables", + "options": { + "formatting": { + "fileHeaderTimestamp": true + } + } + }] + } + } +} +``` + +or: + +```js +import { fileHeader } from 'style-dictionary/utils'; + +const headerContent = await fileHeader({ formatting: { fileHeaderTimestamp: true } }); +``` diff --git a/.eslintrc.json b/.eslintrc.json index a32eb0a2e..a5cb810b1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,27 +1,29 @@ { + "ignorePatterns": ["/docs/dist/**/*"], "parserOptions": { - "ecmaVersion": 6 + "ecmaVersion": "latest", + "sourceType": "module" }, - "plugins": ["jest"], "env": { "node": true, "mocha": true, - "jest": true + "es6": true, + "browser": true }, - "globals": { - "Buffer": true, - "escape": true - }, - "extends": [ - "eslint:recommended", - "plugin:jest/recommended" - ], + "extends": ["eslint:recommended"], + "plugins": ["mocha"], "rules": { - "no-console": 0, "no-unused-vars": 1, - "no-control-regex": 0, - "comma-dangle": 0, - "no-prototype-builtins": 0, - "jest/valid-title": 0 - } + "no-console": ["error", { "allow": ["warn", "error"] }], + "mocha/no-exclusive-tests": "error", + "no-var": "error" + }, + "overrides": [ + { + "files": ["examples/**/*.js"], + "rules": { + "no-console": 0 + } + } + ] } diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ab40d21d7..3bfff5933 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,5 @@ -*Issue #, if available:* - -*Description of changes:* +_Issue #, if available:_ +_Description of changes:_ By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..f7a7b5b2d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,33 @@ +name: Release + +on: + push: + branches: + - v4 + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + # use lts, bump this if new major becomes lts + node-version: 20.x + registry-url: 'https://registry.npmjs.org' + + - name: Install Dependencies + run: npm ci + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@v1 + with: + # This expects you to have a script called release which does a build for your packages and calls changeset publish + publish: npm run release + commit: 'chore: release' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 612e0c2ae..000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Test - -on: - pull_request: - branches: [ "main" ] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [12.x, 14.x, 16.x] - - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - run: npm ci - - run: npm run build --if-present - - run: npm test diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 000000000..2149c7054 --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,41 @@ +name: Verify changes + +on: pull_request + +jobs: + verify: + name: Verify changes + strategy: + matrix: + # latest node & minimum node according to pkg.json engines + node-version: [18.0, 21.x] + os: [ubuntu-latest, windows-latest] + runs-on: ${{matrix.os}} + steps: + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - uses: actions/checkout@v4 + + - name: Setup Node ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install Dependencies + run: npm ci + + - name: Linting & Formatting + run: npm run lint + + - name: Node tests + run: npm run test:node + + - name: Install chromium + run: npx playwright install --with-deps chromium + + - name: Browser tests + run: npm run test diff --git a/.gitignore b/.gitignore index 39f67a4d0..51a3d5eec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Logs -logs +/logs *.log npm-debug.log* @@ -8,11 +8,8 @@ pids *.pid *.seed -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - # Coverage directory used by tools like istanbul -coverage +/coverage # nyc test coverage .nyc_output @@ -24,7 +21,7 @@ coverage .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release +/build/Release # Dependency directories node_modules @@ -40,16 +37,16 @@ yarn.lock .node_repl_history # Native Builds -build/ +/build/ # Android Specific Files .gradle/ local.properties -gen/ -out/ +/gen/ +/out/ *.class .navigation/ -captures/ +/captures/ *.apk *.ap_ *.iml @@ -57,7 +54,7 @@ captures/ *.jks # IOS Specific Files -DerivedData/ +/DerivedData/ *.pbxuser !default.pbxuser *.mode1v3 @@ -77,5 +74,13 @@ xcuserdata/ # Mac directory hidden files *.DS_Store -# Temporary build output directory for unit tests -__tests__/__output +# Temporary build output directory for tests +/__tests__/__output +/__integration__/build + +# build output +/docs/dist/ +# generated types +.astro/ + +dist diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 000000000..e4ce4a513 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit index 449fcdee1..36af21989 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -npm test +npx lint-staged diff --git a/.jsdoc.json b/.jsdoc.json index c245201b0..ee095d5f4 100644 --- a/.jsdoc.json +++ b/.jsdoc.json @@ -1,3 +1,3 @@ { - "plugins": ["./node_modules/jsdoc-escape-at"] + "plugins": ["./node_modules/jsdoc-escape-at", "./node_modules/jsdoc-tsimport-plugin/index.js"] } diff --git a/.npmignore b/.npmignore index 70895556b..6d4977120 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,4 @@ .eslintrc.json .editorconfig images/ -test/ +__tests__/ diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..d0fb38c52 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +.changeset/ +**/*.snap.js +/docs/dist diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c2bbeb70..36e3fca85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,362 +1,1445 @@ # Changelog -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## 4.0.0-prerelease.37 -## [3.8.0](https://github.com/amzn/style-dictionary/compare/v3.7.2...v3.8.0) (2023-04-25) +### Minor Changes +- 8450a45: Some fixes for Expand utility: -### Features + - Array values such as `dashArray` property of `strokeStyle` tokens no longer get expanded unintentionally, `typeof 'object'` check changed to `isPlainObject` check. + - Nested object-value tokens (such as `style` property inside `border` tokens) will now also be expanded. + - When references are involved during expansion, the resolved value is used when the property is an object, if not, then we keep the reference as is. + This is because if the reference is to an object value, the expansion might break the reference. + +## 4.0.0-prerelease.36 + +### Minor Changes + +- 39f0220: Allow not throwing fatal errors on broken token references/aliases, but `console.error` instead. + + You can also configure this on global/platform `log` property: + + ```json + { + "log": { + "errors": { + "brokenReferences": "console" + } + } + } + ``` + + This setting defaults to `"error"` when not configured. + + `resolveReferences` and `getReferences` `warnImmediately` option is set to `true` which causes an error to be thrown/warned immediately by default, which can be configured to `false` if you know those utils are running in the transform/format hooks respectively, where the errors are collected and grouped, then thrown as 1 error/warning instead of multiple. + + Some minor grammatical improvements to some of the error logs were also done. + +## 4.0.0-prerelease.35 + +### Minor Changes + +- c06661d: Re-add and update example basic, fix copySync command in CLI, fix android templates to use $type for DTCG tokens. + +## 4.0.0-prerelease.34 + +### Patch Changes + +- ba03ee9: Fix for expand utility on platform level to adjust the token's path property. + +## 4.0.0-prerelease.33 + +### Minor Changes + +- 261a2cb: Handle transition timingFunction prop in cubicBezier/css transform. Handle typography fontFamily prop in fontFamily/css transform. + +### Patch Changes + +- 261a2cb: Allow border type tokens to be empty, every property is optional. + +## 4.0.0-prerelease.32 + +### Minor Changes + +- af5cc94: Create `formatPlatform` and `formatAllPlatforms` methods. + This will return the outputs and destinations from the format hook for your dictionary, without building these outputs and persisting them to the filesystem. + Additionally, formats can now return any data type instead of requiring it to be a `string` and `destination` property in `files` is now optional. + This allows users to create formats intended for only formatting tokens and letting users do stuff with it during runtime rather than writing to files. + +### Patch Changes + +- 2335f13: Allow using registerHook methods to override hooks that are already registered with the same name. +- 6e226aa: Pass the original ref path to the `getReferences` util result tokens. +- 3f09277: Pass dictionary options to preprocessor functions. + +## 4.0.0-prerelease.31 + +### Patch Changes + +- c708325: Moving the @zip.js/zip.js dependency from a devDependency to a normal dependency. + +## 4.0.0-prerelease.30 + +### Minor Changes + +- 7418c97: Add a couple of utilities for converting a regular Style Dictionary tokens object/file(s) to DTCG formatted tokens: + + - `convertToDTCG` + - `convertJSONToDTCG` + - `convertZIPToDTCG` + + [Documentation of these utilities](https://v4.styledictionary.com/reference/utils/dtcg/) + +## 4.0.0-prerelease.29 + +### Minor Changes + +- cb94554: 'size/rem' transform to not transform tokens that already have a unit, such as `"4px"`, this should not be transformed to `"4rem"`. + +### Patch Changes + +- cb94554: Fix typeDtcgDelegate util $type property position to be allowed anywhere in the object, not just at the top. +- 0972b26: Pass SD options to fileheaders and filters, to make it easier to use and adjust according to config or options like usesDTCG. +- 4ec34fd: Pass options to all of the filter functions in our built-in transforms, to check for `usesDTCG` and `$type` property. +- 0972b26: Add unfilteredAllTokens property in dictionary object for formats, which is an unfiltered version of allTokens property, or a flattened version of the unfilteredTokens property. + +## 4.0.0-prerelease.28 + +### Minor Changes + +- 4225d78: Added the following transforms for CSS, and added them to the `scss`, `css` and `less` transformGroups: + + - `fontFamily/css` -> wraps font names with spaces in `'` quotes + - `cubicBezier/css` -> array value, put inside `cubic-bezier()` CSS function + - `strokeStyle/css/shorthand` -> object value, transform to CSS shorthand + - `border/css/shorthand` -> object value, transform to CSS shorthand + - `typography/css/shorthand` -> object value, transform to CSS shorthand + - `transition/css/shorthand` -> object value, transform to CSS shorthand + - `shadow/css/shorthand` -> object value (or array of objects), transform to CSS shorthand + + The main intention here is to ensure that Style Dictionary is compliant with [DTCG draft specification](https://design-tokens.github.io/community-group/format/) out of the box with regards to exporting to CSS, where object-value tokens are not supported without transforming them to shorthands (or expanding them, which is a different feature that was added in `4.0.0-prerelease.27`). + +### Patch Changes + +- a5bafac: Colors that are not recognized by tinycolor2 as valid color formats (e.g. `linear-gradient(...)`) are now ignored by the builtin color transforms filter functions. + +## 4.0.0-prerelease.27 + +### Major Changes + +- f2ed88b: BREAKING: File headers, when registered, are put inside the `hooks.fileHeaders` property now, as opposed to `fileHeader`. + Note the change from singular to plural form here. + + Before: + + ```js + export default { + fileHeader: { + foo: (defaultMessages = []) => ['Ola, planet!', ...defaultMessages, 'Hello, World!'], + }, + }; + ``` + + After: + + ```js + export default { + hooks: { + fileHeaders: { + foo: (defaultMessages = []) => ['Ola, planet!', ...defaultMessages, 'Hello, World!'], + }, + }, + }; + ``` + +- f2ed88b: BREAKING: Actions, when registered, are put inside the `hooks.actions` property now, as opposed to `action`. + Note the change from singular to plural form here. + + Before: + + ```js + export default { + action: { + 'copy-assets': { + do: () => {} + undo: () => {} + } + }, + }; + ``` + + After: + + ```js + export default { + hooks: { + actions: { + 'copy-assets': { + do: () => {} + undo: () => {} + } + }, + }, + }; + ``` + +- f2ed88b: Filters, when registered, are put inside the `hooks.filters` property now, as opposed to `filter`. + Note the change from singular to plural form here. + + Before: + + ```js + export default { + filter: { + 'colors-only': (token) => token.type === 'color, + }, + platforms: { + css: { + files: [{ + format: 'css/variables', + destination: '_variables.css', + filter: 'colors-only', + }], + }, + }, + }; + ``` + + After: + + ```js + export default { + hooks: { + filters: { + 'colors-only': (token) => token.type === 'color, + }, + }, + platforms: { + css: { + files: [{ + format: 'css/variables', + destination: '_variables.css', + filter: 'colors-only', + }], + }, + }, + }; + ``` + + In addition, when using [`registerFilter`](/reference/api#registerfilter) method, the name of the filter function is now `filter` instead of `matcher`. + + Before: + + ```js title="build-tokens.js" del={5} ins={6} + import StyleDictionary from 'style-dictionary'; + + StyleDictionary.registerFilter({ + name: 'colors-only', + matcher: (token) => token.type === 'color', + }); + ``` + + After: + + ```js title="build-tokens.js" del={5} ins={6} + import StyleDictionary from 'style-dictionary'; + + StyleDictionary.registerFilter({ + name: 'colors-only', + filter: (token) => token.type === 'color', + }); + ``` + + > These changes also apply for the `filter` function (previously `matcher`) inside `transforms`. + +- f2ed88b: BREAKING: Transform groups, when registered, are put inside the `hooks.transformGroups` property now, as opposed to `transformGroup`. + + Before: + + ```js + export default { + // register it inline or by SD.registerTransformGroup + transformGroup: { + foo: ['foo-transform'], + }, + }; + ``` + + After: + + ```js + export default { + hooks: { + transformGroups: { + foo: ['foo-transform'], + }, + }, + }; + ``` + +- f2ed88b: BREAKING: Formats, when registered, are put inside the `hooks.formats` property now, as opposed to `format`. + The `formatter` handler function has been renamed to `format` for consistency. + + The importable type interfaces have also been renamed, `Formatter` is now `FormatFn` and `FormatterArguments` is now `FormatFnArguments`. + Note that you can also use `Format['format']` instead of `FormatFn`, or `Parameters` instead of `FormatFnArguments`, so these renames may not matter. + + Before: + + ```ts + import StyleDictionary from 'style-dictionary'; + import type { Formatter, FormatterArguments } from 'style-dictionary/types'; + + // register it with register method + StyleDictionary.registerFormat({ + name: 'custom/json', + formatter: ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }); + + export default { + // OR define it inline + format: { + 'custom/json': ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }, + platforms: { + json: { + files: [ + { + destination: 'output.json', + format: 'custom/json', + }, + ], + }, + }, + }; + ``` + + After: + + ```ts + import StyleDictionary from 'style-dictionary'; + import type { FormatFn, FormatFnArguments } from 'style-dictionary/types'; + + // register it with register method + StyleDictionary.registerFormat({ + name: 'custom/json', + format: ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }); + + export default { + // OR define it inline + hooks: { + formats: { + 'custom/json': ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }, + }, + platforms: { + json: { + files: [ + { + destination: 'output.json', + format: 'custom/json', + }, + ], + }, + }, + }; + ``` + +- e83886c: BREAKING: preprocessors must now also be explicitly applied on global or platform level, rather than only registering it. This is more consistent with how the other hooks work and allows applying it on a platform level rather than only on the global level. + + `preprocessors` property that contains the registered preprocessors has been moved under a wrapping property called `hooks`. + + Before: + + ```js + export default { + // register it inline or by SD.registerPreprocessor + // applies automatically, globally + preprocessors: { + foo: (dictionary) => { + // preprocess it + return dictionary; + }, + }, + }; + ``` + + After: + + ```js + export default { + // register it inline or by SD.registerPreprocessor + hooks: { + preprocessors: { + foo: (dictionary) => { + // preprocess it + return dictionary; + }, + }, + }, + // apply it globally + preprocessors: ['foo'], + platforms: { + css: { + // or apply is per platform + preprocessors: ['foo'], + }, + }, + }; + ``` + +- 2f80da2: BREAKING: `className`, `packageName`, `mapName`, `type`, `name`, `resourceType` and `resourceMap` options for a bunch of built-in formats have been moved from `file` to go inside the `file.options` object, for API consistency reasons. + + Before: + + ```json + { + "files": [ + { + "destination": "tokenmap.scss", + "format": "scss/map-deep", + "mapName": "tokens" + } + ] + } + ``` + + After: + + ```json + { + "files": [ + { + "destination": "tokenmap.scss", + "format": "scss/map-deep", + "options": { + "mapName": "tokens" + } + } + ] + } + ``` + +- f2ed88b: BREAKING: Transforms, when registered, are put inside the `hooks.transforms` property now, as opposed to `transform`. + The `matcher` property has been renamed to `filter` (to align with the Filter hook change), and the `transformer` handler function has been renamed to `transform` for consistency. + + Before: + + ```js + export default { + // register it inline or by SD.registerTransform + transform: { + 'color-transform': { + type: 'value', + matcher: (token) => token.type === 'color', + transformer: (token) => token.value, + }, + }, + platforms: { + css: { + // apply it per platform + transforms: ['color-transform'], + }, + }, + }; + ``` + + After + + ```js + export default { + // register it inline or by SD.registerTransform + hooks: { + transforms: { + 'color-transform': { + type: 'value', + filter: (token) => token.type === 'color', + transform: (token) => token.value, + }, + }, + }, + platforms: { + css: { + // apply it per platform + transforms: ['color-transform'], + }, + }, + }; + ``` + +- f2ed88b: BREAKING: Parsers, when registered, are put inside the `hooks.parsers` property now, as opposed to `parsers`. + `parsers` property has been repurposed: you will now also need to explicitly apply registered parsers by name in the `parsers` property, they no longer apply by default. + When registering a parser, you must also supply a `name` property just like with all other hooks, and the `parse` function has been renamed to `parser` for consistency. + + Before: + + ```js + export default { + // register it inline or by SD.registerPreprocessor + parsers: [ + { + pattern: /\.json5$/, + parse: ({ contents, filePath }) => { + return JSON5.parse(contents); + }, + }, + ], + }; + ``` + + After: + + ```js + export default { + hooks: { + parsers: { + name: 'json5-parser', + pattern: /\.json5$/, + parser: ({ contents, filePath }) => { + return JSON5.parse(contents); + }, + }, + }, + // apply it globally by name reference + parsers: ['json5-parser'], + }; + ``` + +- 7b82150: BREAKING: For formats using the `fileHeader` `formatHelpers` utility, it will no longer display a timestamp in the fileHeader output by default. This is now an opt-in by setting `file.formatting.fileHeaderTimestamp` to `true`. The reason for making this opt-in now is that using Style Dictionary in the context of a CI (continuous integration) pipeline is a common use-case, and when running on pull request event, output files always show a diff in git due to the timestamp changing, which often just means that the diff is bloated by redundancy. + + New: + + ```json + { + "platforms": { + "css": { + "files": [ + { + "destination": "variables.css", + "format": "css/variables", + "options": { + "formatting": { + "fileHeaderTimestamp": true + } + } + } + ] + } + } + } + ``` + + or: + + ```js + import { fileHeader } from 'style-dictionary/utils'; + + const headerContent = await fileHeader({ formatting: { fileHeaderTimestamp: true } }); + ``` + +### Minor Changes + +- e83886c: Allow expanding tokens on a global or platform-specific level. Supports conditionally expanding per token type, or using a function to determine this per individual token. + +### Patch Changes + +- 2f80da2: All formats using `createPropertyFormatter` or `formattedVariables` helpers now respect the `file.options.formatting` option passed by users to customize formatting. + + Example: + + ```js + { + platforms: { + css: { + transformGroup: 'css', + buildPath, + files: [ + { + destination: 'variables.css', + format: 'css/variables', + options: { + formatting: { indentation: ' ' }, + }, + }, + ] + } + } + } + ``` + +## 4.0.0-prerelease.26 + +### Minor Changes + +- 3485467: Fix some inconsistencies in some of the templates, usually with regards to spaces/newlines + +### Patch Changes + +- 6cfce97: Fix logging to be ordered by platform when building or cleaning platforms. This now happens in parallel, resulting in the logs being ordered randomly which was a small regression to the logging experience. +- 061c67e: Hotfix to address outputReferencesTransformed util not handling object-value tokens properly. + +## 4.0.0-prerelease.25 + +### Major Changes + +- 0b81a08: BREAKING: no longer wraps tokens of type asset in double quotes. Rather, we added a transform `asset/url` that will wrap such tokens inside `url("")` statements, this transform is applied to transformGroups scss, css and less. + +### Minor Changes + +- 2da5130: Added `outputReferencesTransformed` utility function to pass into outputReferences option, which will not output references for values that have been transitively transformed. + +### Patch Changes + +- 47face0: Token merging behavior changed so that upon token collisions, metadata props aren't accidentally merged together. + +## 4.0.0-prerelease.24 + +### Major Changes + +- 5e167de: BREAKING: moved `formatHelpers` away from the StyleDictionary class and export them in `'style-dictionary/utils'` entrypoint instead. + + Before + + ```js + import StyleDictionary from 'style-dictionary'; + + const { fileHeader, formattedVariables } = StyleDictionary.formatHelpers; + ``` + + After + + ```js + import { fileHeader, formattedVariables } from 'style-dictionary/utils'; + ``` + +- 90095a6: BREAKING: Allow specifying a `function` for `outputReferences`, conditionally outputting a ref or not per token. Also exposes `outputReferencesFilter` utility function which will determine whether a token should be outputting refs based on whether those referenced tokens were filtered out or not. + + If you are maintaining a custom format that allows `outputReferences` option, you'll need to take into account that it can be a function, and pass the correct options to it. + + Before: + + ```js + StyleDictionary.registerFormat({ + name: 'custom/es6', + formatter: async (dictionary) => { + const { allTokens, options, file } = dictionary; + const { usesDtcg } = options; + + const compileTokenValue = (token) => { + let value = usesDtcg ? token.$value : token.value; + const originalValue = usesDtcg ? token.original.$value : token.original.value; + + // Look here 👇 + const shouldOutputRefs = outputReferences && usesReferences(originalValue); + + if (shouldOutputRefs) { + // ... your code for putting back the reference in the output + value = ... + } + return value; + } + return `${allTokens.reduce((acc, token) => `${acc}export const ${token.name} = ${compileTokenValue(token)};\n`, '')}`; + }, + }); + ``` + + After + + ```js + StyleDictionary.registerFormat({ + name: 'custom/es6', + formatter: async (dictionary) => { + const { allTokens, options, file } = dictionary; + const { usesDtcg } = options; + + const compileTokenValue = (token) => { + let value = usesDtcg ? token.$value : token.value; + const originalValue = usesDtcg ? token.original.$value : token.original.value; + + // Look here 👇 + const shouldOutputRef = + usesReferences(original) && + (typeof options.outputReferences === 'function' + ? outputReferences(token, { dictionary, usesDtcg }) + : options.outputReferences); + + if (shouldOutputRefs) { + // ... your code for putting back the reference in the output + value = ... + } + return value; + } + return `${allTokens.reduce((acc, token) => `${acc}export const ${token.name} = ${compileTokenValue(token)};\n`, '')}`; + }, + }); + ``` + +## 4.0.0-prerelease.23 + +### Patch Changes + +- f8c40f7: fix(types): add missing type keyword for type export from index.d.ts + +## 4.0.0-prerelease.22 + +### Patch Changes + +- daa78e1: Added missing type exports + +## 4.0.0-prerelease.21 + +### Minor Changes + +- 8b6fff3: Fixes some noisy warnings still being outputted even when verbosity is set to default. + + We also added log.warning "disabled" option for turning off warnings altogether, meaning you only get success logs and fatal errors. + This option can be used from the CLI as well using the `--no-warn` flag. + +### Patch Changes + +- 77ae35f: Fix scenario of passing absolute paths in Node env, do not remove leading slash in absolute paths. + +## 4.0.0-prerelease.20 + +### Minor Changes + +- aff6646: Allow passing a custom FileSystem Volume to your Style Dictionary instances, to ensure input/output files are read/written from/to that specific volume. + Useful in case you want multiple Style Dictionary instances that are isolated from one another in terms of inputs/outputs. + + ```js + import { Volume } from 'memfs'; + // You will need a bundler for memfs in browser... + // Or use as a prebundled fork: + import memfs from '@bundled-es-modules/memfs'; + const { Volume } = memfs; + + const vol = new Volume(); + + const sd = new StyleDictionary( + { + tokens: { + colors: { + red: { + value: '#FF0000', + type: 'color', + }, + }, + }, + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'variables.css', + format: 'css/variables', + }, + ], + }, + }, + }, + { volume: vol }, + ); + + await sd.buildAllPlatforms(); + + vol.readFileSync('/variables.css'); + /** + * :root { + * --colors-red: #FF0000; + * } + */ + ``` + + This also works when using extend: + + ```js + const extendedSd = await sd.extend(cfg, { volume: vol }); + ``` + +## 4.0.0-prerelease.19 + +### Major Changes + +- 79bb201: BREAKING: Logging has been redesigned a fair bit and is more configurable now. + + Before: + + ```json + { + "log": "error" // 'error' | 'warn' -> 'warn' is the default value + } + ``` + + After: + + ```json + { + "log": { + "warnings": "error", // 'error' | 'warn' -> 'warn' is the default value + "verbosity": "verbose" // 'default' | 'verbose' | 'silent' -> 'default' is the default value + } + } + ``` + + Log is now and object and the old "log" option is now "warnings". + + This configures whether the following five warnings will be thrown as errors instead of being logged as warnings: + + - Token value collisions (in the source) + - Token name collisions (when exporting) + - Missing "undo" function for Actions + - File not created because no tokens found, or all of them filtered out + - Broken references in file when using outputReferences, but referring to a token that's been filtered out + + Verbosity configures whether the following warnings/errors should display in a verbose manner: + + - Token collisions of both types (value & name) + - Broken references due to outputReferences & filters + - Token reference errors + + And it also configures whether success/neutral logs should be logged at all. + Using "silent" (or --silent in the CLI) means no logs are shown apart from fatal errors. + +- bcb5ef3: Remove reliance on CTI token structure across transforms, actions and formats. + + Breaking changes: + + - Token type will now be determined by "type" (or "$type") property on the token, rather than by checking its CTI attributes. This change has been reflected in all of the format templates as well as transform "matcher" functions that were previously checking `attributes.category` as the token type indicator. + - Types are mostly aligned with [DTCG spec types](https://design-tokens.github.io/community-group/format/#types), although a few additional ones have been added for compatibility reasons: + - asset -> string type tokens where the value is a filepath to an asset + - icon -> content type string tokens where the content resembles an icon, e.g. for icon fonts like [Microsoft codicons](https://github.com/microsoft/vscode-codicons) + - html -> HTML entity strings for unicode characters + - content -> regular string content e.g. text content which sometimes needs to be wrapped in quotes + - Built-in name transforms are now reliant only on the token path, and are renamed from `name/cti/casing` to just `name/casing`. `name/ti/camel` and `name/ti/constant` have been removed. For example `name/cti/kebab` transform is now `name/kebab`. + - Transform `content/icon` has been renamed to `html/icon` since it targets HTML entity strings, not just any icon content. + - `font/objC/literal`, `font/swift/literal` and `font/flutter/literal` have been removed in favor of `font/objC/literal`, `font/swift/literal` and `font/flutter/literal`, as they do he exact same transformations. + - `typescript/module-declarations` format to be updated with current DesignToken type interface. + + Before: + + ```json + { + "color": { + "red": { + "value": "#FF0000" + } + } + } + ``` + + After: + + ```json + { + "color": { + // <-- this no longer needs to be "color" in order for the tokens inside this group to be considered of type "color" + "red": { + "value": "#FF0000", + "type": "color" + } + } + } + ``` + +### Patch Changes + +- 8e297d6: Fix outputReferences for DTCG spec tokens, by using token.original.$value instead of token.original.value. + +## 4.0.0-prerelease.18 + +### Patch Changes + +- 738686b: Allow transformGroup to be combined with transforms, where standalone transforms will be added after the group's transforms. + +## 4.0.0-prerelease.17 + +### Patch Changes + +- 63681a6: Fix a couple of type imports issues in .d.ts files + +## 4.0.0-prerelease.16 + +### Patch Changes + +- 72f020d: Pass outputReferenceFallbacks option to the relevant utilities, so the option actually works. +- d008c67: Fix a couple of spots where DTCG option wasn't properly taken into account, more tests added. + +## 4.0.0-prerelease.15 + +### Major Changes + +- 502dbd1: BREAKING: All of our hooks, parsers, preprocessors, transforms, formats, actions, fileHeaders and filters, support async functions as well now. This means that the formatHelpers -> fileHeader helper method is now asynchronous, to support async fileheader functions. + + ```js + import StyleDictionary from 'style-dictionary'; + + const { fileHeader } = StyleDictionary.formatHelpers; + + StyleDictionary.registerFormat({ + name: 'custom/css', + // this can be async now, usually it is if you use fileHeader format helper, since that now always returns a Promise + formatter: async function ({ dictionary, file, options }) { + const { outputReferences } = options; + return ( + // this helper is now async! because the user-passed file.fileHeader might be an async function + (await fileHeader({ file })) + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, + }); + ``` + +## 4.0.0-prerelease.14 -* **formats:** add options.outputStringLiterals to typescript/es6-declarations ([#857](https://github.com/amzn/style-dictionary/issues/857)) ([0c31718](https://github.com/amzn/style-dictionary/commit/0c31718eb09e89216fb2446a94d9b505635b9f18)), closes [#905](https://github.com/amzn/style-dictionary/issues/905) -* **formats:** compose object imports ([#874](https://github.com/amzn/style-dictionary/issues/874)) ([8373721](https://github.com/amzn/style-dictionary/commit/83737211d2da2e004ddfb09ede912175f5b4b1bd)) -* **types:** loosening the Platform type to allow for extension ([#926](https://github.com/amzn/style-dictionary/issues/926)) ([c43263b](https://github.com/amzn/style-dictionary/commit/c43263bfd5223a7f24525f20aa87958aeedab812)) +### Minor Changes +- 606af51: Rename `typeW3CDelegate` utility function to `typeDtcgDelegate`, as using "W3C" is highly discouraged when the standard isn't a W3C standard yet. +- 606af51: Support the use of "value"/"type"/"description" as token names or token group names, at the sacrifice of now no longer being able to combine non-DTCG and DTCG syntax within the same token dictionary. + +### Patch Changes + +- cd9f484: Escape double quotes for ts outputStringLiterals + +## 4.0.0-prerelease.13 + +### Patch Changes + +- 24584b4: Conditionally only run dev scripts when CWD is style-dictionary, so our consumers don't run it by accident + +## 4.0.0-prerelease.12 + +### Patch Changes + +- c2cbd1b: Publish the postinstall-dev script to NPM. + +## 4.0.0-prerelease.11 + +### Patch Changes + +- cd48aac: Only run postinstall scripts when NODE_ENV isn't production (e.g. npm install --production or --omit=dev). To avoid errors running husky/patch-package. + +## 4.0.0-prerelease.10 + +### Patch Changes + +- 0c1a36f: Fix small issue in type DTCG delegate utility type tracking. +- 0c1a36f: Expose `typeDtcgDelegate` utility. Don't take `value` into account anymore to determine that it's a design token, use `$value`. + +## 4.0.0-prerelease.9 + +### Minor Changes + +- 294fd0e: Support Design Token Community Group Draft specification for Design Tokens, by adding support for $value, $type and $description properties. + +### Patch Changes + +- 3138313: Allow transitive transforms to return undefined, by doing this the transformer can mark itself as "deferred" for that specific token. This is useful when references in properties other than "value" need to be resolved first. + +## 4.0.0-prerelease.8 + +### Patch Changes + +- 59f3eb0: Expose flattenTokens utility. +- 39547fb: Fix parsers async support, use resolved filePath instead of raw. + +## 4.0.0-prerelease.7 + +### Minor Changes + +- 0410295: Improve and test the error handling of standalone usage of reference utilities. + +## 4.0.0-prerelease.6 + +### Patch Changes + +- 1dd828c: Fix issue in browser-bundled glob, bump. + +## 4.0.0-prerelease.5 + +### Major Changes + +- 6cc7f31: BREAKING: + + - `usesReference` util function is now `usesReferences` to be consistent plural form like the other reference util functions. + - `getReferences` first and second parameters have been swapped to be consistent with `resolveReferences`, so value first, then the full token object (instead of the entire dictionary instance). + - `getReferences` accepts a third options parameter which can be used to set reference Regex options as well as an unfilteredTokens object which can be used as a fallback when references are made to tokens that have been filtered out. There will be warnings logged for this. + - `format.formatter` removed old function signature of `(dictionary, platform, file)` in favor of `({ dictionary, platform, options, file })`. + - Types changes: + + - Style Dictionary is entirely strictly typed now, and there will be `.d.ts` files published next to every file, this means that if you import from one of Style Dictionary's entrypoints, you automatically get the types implicitly with it. This is a big win for people using TypeScript, as the majority of the codebase now has much better types, with much fewer `any`s. + - There is no more hand-written Style Dictionary module `index.d.ts` anymore that exposes all type interfaces on itself. This means that you can no longer grab types that aren't members of the Style Dictionary class directly from the default export of the main entrypoint. External types such as `Parser`, `Transform`, `DesignTokens`, etc. can be imported from the newly added types entrypoint: + + ```ts + import type { DesignTokens, Transform, Parser } from 'style-dictionary/types'; + ``` + + Please raise an issue if you find anything missing or suddenly broken. + + - `Matcher`, `Transformer`, `Formatter`, etc. are still available, although no longer directly but rather as properties on their parents, so `Filter['matcher']`, `Transform['transformer']`, `Format['formatter']` + +### Patch Changes + +- e859036: Fix Windows support by using a Linux/Windows + Node/Browser compatible path utility. Upgrade to latest Glob version. Apply posix: true to prevent breaking change glob update. + +## 4.0.0-prerelease.4 + +### Minor Changes + +- 122c8f6: Expose a new utility called resolveReferences which takes a value containing references, the dictionary object, and resolves the value's references for you. + + ```js + import StyleDictionary from 'style-dictionary'; + import { resolveReferences } from 'style-dictionary/utils'; + + const sd = new StyleDictionary({ + tokens: { + foo: { value: 'foo' }, + bar: { value: '{foo}' }, + qux: { value: '{bar}' }, + }, + }); + + console.log(resolveReferences(sd.tokens.qux.value, sd.tokens)); // 'foo' + ``` + +- 122c8f6: BREAKING: expose getReferences and usesReference utilities as standalone utils rather than requiring them to be bound to dictionary object. This makes it easier to use. + +### Patch Changes + +- 044123c: Patch StyleDictionary main type file to export default instead of "export =" which does not work in ESM. + +## 4.0.0-prerelease.3 + +### Patch Changes + +- 8d2f6d8: Make sure fs-node.js file is published to NPM. + +## 4.0.0-prerelease.2 + +### Major Changes + +- a4542f4: BREAKING: StyleDictionaryInstance.properties & .allProperties have been removed. They were deprecated in v3 in favor of .tokens and .allTokens. +- a4542f4: BREAKING: StyleDictionary to be initialized with a new API and have async methods. Use: + + ```js + import StyleDictionary from 'style-dictionary'; + + /** + * old: + * const sd = StyleDictionary.extend({ source: ['tokens.json'], platforms: {} }); + * sd.buildAllPlatforms(); + */ + const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); + await sd.buildAllPlatforms(); + ``` + + You can still extend a dictionary instance with an extended config, but `.extend()` is only used for this, it is no longer used to initialize the first instance: + + ```js + import StyleDictionary from 'style-dictionary'; + + const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); + const extended = await sd.extend({ + fileHeader: { + myFileHeader: (defaultMessage) => { + return [...defaultMessage, 'hello, world!']; + }, + }, + }); + ``` + + To ensure your initialized StyleDictionary instance is fully ready and has imported all your tokens, you can await `hasInitialized`: + + ```js + import StyleDictionary from 'style-dictionary'; + + const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); + await sd.hasInitialized; + console.log(sd.allTokens); + ``` + + For error handling and testing purposes, you can also manually initialize the style-dictionary config: + + ```js + import StyleDictionary from 'style-dictionary'; + + const sd = new StyleDictionary({ source: ['tokens.js'], platforms: {} }, { init: false }); + try { + await sd.init(); + } catch (e) { + // handle error, e.g. when tokens.js file has syntax errors and cannot be imported + } + console.log(sd.allTokens); + ``` + + The main reason for an initialize step after class instantiation is that async constructors are not a thing in JavaScript, and if you return a promise from a constructor to "hack it", TypeScript will eventually trip over it. + + Due to being able to dynamically (asynchronously) import ES Modules rather than synchronously require CommonJS modules, we had to make the APIs asynchronous, so the following methods are now async: + + - extend + - exportPlatform + - buildAllPlatforms & buildPlatform + - cleanAllPlatforms & cleanPlatform + + In a future release, most other methods will be made async or support async as well, such as parsers, transforms, formats etc. + +### Minor Changes + +- cedf8a0: Preprocessors are a new feature added to style-dictionary, which allows you to do any type of processing of the token dictionary **after** parsing, **before** resolving and transforming. + See [preprocessor docs](https://github.com/amzn/style-dictionary/tree/v4/docs/preprocessors.md) for more information. +- a4542f4: options.log to be respected in all error logging, including platform specific logs. + +## 4.0.0-prerelease.1 + +### Patch Changes + +- c1dd5ec: Allow overriding CSS formatting with commentStyle and commentPosition props. + For commentStyle, options are 'short' or 'long'. + For commentPosition, options are 'above' or 'inline'. + + We also ensure that the right defaults are picked for CSS, SASS/SCSS, Stylus and Less. + + This also contains a fix for ensuring that multi-line comments are automatically put "above" rather than "inline". + +- 6fb81ad: Allow falsy token values for outputReferences, e.g. `0`. +- 24d41c3: Allow outputReferences to work on non-string values. + +## 4.0.0-prerelease.0 + +### Major Changes + +- dcbe2fb: + - The project has been fully converted to [ESM format](https://nodejs.org/api/esm.html), which is also the format that the browser uses. + For users, this means you'll have to either use Style Dictionary in ESM JavaScript code, or dynamically import it into your CommonJS code. + - `StyleDictionary.extend()` method is now asynchronous, which means it returns `Promise` instead of `StyleDictionary.Core`. + - `allProperties` / `properties` was deprecated in v3, and is now removed from `StyleDictionary.Core`, use `allTokens` and `tokens` instead. + - Templates and the method `registerTemplate` were deprecated in v3, now removed. Use Formats instead. + - The package now uses [package entrypoints](https://nodejs.org/api/packages.html), which means that what is importable from the package is locked down to just the specified entrypoints: `style-dictionary` & `style-dictionary/fs`. If more is needed, please raise an issue explaining which file you were importing and why you need it to be public API. + +### Minor Changes + +- dcbe2fb: FileSystem that is used by Style Dictionary can now be customized: + + ```js + import { setFs } from 'style-dictionary/fs'; + setFs(myFileSystemShim); + ``` + + By default, it uses an in-memory filesystem shim `@bundled-es-modules/memfs` in browser context, `node:fs` built-in module in Node context. + +## [3.8.0](https://github.com/amzn/style-dictionary/compare/v3.7.2...v3.8.0) (2023-04-25) + +### Features + +- **formats:** add options.outputStringLiterals to typescript/es6-declarations ([#857](https://github.com/amzn/style-dictionary/issues/857)) ([0c31718](https://github.com/amzn/style-dictionary/commit/0c31718eb09e89216fb2446a94d9b505635b9f18)), closes [#905](https://github.com/amzn/style-dictionary/issues/905) +- **formats:** compose object imports ([#874](https://github.com/amzn/style-dictionary/issues/874)) ([8373721](https://github.com/amzn/style-dictionary/commit/83737211d2da2e004ddfb09ede912175f5b4b1bd)) +- **types:** loosening the Platform type to allow for extension ([#926](https://github.com/amzn/style-dictionary/issues/926)) ([c43263b](https://github.com/amzn/style-dictionary/commit/c43263bfd5223a7f24525f20aa87958aeedab812)) ### Bug Fixes -* **formats:** added missing EOL before EOF for some formats ([#963](https://github.com/amzn/style-dictionary/issues/963)) ([dd60479](https://github.com/amzn/style-dictionary/commit/dd60479d9a5dbc707476259b03f27c719f17e17d)) -* **types:** add correct return types for sortByReference ([#919](https://github.com/amzn/style-dictionary/issues/919)) ([2eff17d](https://github.com/amzn/style-dictionary/commit/2eff17d50c518cd86d68970f904413908e848fa7)), closes [#918](https://github.com/amzn/style-dictionary/issues/918) +- **formats:** added missing EOL before EOF for some formats ([#963](https://github.com/amzn/style-dictionary/issues/963)) ([dd60479](https://github.com/amzn/style-dictionary/commit/dd60479d9a5dbc707476259b03f27c719f17e17d)) +- **types:** add correct return types for sortByReference ([#919](https://github.com/amzn/style-dictionary/issues/919)) ([2eff17d](https://github.com/amzn/style-dictionary/commit/2eff17d50c518cd86d68970f904413908e848fa7)), closes [#918](https://github.com/amzn/style-dictionary/issues/918) ### [3.7.2](https://github.com/amzn/style-dictionary/compare/v3.7.0...v3.7.2) (2023-01-03) - ### Bug Fixes -* **docs:** Correct custom-file-header example link ([#869](https://github.com/amzn/style-dictionary/issues/869)) ([4e156b1](https://github.com/amzn/style-dictionary/commit/4e156b103a35dfb6e70d48db4d04892cc6fb2d43)) -* **docs:** removed the duplicate wording ([#870](https://github.com/amzn/style-dictionary/issues/870)) ([dbb89e5](https://github.com/amzn/style-dictionary/commit/dbb89e59c656c2951ee36ed11ab65edb4d60ee05)) -* **formats:** scss/map-deep type error when values are strings or null ([#838](https://github.com/amzn/style-dictionary/issues/838)) ([d338633](https://github.com/amzn/style-dictionary/commit/d338633fd8c864470e44ff902ed0ed45dc4a3958)), closes [#837](https://github.com/amzn/style-dictionary/issues/837) -* **references:** getReferences now searches the entire object ([#812](https://github.com/amzn/style-dictionary/issues/812)) ([884b1b8](https://github.com/amzn/style-dictionary/commit/884b1b896852d9e0b75066207d06619d500d1d3f)) -* **references:** tokens with a number value should be interpolated correctly ([#825](https://github.com/amzn/style-dictionary/issues/825)) ([a2f7784](https://github.com/amzn/style-dictionary/commit/a2f7784d719f3f416f32a8346cb33f83266f288a)) -* **transforms:** transitive transforms now work without .value in refs ([#808](https://github.com/amzn/style-dictionary/issues/808)) ([41bc893](https://github.com/amzn/style-dictionary/commit/41bc893ffb49ed241c8affe9098672d558966472)) -* **types:** add matcher type to export ([#878](https://github.com/amzn/style-dictionary/issues/878)) ([2617a0d](https://github.com/amzn/style-dictionary/commit/2617a0d42d9c0c017e2a54ad9ea5e8667ece9c92)), closes [#875](https://github.com/amzn/style-dictionary/issues/875) -* **types:** added packageName as optional property on interface File ([#829](https://github.com/amzn/style-dictionary/issues/829)) ([0996cc4](https://github.com/amzn/style-dictionary/commit/0996cc473fe97aaff3298cdfeb20b159e8329ce1)) -* **types:** adding missing format helpers ([#834](https://github.com/amzn/style-dictionary/issues/834)) ([a6f4b34](https://github.com/amzn/style-dictionary/commit/a6f4b3487cf5ef9230417108b07ad73a74d9fa0e)) -* **types:** fix filter config key expected matcher value ([#883](https://github.com/amzn/style-dictionary/issues/883)) ([c77c3db](https://github.com/amzn/style-dictionary/commit/c77c3db2244ccb736b4752591f0494c31b9a1184)) -* **types:** fixing transform group property type of Config ([#833](https://github.com/amzn/style-dictionary/issues/833)) ([0f0ad10](https://github.com/amzn/style-dictionary/commit/0f0ad10564df93813df1261a8ddc55e70f261ad5)) +- **docs:** Correct custom-file-header example link ([#869](https://github.com/amzn/style-dictionary/issues/869)) ([4e156b1](https://github.com/amzn/style-dictionary/commit/4e156b103a35dfb6e70d48db4d04892cc6fb2d43)) +- **docs:** removed the duplicate wording ([#870](https://github.com/amzn/style-dictionary/issues/870)) ([dbb89e5](https://github.com/amzn/style-dictionary/commit/dbb89e59c656c2951ee36ed11ab65edb4d60ee05)) +- **formats:** scss/map-deep type error when values are strings or null ([#838](https://github.com/amzn/style-dictionary/issues/838)) ([d338633](https://github.com/amzn/style-dictionary/commit/d338633fd8c864470e44ff902ed0ed45dc4a3958)), closes [#837](https://github.com/amzn/style-dictionary/issues/837) +- **references:** getReferences now searches the entire object ([#812](https://github.com/amzn/style-dictionary/issues/812)) ([884b1b8](https://github.com/amzn/style-dictionary/commit/884b1b896852d9e0b75066207d06619d500d1d3f)) +- **references:** tokens with a number value should be interpolated correctly ([#825](https://github.com/amzn/style-dictionary/issues/825)) ([a2f7784](https://github.com/amzn/style-dictionary/commit/a2f7784d719f3f416f32a8346cb33f83266f288a)) +- **transforms:** transitive transforms now work without .value in refs ([#808](https://github.com/amzn/style-dictionary/issues/808)) ([41bc893](https://github.com/amzn/style-dictionary/commit/41bc893ffb49ed241c8affe9098672d558966472)) +- **types:** add matcher type to export ([#878](https://github.com/amzn/style-dictionary/issues/878)) ([2617a0d](https://github.com/amzn/style-dictionary/commit/2617a0d42d9c0c017e2a54ad9ea5e8667ece9c92)), closes [#875](https://github.com/amzn/style-dictionary/issues/875) +- **types:** added packageName as optional property on interface File ([#829](https://github.com/amzn/style-dictionary/issues/829)) ([0996cc4](https://github.com/amzn/style-dictionary/commit/0996cc473fe97aaff3298cdfeb20b159e8329ce1)) +- **types:** adding missing format helpers ([#834](https://github.com/amzn/style-dictionary/issues/834)) ([a6f4b34](https://github.com/amzn/style-dictionary/commit/a6f4b3487cf5ef9230417108b07ad73a74d9fa0e)) +- **types:** fix filter config key expected matcher value ([#883](https://github.com/amzn/style-dictionary/issues/883)) ([c77c3db](https://github.com/amzn/style-dictionary/commit/c77c3db2244ccb736b4752591f0494c31b9a1184)) +- **types:** fixing transform group property type of Config ([#833](https://github.com/amzn/style-dictionary/issues/833)) ([0f0ad10](https://github.com/amzn/style-dictionary/commit/0f0ad10564df93813df1261a8ddc55e70f261ad5)) ### [3.7.1](https://github.com/amzn/style-dictionary/compare/v3.7.0...v3.7.1) (2022-06-07) - ### Bug Fixes -* **references:** getReferences now searches the entire object ([#812](https://github.com/amzn/style-dictionary/issues/812)) ([884b1b8](https://github.com/amzn/style-dictionary/commit/884b1b896852d9e0b75066207d06619d500d1d3f)) -* **references:** tokens with a number value should be interpolated correctly ([#825](https://github.com/amzn/style-dictionary/issues/825)) ([a2f7784](https://github.com/amzn/style-dictionary/commit/a2f7784d719f3f416f32a8346cb33f83266f288a)) -* **transforms:** transitive transforms now work without .value in refs ([#808](https://github.com/amzn/style-dictionary/issues/808)) ([41bc893](https://github.com/amzn/style-dictionary/commit/41bc893ffb49ed241c8affe9098672d558966472)) +- **references:** getReferences now searches the entire object ([#812](https://github.com/amzn/style-dictionary/issues/812)) ([884b1b8](https://github.com/amzn/style-dictionary/commit/884b1b896852d9e0b75066207d06619d500d1d3f)) +- **references:** tokens with a number value should be interpolated correctly ([#825](https://github.com/amzn/style-dictionary/issues/825)) ([a2f7784](https://github.com/amzn/style-dictionary/commit/a2f7784d719f3f416f32a8346cb33f83266f288a)) +- **transforms:** transitive transforms now work without .value in refs ([#808](https://github.com/amzn/style-dictionary/issues/808)) ([41bc893](https://github.com/amzn/style-dictionary/commit/41bc893ffb49ed241c8affe9098672d558966472)) ## [3.7.0](https://github.com/amzn/style-dictionary/compare/v3.1.1...v3.7.0) (2022-02-22) - ### Features -* **filter:** Added new filter `removePrivate` ([#770](https://github.com/amzn/style-dictionary/issues/770)) ([3217ba3](https://github.com/amzn/style-dictionary/commit/3217ba365770ea18b9bdf6e5abfcb205268ac936)), closes [#704](https://github.com/amzn/style-dictionary/issues/704) -* **formats:** any swift format ([#734](https://github.com/amzn/style-dictionary/issues/734)) ([9859a8d](https://github.com/amzn/style-dictionary/commit/9859a8dc852a4db1e217880d778c7bed29dd5e40)) - +- **filter:** Added new filter `removePrivate` ([#770](https://github.com/amzn/style-dictionary/issues/770)) ([3217ba3](https://github.com/amzn/style-dictionary/commit/3217ba365770ea18b9bdf6e5abfcb205268ac936)), closes [#704](https://github.com/amzn/style-dictionary/issues/704) +- **formats:** any swift format ([#734](https://github.com/amzn/style-dictionary/issues/734)) ([9859a8d](https://github.com/amzn/style-dictionary/commit/9859a8dc852a4db1e217880d778c7bed29dd5e40)) ### Bug Fixes -* **examples:** complete example style dictionary version to latest ([#755](https://github.com/amzn/style-dictionary/issues/755)) ([c3aae93](https://github.com/amzn/style-dictionary/commit/c3aae93c2dc35eeafdd8dbc2072daebb9c37fb86)) -* **types:** Correct type of `Core.format` ([#780](https://github.com/amzn/style-dictionary/issues/780)) ([9868b7e](https://github.com/amzn/style-dictionary/commit/9868b7e1ff4768c84a0f632db500dba6e18a6f44)), closes [#779](https://github.com/amzn/style-dictionary/issues/779) +- **examples:** complete example style dictionary version to latest ([#755](https://github.com/amzn/style-dictionary/issues/755)) ([c3aae93](https://github.com/amzn/style-dictionary/commit/c3aae93c2dc35eeafdd8dbc2072daebb9c37fb86)) +- **types:** Correct type of `Core.format` ([#780](https://github.com/amzn/style-dictionary/issues/780)) ([9868b7e](https://github.com/amzn/style-dictionary/commit/9868b7e1ff4768c84a0f632db500dba6e18a6f44)), closes [#779](https://github.com/amzn/style-dictionary/issues/779) ### [3.1.1](https://github.com/amzn/style-dictionary/compare/v3.1.0...v3.1.1) (2021-12-17) - ### Bug Fixes -* **deps:** adding jsonc-parser to regular dependencies ([#750](https://github.com/amzn/style-dictionary/issues/750)) ([43ff607](https://github.com/amzn/style-dictionary/commit/43ff607c74de7d796fe9e68ca7e26d9bd434498e)) +- **deps:** adding jsonc-parser to regular dependencies ([#750](https://github.com/amzn/style-dictionary/issues/750)) ([43ff607](https://github.com/amzn/style-dictionary/commit/43ff607c74de7d796fe9e68ca7e26d9bd434498e)) ## [3.1.0](https://github.com/amzn/style-dictionary/compare/v3.0.3...v3.1.0) (2021-12-16) - ### Features -* **formats:** Add `outputReferences` support to `scss/map-deep` ([#720](https://github.com/amzn/style-dictionary/issues/720)) ([65453e0](https://github.com/amzn/style-dictionary/commit/65453e0d980273aeeb1a201a1996c4ad3a5719a5)), closes [#712](https://github.com/amzn/style-dictionary/issues/712) -* **formats:** add support for Microsoft's JSONC format ([#732](https://github.com/amzn/style-dictionary/issues/732)) ([cfa83cb](https://github.com/amzn/style-dictionary/commit/cfa83cb65b7ec7b3e5a9def7f0ceb6ac3b2898df)), closes [#698](https://github.com/amzn/style-dictionary/issues/698) -* **formats:** object handling for typescript/es6-declarations ([#718](https://github.com/amzn/style-dictionary/issues/718)) ([4e3905a](https://github.com/amzn/style-dictionary/commit/4e3905a7a3525f872615adaf0cae0b5553309bb6)) -* **references:** ability to reference other tokens without 'value' ([#746](https://github.com/amzn/style-dictionary/issues/746)) ([c6f482e](https://github.com/amzn/style-dictionary/commit/c6f482e2845f8e13e579ffc858b0e53b9155a47e)) -* **transforms:** add transformer for Color class from SwiftUI ([#733](https://github.com/amzn/style-dictionary/issues/733)) ([439e474](https://github.com/amzn/style-dictionary/commit/439e474aee9da8390f447f31d412e496c45b4605)) - +- **formats:** Add `outputReferences` support to `scss/map-deep` ([#720](https://github.com/amzn/style-dictionary/issues/720)) ([65453e0](https://github.com/amzn/style-dictionary/commit/65453e0d980273aeeb1a201a1996c4ad3a5719a5)), closes [#712](https://github.com/amzn/style-dictionary/issues/712) +- **formats:** add support for Microsoft's JSONC format ([#732](https://github.com/amzn/style-dictionary/issues/732)) ([cfa83cb](https://github.com/amzn/style-dictionary/commit/cfa83cb65b7ec7b3e5a9def7f0ceb6ac3b2898df)), closes [#698](https://github.com/amzn/style-dictionary/issues/698) +- **formats:** object handling for typescript/es6-declarations ([#718](https://github.com/amzn/style-dictionary/issues/718)) ([4e3905a](https://github.com/amzn/style-dictionary/commit/4e3905a7a3525f872615adaf0cae0b5553309bb6)) +- **references:** ability to reference other tokens without 'value' ([#746](https://github.com/amzn/style-dictionary/issues/746)) ([c6f482e](https://github.com/amzn/style-dictionary/commit/c6f482e2845f8e13e579ffc858b0e53b9155a47e)) +- **transforms:** add transformer for Color class from SwiftUI ([#733](https://github.com/amzn/style-dictionary/issues/733)) ([439e474](https://github.com/amzn/style-dictionary/commit/439e474aee9da8390f447f31d412e496c45b4605)) ### Bug Fixes -* **cli:** fixing unknown commands message ([#747](https://github.com/amzn/style-dictionary/issues/747)) ([8a5f047](https://github.com/amzn/style-dictionary/commit/8a5f047af4a97a51894d4dfe4c917bf91686db8e)) -* **examples:** Watch correct directory ([#739](https://github.com/amzn/style-dictionary/issues/739)) ([56574a4](https://github.com/amzn/style-dictionary/commit/56574a4247eafc79a843e80f433feaf025142ff8)), closes [#705](https://github.com/amzn/style-dictionary/issues/705) -* **types:** adding registerFileHeader type ([#722](https://github.com/amzn/style-dictionary/issues/722)) ([54332b3](https://github.com/amzn/style-dictionary/commit/54332b3e4ee77a0b0e8f84836413949f8e64ccd5)), closes [#665](https://github.com/amzn/style-dictionary/issues/665) -* **types:** fixing transform group types ([#729](https://github.com/amzn/style-dictionary/issues/729)) ([ad7f6ea](https://github.com/amzn/style-dictionary/commit/ad7f6ea555ec77defd264c9ade9628aefd108959)) -* **types:** make FileHeaderArgs.commentStyle optional ([#743](https://github.com/amzn/style-dictionary/issues/743)) ([401d93b](https://github.com/amzn/style-dictionary/commit/401d93b72caf02cec34fba3c214edfdd5d52b362)) +- **cli:** fixing unknown commands message ([#747](https://github.com/amzn/style-dictionary/issues/747)) ([8a5f047](https://github.com/amzn/style-dictionary/commit/8a5f047af4a97a51894d4dfe4c917bf91686db8e)) +- **examples:** Watch correct directory ([#739](https://github.com/amzn/style-dictionary/issues/739)) ([56574a4](https://github.com/amzn/style-dictionary/commit/56574a4247eafc79a843e80f433feaf025142ff8)), closes [#705](https://github.com/amzn/style-dictionary/issues/705) +- **types:** adding registerFileHeader type ([#722](https://github.com/amzn/style-dictionary/issues/722)) ([54332b3](https://github.com/amzn/style-dictionary/commit/54332b3e4ee77a0b0e8f84836413949f8e64ccd5)), closes [#665](https://github.com/amzn/style-dictionary/issues/665) +- **types:** fixing transform group types ([#729](https://github.com/amzn/style-dictionary/issues/729)) ([ad7f6ea](https://github.com/amzn/style-dictionary/commit/ad7f6ea555ec77defd264c9ade9628aefd108959)) +- **types:** make FileHeaderArgs.commentStyle optional ([#743](https://github.com/amzn/style-dictionary/issues/743)) ([401d93b](https://github.com/amzn/style-dictionary/commit/401d93b72caf02cec34fba3c214edfdd5d52b362)) ### [3.0.3](https://github.com/amzn/style-dictionary/compare/v3.0.2...v3.0.3) (2021-10-15) - ### Bug Fixes -* **types:** `className` optional parameter ([#683](https://github.com/amzn/style-dictionary/issues/683)) ([639d7da](https://github.com/amzn/style-dictionary/commit/639d7daa49fccdf569ec39a14953e366df1d7908)), closes [/github.com/amzn/style-dictionary/blob/main/examples/basic/config.json#L100](https://github.com/amzn//github.com/amzn/style-dictionary/blob/main/examples/basic/config.json/issues/L100) -* **types:** added `name` to format, and export `Named` ([#714](https://github.com/amzn/style-dictionary/issues/714)) ([9ca0f6f](https://github.com/amzn/style-dictionary/commit/9ca0f6fc5d01706bf6864a2ea0fababb191f30f4)) +- **types:** `className` optional parameter ([#683](https://github.com/amzn/style-dictionary/issues/683)) ([639d7da](https://github.com/amzn/style-dictionary/commit/639d7daa49fccdf569ec39a14953e366df1d7908)), closes [/github.com/amzn/style-dictionary/blob/main/examples/basic/config.json#L100](https://github.com/amzn//github.com/amzn/style-dictionary/blob/main/examples/basic/config.json/issues/L100) +- **types:** added `name` to format, and export `Named` ([#714](https://github.com/amzn/style-dictionary/issues/714)) ([9ca0f6f](https://github.com/amzn/style-dictionary/commit/9ca0f6fc5d01706bf6864a2ea0fababb191f30f4)) ### [3.0.2](https://github.com/amzn/style-dictionary/compare/v3.0.1...v3.0.2) (2021-08-19) - ### Bug Fixes -* **format:** 'typescript/es6-declarations' return type ([#681](https://github.com/amzn/style-dictionary/issues/681)) ([0cf6c52](https://github.com/amzn/style-dictionary/commit/0cf6c52a3f85a91e5763dc31e0fb6efe2a531e25)) -* **lib:** fix `createFormatArgs` positional args ([#655](https://github.com/amzn/style-dictionary/issues/655)) ([29e511d](https://github.com/amzn/style-dictionary/commit/29e511d07e7991430f6f892879aeb0ade0c6a289)), closes [#652](https://github.com/amzn/style-dictionary/issues/652) -* **references:** check if object value is a string before replacement ([#682](https://github.com/amzn/style-dictionary/issues/682)) ([bfc204c](https://github.com/amzn/style-dictionary/commit/bfc204c50e7addde2b98dc5703b9be31b5b44823)) -* **types:** format config expects formatter function ([#650](https://github.com/amzn/style-dictionary/issues/650)) ([b12c4b1](https://github.com/amzn/style-dictionary/commit/b12c4b1c6a94c62c757cd1675d216d9638f8d6e0)) +- **format:** 'typescript/es6-declarations' return type ([#681](https://github.com/amzn/style-dictionary/issues/681)) ([0cf6c52](https://github.com/amzn/style-dictionary/commit/0cf6c52a3f85a91e5763dc31e0fb6efe2a531e25)) +- **lib:** fix `createFormatArgs` positional args ([#655](https://github.com/amzn/style-dictionary/issues/655)) ([29e511d](https://github.com/amzn/style-dictionary/commit/29e511d07e7991430f6f892879aeb0ade0c6a289)), closes [#652](https://github.com/amzn/style-dictionary/issues/652) +- **references:** check if object value is a string before replacement ([#682](https://github.com/amzn/style-dictionary/issues/682)) ([bfc204c](https://github.com/amzn/style-dictionary/commit/bfc204c50e7addde2b98dc5703b9be31b5b44823)) +- **types:** format config expects formatter function ([#650](https://github.com/amzn/style-dictionary/issues/650)) ([b12c4b1](https://github.com/amzn/style-dictionary/commit/b12c4b1c6a94c62c757cd1675d216d9638f8d6e0)) ### [3.0.1](https://github.com/amzn/style-dictionary/compare/v3.0.0...v3.0.1) (2021-06-07) - ### Bug Fixes -* **swift:** add missing space after UIColor's alpha property ([#648](https://github.com/amzn/style-dictionary/issues/648)) ([7c65733](https://github.com/amzn/style-dictionary/commit/7c65733c05a82b99960e6dca25124fce91fbda32)) -* **types:** directly export Named type to avoid ambiguity with TS --isolatedModules option ([8295b0d](https://github.com/amzn/style-dictionary/commit/8295b0dffc28a5dda934fb32a26f32ffcc241ffb)) -* **types:** directly export Named type to avoid ambiguity with TS --isolatedModules option ([3ed31be](https://github.com/amzn/style-dictionary/commit/3ed31be5b09312df88c66e9274672303a8609acc)) +- **swift:** add missing space after UIColor's alpha property ([#648](https://github.com/amzn/style-dictionary/issues/648)) ([7c65733](https://github.com/amzn/style-dictionary/commit/7c65733c05a82b99960e6dca25124fce91fbda32)) +- **types:** directly export Named type to avoid ambiguity with TS --isolatedModules option ([8295b0d](https://github.com/amzn/style-dictionary/commit/8295b0dffc28a5dda934fb32a26f32ffcc241ffb)) +- **types:** directly export Named type to avoid ambiguity with TS --isolatedModules option ([3ed31be](https://github.com/amzn/style-dictionary/commit/3ed31be5b09312df88c66e9274672303a8609acc)) ## [3.0.0](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.10...v3.0.0) (2021-05-25) ## [3.0.0-rc.10](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.9...v3.0.0-rc.10) (2021-05-24) - ### Features -* **formats:** add typescript declarations formats ([#557](https://github.com/amzn/style-dictionary/issues/557)) ([f517bcf](https://github.com/amzn/style-dictionary/commit/f517bcfa219bddc5a10b5443ccb85c4869711064)), closes [#425](https://github.com/amzn/style-dictionary/issues/425) -* **types:** cleaning up our type definitions ([#632](https://github.com/amzn/style-dictionary/issues/632)) ([db6269b](https://github.com/amzn/style-dictionary/commit/db6269b636264cc0849f595c0f15a34c977c1398)) - +- **formats:** add typescript declarations formats ([#557](https://github.com/amzn/style-dictionary/issues/557)) ([f517bcf](https://github.com/amzn/style-dictionary/commit/f517bcfa219bddc5a10b5443ccb85c4869711064)), closes [#425](https://github.com/amzn/style-dictionary/issues/425) +- **types:** cleaning up our type definitions ([#632](https://github.com/amzn/style-dictionary/issues/632)) ([db6269b](https://github.com/amzn/style-dictionary/commit/db6269b636264cc0849f595c0f15a34c977c1398)) ### Bug Fixes -* **references:** value object references now work ([#623](https://github.com/amzn/style-dictionary/issues/623)) ([23de306](https://github.com/amzn/style-dictionary/commit/23de3062c464a70d9e6492a380e1052e9500ea2d)), closes [#615](https://github.com/amzn/style-dictionary/issues/615) -* **template:** remove blank lines in scss/map-deep and scss/map-flat templates ([#588](https://github.com/amzn/style-dictionary/issues/588)) ([a88e622](https://github.com/amzn/style-dictionary/commit/a88e622bcc06a98972dddb2b11903828ba3dab2b)) +- **references:** value object references now work ([#623](https://github.com/amzn/style-dictionary/issues/623)) ([23de306](https://github.com/amzn/style-dictionary/commit/23de3062c464a70d9e6492a380e1052e9500ea2d)), closes [#615](https://github.com/amzn/style-dictionary/issues/615) +- **template:** remove blank lines in scss/map-deep and scss/map-flat templates ([#588](https://github.com/amzn/style-dictionary/issues/588)) ([a88e622](https://github.com/amzn/style-dictionary/commit/a88e622bcc06a98972dddb2b11903828ba3dab2b)) ### [2.10.3](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.5...v2.10.3) (2021-03-09) - ### Bug Fixes -* **extend:** remove prototype pollution ([#560](https://github.com/amzn/style-dictionary/issues/560)) ([89ee39a](https://github.com/amzn/style-dictionary/commit/89ee39a7953c1825ea4578d43f129e23b4ed5da8)) +- **extend:** remove prototype pollution ([#560](https://github.com/amzn/style-dictionary/issues/560)) ([89ee39a](https://github.com/amzn/style-dictionary/commit/89ee39a7953c1825ea4578d43f129e23b4ed5da8)) ## [3.0.0-rc.9](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.8...v3.0.0-rc.9) (2021-05-04) - ### Features -* **compose:** Add Jetpack Compose format ([#599](https://github.com/amzn/style-dictionary/issues/599)) ([8a53858](https://github.com/amzn/style-dictionary/commit/8a53858dc35f4b4565abe9a6500c78814e3e6eae)), closes [#478](https://github.com/amzn/style-dictionary/issues/478) - +- **compose:** Add Jetpack Compose format ([#599](https://github.com/amzn/style-dictionary/issues/599)) ([8a53858](https://github.com/amzn/style-dictionary/commit/8a53858dc35f4b4565abe9a6500c78814e3e6eae)), closes [#478](https://github.com/amzn/style-dictionary/issues/478) ### Bug Fixes -* **formats:** bringing mapName back to scss formats ([#611](https://github.com/amzn/style-dictionary/issues/611)) ([7a28f40](https://github.com/amzn/style-dictionary/commit/7a28f40b7f44b37e565b1360683b60268d044e9e)) -* **formats:** fixing formatting options in fileHeader ([#614](https://github.com/amzn/style-dictionary/issues/614)) ([3f7fe96](https://github.com/amzn/style-dictionary/commit/3f7fe9674c0cb1f228e0415ce468d18a48e4a7f0)), closes [#612](https://github.com/amzn/style-dictionary/issues/612) -* **references:** fixing circular reference errors ([#607](https://github.com/amzn/style-dictionary/issues/607)) ([9af17f4](https://github.com/amzn/style-dictionary/commit/9af17f420c2a11c64f77041f5c2439c093f9c035)), closes [#608](https://github.com/amzn/style-dictionary/issues/608) -* **references:** flushing the filtered reference warnings ([#598](https://github.com/amzn/style-dictionary/issues/598)) ([d3b5135](https://github.com/amzn/style-dictionary/commit/d3b51352f33cb15765cb152605acd3c44e6fbf69)) +- **formats:** bringing mapName back to scss formats ([#611](https://github.com/amzn/style-dictionary/issues/611)) ([7a28f40](https://github.com/amzn/style-dictionary/commit/7a28f40b7f44b37e565b1360683b60268d044e9e)) +- **formats:** fixing formatting options in fileHeader ([#614](https://github.com/amzn/style-dictionary/issues/614)) ([3f7fe96](https://github.com/amzn/style-dictionary/commit/3f7fe9674c0cb1f228e0415ce468d18a48e4a7f0)), closes [#612](https://github.com/amzn/style-dictionary/issues/612) +- **references:** fixing circular reference errors ([#607](https://github.com/amzn/style-dictionary/issues/607)) ([9af17f4](https://github.com/amzn/style-dictionary/commit/9af17f420c2a11c64f77041f5c2439c093f9c035)), closes [#608](https://github.com/amzn/style-dictionary/issues/608) +- **references:** flushing the filtered reference warnings ([#598](https://github.com/amzn/style-dictionary/issues/598)) ([d3b5135](https://github.com/amzn/style-dictionary/commit/d3b51352f33cb15765cb152605acd3c44e6fbf69)) ## [3.0.0-rc.8](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.7...v3.0.0-rc.8) (2021-04-05) - ### Features -* **formats:** add an optional selector to css/variables format ([#582](https://github.com/amzn/style-dictionary/issues/582)) ([34922a8](https://github.com/amzn/style-dictionary/commit/34922a8572b7cefc6ca579cca9f73b16bfc4efc0)) -* **formats:** output references handles interpoloated references ([#590](https://github.com/amzn/style-dictionary/issues/590)) ([cc595ca](https://github.com/amzn/style-dictionary/commit/cc595ca0683cc757dfae562a8688eb0b8d121cbe)), closes [#589](https://github.com/amzn/style-dictionary/issues/589) - +- **formats:** add an optional selector to css/variables format ([#582](https://github.com/amzn/style-dictionary/issues/582)) ([34922a8](https://github.com/amzn/style-dictionary/commit/34922a8572b7cefc6ca579cca9f73b16bfc4efc0)) +- **formats:** output references handles interpoloated references ([#590](https://github.com/amzn/style-dictionary/issues/590)) ([cc595ca](https://github.com/amzn/style-dictionary/commit/cc595ca0683cc757dfae562a8688eb0b8d121cbe)), closes [#589](https://github.com/amzn/style-dictionary/issues/589) ### Bug Fixes -* **combine:** filePath was missing for falsey values ([#583](https://github.com/amzn/style-dictionary/issues/583)) ([8c405e6](https://github.com/amzn/style-dictionary/commit/8c405e6765367aff7eb94fda1a0a235f1c422c9c)) -* **formats:** update output references in formats to handle nested references ([#587](https://github.com/amzn/style-dictionary/issues/587)) ([9ce0311](https://github.com/amzn/style-dictionary/commit/9ce031108979493c7f5d0df34e3546322694feb6)) +- **combine:** filePath was missing for falsey values ([#583](https://github.com/amzn/style-dictionary/issues/583)) ([8c405e6](https://github.com/amzn/style-dictionary/commit/8c405e6765367aff7eb94fda1a0a235f1c422c9c)) +- **formats:** update output references in formats to handle nested references ([#587](https://github.com/amzn/style-dictionary/issues/587)) ([9ce0311](https://github.com/amzn/style-dictionary/commit/9ce031108979493c7f5d0df34e3546322694feb6)) ## [3.0.0-rc.7](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.6...v3.0.0-rc.7) (2021-03-24) - ### Features -* **formats:** adding custom file headers ([#572](https://github.com/amzn/style-dictionary/issues/572)) ([2a29502](https://github.com/amzn/style-dictionary/commit/2a29502f762c8694dd541dc9c0a0e0aa32e4dec9)), closes [#566](https://github.com/amzn/style-dictionary/issues/566) - +- **formats:** adding custom file headers ([#572](https://github.com/amzn/style-dictionary/issues/572)) ([2a29502](https://github.com/amzn/style-dictionary/commit/2a29502f762c8694dd541dc9c0a0e0aa32e4dec9)), closes [#566](https://github.com/amzn/style-dictionary/issues/566) ### Bug Fixes -* **references:** use unfiltered dictionary for reference resolution in formats ([#553](https://github.com/amzn/style-dictionary/issues/553)) ([62c8fb8](https://github.com/amzn/style-dictionary/commit/62c8fb8ddaccb94dc2eee3b4504f38c264689b77)) +- **references:** use unfiltered dictionary for reference resolution in formats ([#553](https://github.com/amzn/style-dictionary/issues/553)) ([62c8fb8](https://github.com/amzn/style-dictionary/commit/62c8fb8ddaccb94dc2eee3b4504f38c264689b77)) ## [3.0.0-rc.6](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.5...v3.0.0-rc.6) (2021-03-09) - ### Bug Fixes -* **extend:** remove prototype pollution ([#554](https://github.com/amzn/style-dictionary/issues/554)) ([b99710a](https://github.com/amzn/style-dictionary/commit/b99710a23abf7d49be28f4ce33dbe99a8af5923f)) +- **extend:** remove prototype pollution ([#554](https://github.com/amzn/style-dictionary/issues/554)) ([b99710a](https://github.com/amzn/style-dictionary/commit/b99710a23abf7d49be28f4ce33dbe99a8af5923f)) ## [3.0.0-rc.5](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.4...v3.0.0-rc.5) (2021-02-27) - ### Bug Fixes -* **types:** introduce parser, update config, optional transform options ([#546](https://github.com/amzn/style-dictionary/issues/546)) ([0042354](https://github.com/amzn/style-dictionary/commit/0042354b4ccb43ef26ddb13adab82b73f25dbf4f)), closes [#545](https://github.com/amzn/style-dictionary/issues/545) +- **types:** introduce parser, update config, optional transform options ([#546](https://github.com/amzn/style-dictionary/issues/546)) ([0042354](https://github.com/amzn/style-dictionary/commit/0042354b4ccb43ef26ddb13adab82b73f25dbf4f)), closes [#545](https://github.com/amzn/style-dictionary/issues/545) ## [3.0.0-rc.4](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.3...v3.0.0-rc.4) (2021-02-16) - ### Features -* **formats:** add stylus/variables format ([#527](https://github.com/amzn/style-dictionary/issues/527)) ([8c56752](https://github.com/amzn/style-dictionary/commit/8c56752d43616884fe6b1f4f7a77994396ce2c3f)), closes [#526](https://github.com/amzn/style-dictionary/issues/526) +- **formats:** add stylus/variables format ([#527](https://github.com/amzn/style-dictionary/issues/527)) ([8c56752](https://github.com/amzn/style-dictionary/commit/8c56752d43616884fe6b1f4f7a77994396ce2c3f)), closes [#526](https://github.com/amzn/style-dictionary/issues/526) ## [3.0.0-rc.3](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.2...v3.0.0-rc.3) (2021-02-06) - ### Features -* **build-file:** do not generate file if properties is empty ([#494](https://github.com/amzn/style-dictionary/issues/494)) ([8945c46](https://github.com/amzn/style-dictionary/commit/8945c46f26a08ff6ffac3a5aa0e84a0f330efdb4)) -* **format:** output references ([#504](https://github.com/amzn/style-dictionary/issues/504)) ([7e7889a](https://github.com/amzn/style-dictionary/commit/7e7889a41c79c58a04297762a31550c9bd7c2ee0)) -* **format:** use named parameters in formatter functions ([#533](https://github.com/amzn/style-dictionary/issues/533)) ([32bd40d](https://github.com/amzn/style-dictionary/commit/32bd40d3a94dd3be49ea795e3dbcc70e149bd6eb)) -* react-native support ([#512](https://github.com/amzn/style-dictionary/issues/512)) ([bd61cd2](https://github.com/amzn/style-dictionary/commit/bd61cd294afccd5299a7103fd2ea6177203e9994)) - +- **build-file:** do not generate file if properties is empty ([#494](https://github.com/amzn/style-dictionary/issues/494)) ([8945c46](https://github.com/amzn/style-dictionary/commit/8945c46f26a08ff6ffac3a5aa0e84a0f330efdb4)) +- **format:** output references ([#504](https://github.com/amzn/style-dictionary/issues/504)) ([7e7889a](https://github.com/amzn/style-dictionary/commit/7e7889a41c79c58a04297762a31550c9bd7c2ee0)) +- **format:** use named parameters in formatter functions ([#533](https://github.com/amzn/style-dictionary/issues/533)) ([32bd40d](https://github.com/amzn/style-dictionary/commit/32bd40d3a94dd3be49ea795e3dbcc70e149bd6eb)) +- react-native support ([#512](https://github.com/amzn/style-dictionary/issues/512)) ([bd61cd2](https://github.com/amzn/style-dictionary/commit/bd61cd294afccd5299a7103fd2ea6177203e9994)) ### Bug Fixes -* **examples:** little typo ([#518](https://github.com/amzn/style-dictionary/issues/518)) ([33271b6](https://github.com/amzn/style-dictionary/commit/33271b62b2a0c100a2be8c08f7cd89815e287327)) -* **export platform:** fixing infinite loop when there are reference errors ([#531](https://github.com/amzn/style-dictionary/issues/531)) ([6078c80](https://github.com/amzn/style-dictionary/commit/6078c8041286589eef7515945f771240bf73c8ef)) -* **property setup:** original property being mutated if the value is an object ([#534](https://github.com/amzn/style-dictionary/issues/534)) ([0b13ae2](https://github.com/amzn/style-dictionary/commit/0b13ae212023ba003ab71cc30eadb20ad10ebc0c)) -* **types:** add transitive to value transform type ([#536](https://github.com/amzn/style-dictionary/issues/536)) ([695eed6](https://github.com/amzn/style-dictionary/commit/695eed60f9f56c30542bbec8d0c1622a6a6959df)) -* **types:** Change transforms to transform in Core ([#530](https://github.com/amzn/style-dictionary/issues/530)) ([40a2601](https://github.com/amzn/style-dictionary/commit/40a2601724ed947aa141ff53e874c14c317992df)) +- **examples:** little typo ([#518](https://github.com/amzn/style-dictionary/issues/518)) ([33271b6](https://github.com/amzn/style-dictionary/commit/33271b62b2a0c100a2be8c08f7cd89815e287327)) +- **export platform:** fixing infinite loop when there are reference errors ([#531](https://github.com/amzn/style-dictionary/issues/531)) ([6078c80](https://github.com/amzn/style-dictionary/commit/6078c8041286589eef7515945f771240bf73c8ef)) +- **property setup:** original property being mutated if the value is an object ([#534](https://github.com/amzn/style-dictionary/issues/534)) ([0b13ae2](https://github.com/amzn/style-dictionary/commit/0b13ae212023ba003ab71cc30eadb20ad10ebc0c)) +- **types:** add transitive to value transform type ([#536](https://github.com/amzn/style-dictionary/issues/536)) ([695eed6](https://github.com/amzn/style-dictionary/commit/695eed60f9f56c30542bbec8d0c1622a6a6959df)) +- **types:** Change transforms to transform in Core ([#530](https://github.com/amzn/style-dictionary/issues/530)) ([40a2601](https://github.com/amzn/style-dictionary/commit/40a2601724ed947aa141ff53e874c14c317992df)) ## [3.0.0-rc.2](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.1...v3.0.0-rc.2) (2021-01-12) - ### Features -* **format:** adding android/resources format ([e43aafd](https://github.com/amzn/style-dictionary/commit/e43aafd0e4c5f34158ea0cdc222833b79b35ab16)) -* **transforms:** add 'px to rem' transform ([#491](https://github.com/amzn/style-dictionary/issues/491)) ([75f0ba3](https://github.com/amzn/style-dictionary/commit/75f0ba36e1211edf955c7b6bd6c58cbd9fc6524c)) - +- **format:** adding android/resources format ([e43aafd](https://github.com/amzn/style-dictionary/commit/e43aafd0e4c5f34158ea0cdc222833b79b35ab16)) +- **transforms:** add 'px to rem' transform ([#491](https://github.com/amzn/style-dictionary/issues/491)) ([75f0ba3](https://github.com/amzn/style-dictionary/commit/75f0ba36e1211edf955c7b6bd6c58cbd9fc6524c)) ### Bug Fixes -* **extend:** use given file path for token data ([#499](https://github.com/amzn/style-dictionary/issues/499)) ([0b23c9d](https://github.com/amzn/style-dictionary/commit/0b23c9d77e367b2080e4b624fcb294773b2aefcb)) -* **parsers:** fixed an error where parsers weren't running ([#511](https://github.com/amzn/style-dictionary/issues/511)) ([b0077c3](https://github.com/amzn/style-dictionary/commit/b0077c3d06caf5b7fcacd7378aab7827cdaa3961)) -* **types:** fix transform options type [#502](https://github.com/amzn/style-dictionary/issues/502) ([32787f8](https://github.com/amzn/style-dictionary/commit/32787f8a133a61f6132cef4bb88922f72951b804)) +- **extend:** use given file path for token data ([#499](https://github.com/amzn/style-dictionary/issues/499)) ([0b23c9d](https://github.com/amzn/style-dictionary/commit/0b23c9d77e367b2080e4b624fcb294773b2aefcb)) +- **parsers:** fixed an error where parsers weren't running ([#511](https://github.com/amzn/style-dictionary/issues/511)) ([b0077c3](https://github.com/amzn/style-dictionary/commit/b0077c3d06caf5b7fcacd7378aab7827cdaa3961)) +- **types:** fix transform options type [#502](https://github.com/amzn/style-dictionary/issues/502) ([32787f8](https://github.com/amzn/style-dictionary/commit/32787f8a133a61f6132cef4bb88922f72951b804)) ## [3.0.0-rc.1](https://github.com/amzn/style-dictionary/compare/v3.0.0-rc.0...v3.0.0-rc.1) (2020-12-04) ## [3.0.0-rc.0](https://github.com/amzn/style-dictionary/compare/v2.10.2...v3.0.0-rc.0) (2020-12-03) - ### Features -* **examples:** add custom filters example ([c9bfcbc](https://github.com/amzn/style-dictionary/commit/c9bfcbcb07fec4435f2368c66d0db793d676a06e)) -* **examples:** add custom filters example ([f95c420](https://github.com/amzn/style-dictionary/commit/f95c4202e93dcc00b47e595c4910f435a57d1987)) -* **examples:** add matching build files example ([#481](https://github.com/amzn/style-dictionary/issues/481)) ([5a80ef6](https://github.com/amzn/style-dictionary/commit/5a80ef626bacb6b487f2543793e7ed6451e81498)), closes [#251](https://github.com/amzn/style-dictionary/issues/251) -* add support for !default in SCSS variables format ([#359](https://github.com/amzn/style-dictionary/issues/359)) ([fa82002](https://github.com/amzn/style-dictionary/commit/fa8200221477a7bf0d9fcb031a54dc61ba2e3f72)), closes [#307](https://github.com/amzn/style-dictionary/issues/307) -* add TypeScript typings ([#410](https://github.com/amzn/style-dictionary/issues/410)) ([a8bb832](https://github.com/amzn/style-dictionary/commit/a8bb83278fa5bf7b1796d7f466f21a7beef0da84)) -* **core:** add new entries on property object ([#356](https://github.com/amzn/style-dictionary/issues/356)) ([fd254a5](https://github.com/amzn/style-dictionary/commit/fd254a5e9f78b9888cf59770e61800357421d934)) -* **formats:** add file object to formatter method ([#439](https://github.com/amzn/style-dictionary/issues/439)) ([1481c46](https://github.com/amzn/style-dictionary/commit/1481c46647808d95dc26ff6c08a0906df09d0316)) -* **formats:** javascript/module-flat format ([#457](https://github.com/amzn/style-dictionary/issues/457)) ([37b06e8](https://github.com/amzn/style-dictionary/commit/37b06e86ba77576fb0619372fd73e16673c6440d)) -* **parser:** adding custom parser support ([#429](https://github.com/amzn/style-dictionary/issues/429)) ([887a837](https://github.com/amzn/style-dictionary/commit/887a837a72f15cb4e2550f883e6d4479e1fa9d42)) -* **transforms:** Make transitive transforms & resolves possible ([#371](https://github.com/amzn/style-dictionary/issues/371)) ([3edbb17](https://github.com/amzn/style-dictionary/commit/3edbb178d53f9e5af2328b7c26271fe436af86d3)), closes [#208](https://github.com/amzn/style-dictionary/issues/208) +- **examples:** add custom filters example ([c9bfcbc](https://github.com/amzn/style-dictionary/commit/c9bfcbcb07fec4435f2368c66d0db793d676a06e)) +- **examples:** add custom filters example ([f95c420](https://github.com/amzn/style-dictionary/commit/f95c4202e93dcc00b47e595c4910f435a57d1987)) +- **examples:** add matching build files example ([#481](https://github.com/amzn/style-dictionary/issues/481)) ([5a80ef6](https://github.com/amzn/style-dictionary/commit/5a80ef626bacb6b487f2543793e7ed6451e81498)), closes [#251](https://github.com/amzn/style-dictionary/issues/251) +- add support for !default in SCSS variables format ([#359](https://github.com/amzn/style-dictionary/issues/359)) ([fa82002](https://github.com/amzn/style-dictionary/commit/fa8200221477a7bf0d9fcb031a54dc61ba2e3f72)), closes [#307](https://github.com/amzn/style-dictionary/issues/307) +- add TypeScript typings ([#410](https://github.com/amzn/style-dictionary/issues/410)) ([a8bb832](https://github.com/amzn/style-dictionary/commit/a8bb83278fa5bf7b1796d7f466f21a7beef0da84)) +- **core:** add new entries on property object ([#356](https://github.com/amzn/style-dictionary/issues/356)) ([fd254a5](https://github.com/amzn/style-dictionary/commit/fd254a5e9f78b9888cf59770e61800357421d934)) +- **formats:** add file object to formatter method ([#439](https://github.com/amzn/style-dictionary/issues/439)) ([1481c46](https://github.com/amzn/style-dictionary/commit/1481c46647808d95dc26ff6c08a0906df09d0316)) +- **formats:** javascript/module-flat format ([#457](https://github.com/amzn/style-dictionary/issues/457)) ([37b06e8](https://github.com/amzn/style-dictionary/commit/37b06e86ba77576fb0619372fd73e16673c6440d)) +- **parser:** adding custom parser support ([#429](https://github.com/amzn/style-dictionary/issues/429)) ([887a837](https://github.com/amzn/style-dictionary/commit/887a837a72f15cb4e2550f883e6d4479e1fa9d42)) +- **transforms:** Make transitive transforms & resolves possible ([#371](https://github.com/amzn/style-dictionary/issues/371)) ([3edbb17](https://github.com/amzn/style-dictionary/commit/3edbb178d53f9e5af2328b7c26271fe436af86d3)), closes [#208](https://github.com/amzn/style-dictionary/issues/208) ### Bug Fixes -* **cli:** update clean config path logic ([#454](https://github.com/amzn/style-dictionary/issues/454)) ([dc3cfa5](https://github.com/amzn/style-dictionary/commit/dc3cfa58aa7cc78a6359a8bb269e6f32ba50b110)) -* **formats:** fix max call stack issue on json/nested format ([#465](https://github.com/amzn/style-dictionary/issues/465)) ([67fb361](https://github.com/amzn/style-dictionary/commit/67fb361fb2448f9b91a1a125ee61d6bbe2f77732)) -* **transforms:** fix transitive transforms ([#476](https://github.com/amzn/style-dictionary/issues/476)) ([ac0c515](https://github.com/amzn/style-dictionary/commit/ac0c515c8b4593b91eb352b1f744895796e3ab49)) +- **cli:** update clean config path logic ([#454](https://github.com/amzn/style-dictionary/issues/454)) ([dc3cfa5](https://github.com/amzn/style-dictionary/commit/dc3cfa58aa7cc78a6359a8bb269e6f32ba50b110)) +- **formats:** fix max call stack issue on json/nested format ([#465](https://github.com/amzn/style-dictionary/issues/465)) ([67fb361](https://github.com/amzn/style-dictionary/commit/67fb361fb2448f9b91a1a125ee61d6bbe2f77732)) +- **transforms:** fix transitive transforms ([#476](https://github.com/amzn/style-dictionary/issues/476)) ([ac0c515](https://github.com/amzn/style-dictionary/commit/ac0c515c8b4593b91eb352b1f744895796e3ab49)) ### [2.10.3](https://github.com/amzn/style-dictionary/compare/v2.10.2...v2.10.3) (2021-03-09) - ### Bug Fixes -* **extend:** remove prototype pollution ([#560](https://github.com/amzn/style-dictionary/issues/560)) ([89ee39a](https://github.com/amzn/style-dictionary/commit/89ee39a7953c1825ea4578d43f129e23b4ed5da8)) - +- **extend:** remove prototype pollution ([#560](https://github.com/amzn/style-dictionary/issues/560)) ([89ee39a](https://github.com/amzn/style-dictionary/commit/89ee39a7953c1825ea4578d43f129e23b4ed5da8)) ### [2.10.2](https://github.com/amzn/style-dictionary/compare/v2.10.1...v2.10.2) (2020-10-08) - ### Bug Fixes -* **cli:** update clean config path logic ([#454](https://github.com/amzn/style-dictionary/issues/454)) ([3cc3d4e](https://github.com/amzn/style-dictionary/commit/3cc3d4e04f2ee4d0ac8b1f90b725e80f6b53beb4)) -* **formats:** fix max call stack issue on json/nested format ([#465](https://github.com/amzn/style-dictionary/issues/465)) ([4064e6a](https://github.com/amzn/style-dictionary/commit/4064e6add00ca3380d9a2c9ef9862f73ef051de9)) +- **cli:** update clean config path logic ([#454](https://github.com/amzn/style-dictionary/issues/454)) ([3cc3d4e](https://github.com/amzn/style-dictionary/commit/3cc3d4e04f2ee4d0ac8b1f90b725e80f6b53beb4)) +- **formats:** fix max call stack issue on json/nested format ([#465](https://github.com/amzn/style-dictionary/issues/465)) ([4064e6a](https://github.com/amzn/style-dictionary/commit/4064e6add00ca3380d9a2c9ef9862f73ef051de9)) ### [2.10.1](https://github.com/amzn/style-dictionary/compare/v2.10.0...v2.10.1) (2020-07-09) - ### Bug Fixes -* **filter:** fix conditional to ensure we catch properties with a falsy value ([#423](https://github.com/amzn/style-dictionary/issues/423)) ([1ec4e74](https://github.com/amzn/style-dictionary/commit/1ec4e74b9b717208f7d64aa33d43774ae8023a23)), closes [#406](https://github.com/amzn/style-dictionary/issues/406) -* **formats:** align scss/map-* with scss/variables on asset category ([9d867ef](https://github.com/amzn/style-dictionary/commit/9d867ef3ad72cf68557434ce1a28ba996a5ac467)) +- **filter:** fix conditional to ensure we catch properties with a falsy value ([#423](https://github.com/amzn/style-dictionary/issues/423)) ([1ec4e74](https://github.com/amzn/style-dictionary/commit/1ec4e74b9b717208f7d64aa33d43774ae8023a23)), closes [#406](https://github.com/amzn/style-dictionary/issues/406) +- **formats:** align scss/map-\* with scss/variables on asset category ([9d867ef](https://github.com/amzn/style-dictionary/commit/9d867ef3ad72cf68557434ce1a28ba996a5ac467)) ## [2.10.0](https://github.com/amzn/style-dictionary/compare/v2.9.0...v2.10.0) (2020-05-05) - ### Features -* adding color/hsl and color/hsl-4 transforms ([#383](https://github.com/amzn/style-dictionary/issues/383)) ([b777cfb](https://github.com/amzn/style-dictionary/commit/b777cfb11e5edc32e61df2dd33909c37a7efe2e5)) -* flutter support ([#320](https://github.com/amzn/style-dictionary/issues/320)) ([8a5f645](https://github.com/amzn/style-dictionary/commit/8a5f645cc9e73fea9bbb8b6b38c5baa1d23149c8)), closes [#255](https://github.com/amzn/style-dictionary/issues/255) [#288](https://github.com/amzn/style-dictionary/issues/288) +- adding color/hsl and color/hsl-4 transforms ([#383](https://github.com/amzn/style-dictionary/issues/383)) ([b777cfb](https://github.com/amzn/style-dictionary/commit/b777cfb11e5edc32e61df2dd33909c37a7efe2e5)) +- flutter support ([#320](https://github.com/amzn/style-dictionary/issues/320)) ([8a5f645](https://github.com/amzn/style-dictionary/commit/8a5f645cc9e73fea9bbb8b6b38c5baa1d23149c8)), closes [#255](https://github.com/amzn/style-dictionary/issues/255) [#288](https://github.com/amzn/style-dictionary/issues/288) -# [2.9.0](https://github.com/amzn/style-dictionary/compare/v2.8.3...v2.9.0) (2020-04-21) +# [2.9.0](https://github.com/amzn/style-dictionary/compare/v2.8.3...v2.9.0) (2020-04-21) ### Bug Fixes -* **transforms:** add NaN check to all size transforms ([#413](https://github.com/amzn/style-dictionary/issues/413)) ([d353795](https://github.com/amzn/style-dictionary/commit/d353795)) -* **transforms:** add specificity so color for hex values is correct ([#412](https://github.com/amzn/style-dictionary/issues/412)) ([01cc11c](https://github.com/amzn/style-dictionary/commit/01cc11c)), closes [#407](https://github.com/amzn/style-dictionary/issues/407) -* clean require cache before loading file content ([#405](https://github.com/amzn/style-dictionary/issues/405)) ([18a50d0](https://github.com/amzn/style-dictionary/commit/18a50d0)), closes [#404](https://github.com/amzn/style-dictionary/issues/404) -* parseFloat() has only one argument ([#417](https://github.com/amzn/style-dictionary/issues/417)) ([16c3040](https://github.com/amzn/style-dictionary/commit/16c3040)), closes [#416](https://github.com/amzn/style-dictionary/issues/416) - +- **transforms:** add NaN check to all size transforms ([#413](https://github.com/amzn/style-dictionary/issues/413)) ([d353795](https://github.com/amzn/style-dictionary/commit/d353795)) +- **transforms:** add specificity so color for hex values is correct ([#412](https://github.com/amzn/style-dictionary/issues/412)) ([01cc11c](https://github.com/amzn/style-dictionary/commit/01cc11c)), closes [#407](https://github.com/amzn/style-dictionary/issues/407) +- clean require cache before loading file content ([#405](https://github.com/amzn/style-dictionary/issues/405)) ([18a50d0](https://github.com/amzn/style-dictionary/commit/18a50d0)), closes [#404](https://github.com/amzn/style-dictionary/issues/404) +- parseFloat() has only one argument ([#417](https://github.com/amzn/style-dictionary/issues/417)) ([16c3040](https://github.com/amzn/style-dictionary/commit/16c3040)), closes [#416](https://github.com/amzn/style-dictionary/issues/416) ### Features -* **attribute/cti:** attribute/cti should respect manually set attributes ([#415](https://github.com/amzn/style-dictionary/issues/415)) ([fb3e393](https://github.com/amzn/style-dictionary/commit/fb3e393)), closes [#414](https://github.com/amzn/style-dictionary/issues/414) - - +- **attribute/cti:** attribute/cti should respect manually set attributes ([#415](https://github.com/amzn/style-dictionary/issues/415)) ([fb3e393](https://github.com/amzn/style-dictionary/commit/fb3e393)), closes [#414](https://github.com/amzn/style-dictionary/issues/414) -## [2.8.3](https://github.com/amzn/style-dictionary/compare/v2.8.2...v2.8.3) (2019-10-30) +## [2.8.3](https://github.com/amzn/style-dictionary/compare/v2.8.2...v2.8.3) (2019-10-30) ### Bug Fixes -* **format:** minor css format output fix ([#323](https://github.com/amzn/style-dictionary/issues/323)) ([adb94e1](https://github.com/amzn/style-dictionary/commit/adb94e1)), closes [#322](https://github.com/amzn/style-dictionary/issues/322) -* **utils:** handle 0 values ([#325](https://github.com/amzn/style-dictionary/issues/325)) ([189d61b](https://github.com/amzn/style-dictionary/commit/189d61b)), closes [#324](https://github.com/amzn/style-dictionary/issues/324) - - +- **format:** minor css format output fix ([#323](https://github.com/amzn/style-dictionary/issues/323)) ([adb94e1](https://github.com/amzn/style-dictionary/commit/adb94e1)), closes [#322](https://github.com/amzn/style-dictionary/issues/322) +- **utils:** handle 0 values ([#325](https://github.com/amzn/style-dictionary/issues/325)) ([189d61b](https://github.com/amzn/style-dictionary/commit/189d61b)), closes [#324](https://github.com/amzn/style-dictionary/issues/324) -## [2.8.2](https://github.com/amzn/style-dictionary/compare/v2.8.1...v2.8.2) (2019-09-04) +## [2.8.2](https://github.com/amzn/style-dictionary/compare/v2.8.1...v2.8.2) (2019-09-04) ### Bug Fixes -* **format:** issue [#295](https://github.com/amzn/style-dictionary/issues/295) ([c654648](https://github.com/amzn/style-dictionary/commit/c654648)) -* **format:** issue [#295](https://github.com/amzn/style-dictionary/issues/295) ([#316](https://github.com/amzn/style-dictionary/issues/316)) ([030175e](https://github.com/amzn/style-dictionary/commit/030175e)) -* **formats:** change less and scss comments to short version ([#306](https://github.com/amzn/style-dictionary/issues/306)) ([4f13f57](https://github.com/amzn/style-dictionary/commit/4f13f57)), closes [#305](https://github.com/amzn/style-dictionary/issues/305) -* **transform:** increase uicolor to 3 decimals to retain 8bit precision ([#314](https://github.com/amzn/style-dictionary/issues/314)) ([a3bde96](https://github.com/amzn/style-dictionary/commit/a3bde96)) - - +- **format:** issue [#295](https://github.com/amzn/style-dictionary/issues/295) ([c654648](https://github.com/amzn/style-dictionary/commit/c654648)) +- **format:** issue [#295](https://github.com/amzn/style-dictionary/issues/295) ([#316](https://github.com/amzn/style-dictionary/issues/316)) ([030175e](https://github.com/amzn/style-dictionary/commit/030175e)) +- **formats:** change less and scss comments to short version ([#306](https://github.com/amzn/style-dictionary/issues/306)) ([4f13f57](https://github.com/amzn/style-dictionary/commit/4f13f57)), closes [#305](https://github.com/amzn/style-dictionary/issues/305) +- **transform:** increase uicolor to 3 decimals to retain 8bit precision ([#314](https://github.com/amzn/style-dictionary/issues/314)) ([a3bde96](https://github.com/amzn/style-dictionary/commit/a3bde96)) -## [2.8.1](https://github.com/amzn/style-dictionary/compare/v2.8.0...v2.8.1) (2019-07-02) +## [2.8.1](https://github.com/amzn/style-dictionary/compare/v2.8.0...v2.8.1) (2019-07-02) ### Bug Fixes -* **format:** adding configurable name to sass map name ([#291](https://github.com/amzn/style-dictionary/issues/291)) ([cfa2422](https://github.com/amzn/style-dictionary/commit/cfa2422)), closes [#290](https://github.com/amzn/style-dictionary/issues/290) -* **sketch:** fix sketch palette format to use new filters ([#287](https://github.com/amzn/style-dictionary/issues/287)) ([374012c](https://github.com/amzn/style-dictionary/commit/374012c)), closes [#285](https://github.com/amzn/style-dictionary/issues/285) - - +- **format:** adding configurable name to sass map name ([#291](https://github.com/amzn/style-dictionary/issues/291)) ([cfa2422](https://github.com/amzn/style-dictionary/commit/cfa2422)), closes [#290](https://github.com/amzn/style-dictionary/issues/290) +- **sketch:** fix sketch palette format to use new filters ([#287](https://github.com/amzn/style-dictionary/issues/287)) ([374012c](https://github.com/amzn/style-dictionary/commit/374012c)), closes [#285](https://github.com/amzn/style-dictionary/issues/285) -# [2.8.0](https://github.com/amzn/style-dictionary/compare/v2.7.0...v2.8.0) (2019-05-28) +# [2.8.0](https://github.com/amzn/style-dictionary/compare/v2.7.0...v2.8.0) (2019-05-28) ### Bug Fixes -* **cleanfile:** add file check and log for non-existent file ([#277](https://github.com/amzn/style-dictionary/issues/277)) ([6375133](https://github.com/amzn/style-dictionary/commit/6375133)) -* **docs/examples:** 404 errors and typos ([#269](https://github.com/amzn/style-dictionary/issues/269)) ([da369da](https://github.com/amzn/style-dictionary/commit/da369da)) -* **error-messaging:** add better error messaging when a transform or transformGroup does not exist ([#264](https://github.com/amzn/style-dictionary/issues/264)) ([d5c0583](https://github.com/amzn/style-dictionary/commit/d5c0583)) -* **extend:** multiple extensions properly deep merge ([#276](https://github.com/amzn/style-dictionary/issues/276)) ([f1d6bb0](https://github.com/amzn/style-dictionary/commit/f1d6bb0)), closes [#274](https://github.com/amzn/style-dictionary/issues/274) -* accidentally generating test output in root directory ([4994553](https://github.com/amzn/style-dictionary/commit/4994553)) - +- **cleanfile:** add file check and log for non-existent file ([#277](https://github.com/amzn/style-dictionary/issues/277)) ([6375133](https://github.com/amzn/style-dictionary/commit/6375133)) +- **docs/examples:** 404 errors and typos ([#269](https://github.com/amzn/style-dictionary/issues/269)) ([da369da](https://github.com/amzn/style-dictionary/commit/da369da)) +- **error-messaging:** add better error messaging when a transform or transformGroup does not exist ([#264](https://github.com/amzn/style-dictionary/issues/264)) ([d5c0583](https://github.com/amzn/style-dictionary/commit/d5c0583)) +- **extend:** multiple extensions properly deep merge ([#276](https://github.com/amzn/style-dictionary/issues/276)) ([f1d6bb0](https://github.com/amzn/style-dictionary/commit/f1d6bb0)), closes [#274](https://github.com/amzn/style-dictionary/issues/274) +- accidentally generating test output in root directory ([4994553](https://github.com/amzn/style-dictionary/commit/4994553)) ### Features -* **config:** use config.js if config.json is not found ([#249](https://github.com/amzn/style-dictionary/issues/249)) ([09fc43f](https://github.com/amzn/style-dictionary/commit/09fc43f)), closes [#238](https://github.com/amzn/style-dictionary/issues/238) [#238](https://github.com/amzn/style-dictionary/issues/238) [#247](https://github.com/amzn/style-dictionary/issues/247) -* add automatic changelog generation ([#225](https://github.com/amzn/style-dictionary/issues/225)) ([b062008](https://github.com/amzn/style-dictionary/commit/b062008)) -* **docs:** adding PR and download badges; fixing code coverage badge ([#270](https://github.com/amzn/style-dictionary/issues/270)) ([2307a44](https://github.com/amzn/style-dictionary/commit/2307a44)), closes [#265](https://github.com/amzn/style-dictionary/issues/265) -* **ios-swift:** adding common transforms for Swift in iOS ([#255](https://github.com/amzn/style-dictionary/issues/255)) ([749db69](https://github.com/amzn/style-dictionary/commit/749db69)), closes [#161](https://github.com/amzn/style-dictionary/issues/161) -* **transforms:** Add UIColor transform for swift ([#250](https://github.com/amzn/style-dictionary/issues/250)) ([a62d880](https://github.com/amzn/style-dictionary/commit/a62d880)), closes [#161](https://github.com/amzn/style-dictionary/issues/161) -* **warning:** catch property name collisions during file output ([#273](https://github.com/amzn/style-dictionary/issues/273)) ([9a40407](https://github.com/amzn/style-dictionary/commit/9a40407)) +- **config:** use config.js if config.json is not found ([#249](https://github.com/amzn/style-dictionary/issues/249)) ([09fc43f](https://github.com/amzn/style-dictionary/commit/09fc43f)), closes [#238](https://github.com/amzn/style-dictionary/issues/238) [#238](https://github.com/amzn/style-dictionary/issues/238) [#247](https://github.com/amzn/style-dictionary/issues/247) +- add automatic changelog generation ([#225](https://github.com/amzn/style-dictionary/issues/225)) ([b062008](https://github.com/amzn/style-dictionary/commit/b062008)) +- **docs:** adding PR and download badges; fixing code coverage badge ([#270](https://github.com/amzn/style-dictionary/issues/270)) ([2307a44](https://github.com/amzn/style-dictionary/commit/2307a44)), closes [#265](https://github.com/amzn/style-dictionary/issues/265) +- **ios-swift:** adding common transforms for Swift in iOS ([#255](https://github.com/amzn/style-dictionary/issues/255)) ([749db69](https://github.com/amzn/style-dictionary/commit/749db69)), closes [#161](https://github.com/amzn/style-dictionary/issues/161) +- **transforms:** Add UIColor transform for swift ([#250](https://github.com/amzn/style-dictionary/issues/250)) ([a62d880](https://github.com/amzn/style-dictionary/commit/a62d880)), closes [#161](https://github.com/amzn/style-dictionary/issues/161) +- **warning:** catch property name collisions during file output ([#273](https://github.com/amzn/style-dictionary/issues/273)) ([9a40407](https://github.com/amzn/style-dictionary/commit/9a40407)) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d54e6feb6..fb6169495 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4bdb1f771..4728beb5b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,6 @@ This is a labor of love, and we work hard to provide a useful framework. We greatly value feedback and contributions from our community. Whether it's a bug report, new feature, correction, or additional documentation, we welcome your issues and pull requests. Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. - ## Filing Bug Reports You can file bug reports on the [GitHub issues][issues] page. @@ -14,7 +13,6 @@ If you are filing a report for a bug or regression in the framework, it's extrem 3. Provide as much information about your environment, npm version, and relevant dependencies as possible. For example, let us know what version of Node.js you are using, what other node modules, what ES version, etc. If possible, send us a github repository we can take a look at. 4. Provide a minimal test case that reproduces your issue or any error information you related to your problem. We can provide feedback much more quickly if we know what operations you are calling in the framework. If you cannot provide a full test case, provide as much code as you can to help us diagnose the problem. Any relevant information should be provided as well, like whether this is a persistent issue, or if it only occurs some of the time. - ## Submitting Pull Requests We are always happy to receive code and documentation contributions to the framework. Please be aware of the following notes prior to opening a pull request: @@ -23,23 +21,23 @@ We are always happy to receive code and documentation contributions to the frame 2. For any significant features or API changes please reach out to us to avoid any duplicate effort. 3. Adding to the included transforms, transformGroups, and formats, please read [this section](#what-should-be-included). - ## Package Manager and dependencies We use npm as our package manager. After downloading the repo, please use the command "npm ci" to ensure you use the package-lock dependency tree. Note that you need NPM 5.7.0 or higher to use this command. - ## Code Style We use ESLint on the code to ensure a consistent style. Any new code committed must pass our ESLint tests. Take a look at our [ESLint file][eslint]. ### Code Rules -1. **Do not mutate token names or values in a format.** Mutations like this should happen in a transformer. + +1. **Do not mutate token names or values in a format.** Mutations like this should happen in a transform. 1. **Be as generic as possible.** Do not hard-code any values or configuration in formats. 1. **Fail loudly.** Users should be aware if something is missing or configurations aren't correct. This will help debug any issues instead of failing silently. 1. **Rely on few dependencies.** This framework is meant to be extended and allows for customization. We don't want to bring a slew of dependencies that most people don't need. ### Commit Rules + We follow [conventional commits'](https://www.conventionalcommits.org/en/v1.0.0-beta.2/#specification) specification. Please follow the spec to have a successful commit. @@ -56,32 +54,17 @@ If it has a generic and flexible enough use-case, it can be included. We would l We separate each function/method into its own file and group them into directories. The times we break that is for transforms and formats, but we might change that in the future. Keep the files/methods as self-contained as possible, they should each do one task. - ## Testing Any new features should implement the proper unit tests. We use Jest to test our framework. -If you are adding a new transform, action, or format: please add new unit tests. You can see examples in test/formats. +If you are adding a new transform, action, or format: please add new unit tests. You can see examples in **\_\_tests\_\_**/formats. ## Documentation -We use [JSDoc](http://usejsdoc.org) comments in all of the code, including built-in formats and transforms, to document all of the functionality of Style Dictionary. If you are adding a new function or changing how something works, please update the JSDoc comments. - -We use [jsdoc-to-markdown](https://github.com/jsdoc2md/jsdoc-to-markdown) to create markdown files based on JSDoc comments in the code. These markdown files get generated in the docs/ directory. To see what is happening, take a look at [scripts/generateDocs.js](scripts/generateDocs.js). This file is run when the npm script `generate-docs` is run, which happens whenever we do an npm release. This script generates: - * docs/actions.md - * docs/api.md - * docs/formats.md - * docs/transform_groups.md - * docs/transforms.md - -Each of these files uses a handlebars template in scripts/handlebars/templates and jsdoc-to-markdown to generate the respective markdown file. - -There are other markdown files in the [docs/](docs/) directory that are plain markdown files. You can edit any of those like normal. - -We use [docsify](https://docsify.js.org/#/) to transform the markdown files into a documentation website. To preview it locally, run `npm run serve-docs`. +We use [Astro](https://astro.build/) to transform the markdown files into a documentation website. To preview it locally, run `npm run docs:start`. [issues]: https://github.com/amzn/style-dictionary/issues -[pr]: https://github.com/amzn/style-dictionary/pulls [license]: https://github.com/amzn/style-dictionary/blob/main/LICENSE [cla]: http://en.wikipedia.org/wiki/Contributor_License_Agreement [eslint]: https://github.com/amzn/style-dictionary/blob/main/.eslintrc.json diff --git a/README.md b/README.md index e4918d9e5..201873000 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ [![downloads](https://img.shields.io/npm/dm/style-dictionary.svg?style=flat-square)](https://www.npmjs.com/package/style-dictionary) # Style Dictionary -> *Style once, use everywhere.* + +> _Style once, use everywhere._ A Style Dictionary uses design tokens to define styles once and use those styles on any platform or language. It provides a single place to create and edit your styles, and exports these tokens to all the places you need - iOS, Android, CSS, JS, HTML, sketch files, style documentation, etc. It is available as a CLI through npm, but can also be used like any normal node module if you want to extend its functionality. @@ -20,56 +21,67 @@ When you are managing user experiences, it can be quite challenging to keep styl For detailed usage head to https://amzn.github.io/style-dictionary ## Watch the Demo on YouTube + [![Watch the video](/docs/assets/fake_player.png)](http://youtu.be/1HREvonfqhY) ## Experiment in the playground + Try the browser-based Style Dictionary playground: [https://www.style-dictionary-play.dev/](https://www.style-dictionary-play.dev/), built by the folks at [\RIOTS](https://divriots.com/). ## Contents -* [Installation](#installation) -* [Usage](#usage) -* [Example](#example) -* [Quick Start](#quick-start) -* [Design Tokens](#design-tokens) -* [Extending](#extending) -* [Contributing](#contributing) -* [License](#license) +- [Installation](#installation) +- [Usage](#usage) +- [Example](#example) +- [Quick Start](#quick-start) +- [Design Tokens](#design-tokens) +- [Extending](#extending) +- [Contributing](#contributing) +- [License](#license) ## Installation -*Note that you must have node (and npm) installed.* + +_Note that you must have node (and npm) installed._ If you want to use the CLI, you can install it globally via npm: + ```bash $ npm install -g style-dictionary ``` Or you can install it like a normal npm dependency. This is a build tool and you are most likely going to want to save it as a dev dependency: + ```bash $ npm install -D style-dictionary ``` If you want to install it with yarn: + ```bash $ yarn add style-dictionary --dev ``` ## Usage + ### CLI + ```bash $ style-dictionary build ``` + Call this in the root directory of your project. The only thing needed is a `config.json` file. There are also arguments: -| Flag | Short Flag | Description | -| --- | --- | --- | -| --config \[path\] | -c | Set the config file to use. Must be a .json file | -| --platform \[platform\] | -p | Only build a specific platform defined in the config file. | -| --help | -h | Display help content | -| --version | -v | Display the version | +| Flag | Short Flag | Description | +| ----------------------- | ---------- | ---------------------------------------------------------- | +| --config \[path\] | -c | Set the config file to use. Must be a .json file | +| --platform \[platform\] | -p | Only build a specific platform defined in the config file. | +| --help | -h | Display help content | +| --version | -v | Display the version | ### Node + You can also use the style dictionary build system in node if you want to [extend](#extending) the functionality or use it in another build system like Grunt or Gulp. + ```javascript const StyleDictionary = require('style-dictionary').extend('config.json'); @@ -77,6 +89,7 @@ StyleDictionary.buildAllPlatforms(); ``` The `.extend()` method is an overloaded method that can also take an object with the configuration in the same format as a config.json file. + ```javascript const StyleDictionary = require('style-dictionary').extend({ source: ['tokens/**/*.json'], @@ -84,19 +97,22 @@ const StyleDictionary = require('style-dictionary').extend({ scss: { transformGroup: 'scss', buildPath: 'build/', - files: [{ - destination: 'variables.scss', - format: 'scss/variables' - }] - } + files: [ + { + destination: 'variables.scss', + format: 'scss/variables', + }, + ], + }, // ... - } + }, }); StyleDictionary.buildAllPlatforms(); ``` ## Example + [Take a look at some of our examples](examples/) A style dictionary is a collection of design tokens, key/value pairs that describe stylistic attributes like colors, sizes, icons, motion, etc. A style dictionary defines these design tokens in JSON or Javascript files, and can also include static assets like images and fonts. Here is a basic example of what the package structure can look like: @@ -115,6 +131,7 @@ A style dictionary is a collection of design tokens, key/value pairs that descri ``` ### config.json + This tells the style dictionary build system how and what to build. The default file path is `config.json` or `config.js` in the root of the project, but you can name it whatever you want by passing in the `--config` flag to the [CLI](https://amzn.github.io/style-dictionary/#/using_the_cli). ```json @@ -124,36 +141,40 @@ This tells the style dictionary build system how and what to build. The default "scss": { "transformGroup": "scss", "buildPath": "build/", - "files": [{ - "destination": "scss/_variables.scss", - "format": "scss/variables" - }] + "files": [ + { + "destination": "scss/_variables.scss", + "format": "scss/variables" + } + ] }, "android": { "transformGroup": "android", "buildPath": "build/android/", - "files": [{ - "destination": "font_dimens.xml", - "format": "android/fontDimens" - }] + "files": [ + { + "destination": "font_dimens.xml", + "format": "android/fontDimens" + } + ] } } } ``` -| Attribute | Type | Description | -| :--- | :--- | :--- | -| source | Array | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files. Style Dictionary will do a deep merge of all of the token files, allowing you to organize your files files however you want. | -| include | Array | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files that contain default styles. The Style Dictionary uses this as a base collection of tokens. The tokens found using the "source" attribute will overwrite tokens found using include. | -| platforms | Object | Sets of platform files to be built. | -| platform.transformGroup | String (optional) | Apply a group of transforms to the tokens, must either define this or `transforms`. | -| platform.transforms | Array (optional) | Transforms to apply sequentially to all tokens. Can be a built-in one or you can create your own. | -| platform.buildPath | String (optional) | Base path to build the files, must end with a trailing slash. | -| platform.files | Array (optional) | Files to be generated for this platform. | -| platform.file.destination | String (optional) | Location to build the file, will be appended to the buildPath. | -| platform.file.format | String (optional) | Format used to generate the file. Can be a built-in one or you can create your own. [More on formats](https://amzn.github.io/style-dictionary/#/formats) | -| platform.file.options | Object (optional) | A set of extra options associated with the file. | -| platform.file.options.showFileHeader | Boolean | If the generated file should have a "Do not edit + Timestamp" header (where the format supports it). By default is "true". | +| Property | Type | Description | +| :----------------------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| source | Array | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files. Style Dictionary will do a deep merge of all of the token files, allowing you to organize your files files however you want. | +| include | Array | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files that contain default styles. The Style Dictionary uses this as a base collection of tokens. The tokens found using the "source" attribute will overwrite tokens found using include. | +| platforms | Object | Sets of platform files to be built. | +| platform.transformGroup | String (optional) | Apply a group of transforms to the tokens, must either define this or `transforms`. | +| platform.transforms | Array (optional) | Transforms to apply sequentially to all tokens. Can be a built-in one or you can create your own. | +| platform.buildPath | String (optional) | Base path to build the files, must end with a trailing slash. | +| platform.files | Array (optional) | Files to be generated for this platform. | +| platform.file.destination | String (optional) | Location to build the file, will be appended to the buildPath. | +| platform.file.format | String (optional) | Format used to generate the file. Can be a built-in one or you can create your own. [More on formats](https://amzn.github.io/style-dictionary/#/formats) | +| platform.file.options | Object (optional) | A set of extra options associated with the file. | +| platform.file.options.showFileHeader | Boolean | If the generated file should have a "Do not edit + Timestamp" header (where the format supports it). By default is "true". | ### Design Tokens @@ -161,10 +182,10 @@ This tells the style dictionary build system how and what to build. The default { "size": { "font": { - "small" : { "value": "10px" }, + "small": { "value": "10px" }, "medium": { "value": "16px" }, - "large" : { "value": "24px" }, - "base" : { "value": "{size.font.medium.value}" } + "large": { "value": "24px" }, + "base": { "value": "{size.font.medium.value}" } } } } @@ -195,7 +216,6 @@ float const SizeFontLarge = 24.00f; float const SizeFontBase = 16.00f; ``` - ## Quick Start The style dictionary framework comes with some example code to get you started. Install the node module globally, create a directory and `cd` into it. @@ -220,7 +240,6 @@ $ style-dictionary build Take a look at the documentation for the example code. - ## Design Tokens A design token is an attribute to describe something visually. It is atomic (it cannot be broken down further). Design tokens have a name, a value, and optional attributes or metadata. The name of a token can be anything, but we have a proposed naming structure that we find works really well in the next section. @@ -233,7 +252,7 @@ While not exactly necessary, we feel this classification structure of design tok { "size": { "font": { - "base": { "value": "16" }, + "base": { "value": "16" }, "large": { "value": "20" } } } @@ -254,7 +273,7 @@ You can also add a _comment_ to a design token: { "size": { "font": { - "base": { + "base": { "value": "16", "comment": "the base size of the font" }, @@ -267,8 +286,7 @@ You can also add a _comment_ to a design token: } ``` -The comment will appear in the output files, where relevant or the output format supports comments. - +The comment will appear in the output files, where relevant or the output format supports comments. ## Extending @@ -280,12 +298,12 @@ const StyleDictionary = require('style-dictionary').extend('config.json'); StyleDictionary.registerTransform({ name: 'time/seconds', type: 'value', - matcher: function(token) { - return token.attributes.category === 'time'; + filter: function (token) { + return token.type === 'time'; }, - transformer: function(token) { + transform: function (token) { return (parseInt(token.original.value) / 1000).toString() + 's'; - } + }, }); StyleDictionary.buildAllPlatforms(); @@ -303,7 +321,6 @@ The mascot for Style Dictionary is ["Pascal"](https://github.com/amzn/style-dict Please help make this framework better. For more information take a look at [CONTRIBUTING.md](CONTRIBUTING.md) - ## License [Apache 2.0](LICENSE) diff --git a/__integration__/README.md b/__integration__/README.md index f8d9415dd..bcdbe13e9 100644 --- a/__integration__/README.md +++ b/__integration__/README.md @@ -1,12 +1,12 @@ # Style Dictionary Integration Tests -Style Dictionary is a tool to generate valid source code for multiple platforms and languages to consume. Because of this, unit testing can only get us so far. Simply unit testing or even basic snapshot testing of outputs doesn't give the whole picture. +Style Dictionary is a tool to generate valid source code for multiple platforms and languages to consume. Because of this, unit testing can only get us so far. Simply unit testing or even basic snapshot testing of outputs doesn't give the whole picture. -The integration tests here are meant to show complete end-to-end examples of Style Dictionary being used in order to validate the files it is generating. +The integration tests here are meant to show complete end-to-end examples of Style Dictionary being used in order to validate the files it is generating. The integration tests still use Jest and snapshots, but rather than singling out format code, each test group builds a complete Style Dictionary and then tests the content of the output files with snapshots and validating syntax where possible. ## To do -* Jest snapshots are a good built-in way to test if content has changed, but storing the contents of a source code file like a CSS variables file doesn't get proper syntax highlighting and validation in IDEs. It would be better if we could store the raw output file and test against the new contents, but snapshot testing does not allow for that. -* Add more syntax validations \ No newline at end of file +- Jest snapshots are a good built-in way to test if content has changed, but storing the contents of a source code file like a CSS variables file doesn't get proper syntax highlighting and validation in IDEs. It would be better if we could store the raw output file and test against the new contents, but snapshot testing does not allow for that. +- Add more syntax validations diff --git a/__integration__/__snapshots__/android.test.js.snap b/__integration__/__snapshots__/android.test.js.snap deleted file mode 100644 index 8d8a33582..000000000 --- a/__integration__/__snapshots__/android.test.js.snap +++ /dev/null @@ -1,517 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration android android/resources should match snapshot 1`] = ` -" - - - - #ffffffff - #fff3f4f4 - #ffdee1e1 - #ffffeae9 - #ffffede3 - #ffebf9eb - #ffe9f8ff - #ffdee1e1 - #ffc8cccc - #ff0b8599 - #ff6f5ed3 - #ffebf9eb - #ffd7f4d7 - #ffc2f2bd - #ff98e58e - #ff75dd66 - #ff59cb59 - #ff2bb656 - #ff0ca750 - #ff008b46 - #ff006b40 - #ff08422f - #ff002b20 - #ffe5f9f5 - #ffcdf7ef - #ffb3f2e6 - #ff7dead5 - #ff24e0c5 - #ff08c4b2 - #ff00a99c - #ff0b968f - #ff067c7c - #ff026661 - #ff083f3f - #ff002528 - #ffd9fcfb - #ffc5f9f9 - #ffa5f2f2 - #ff76e5e2 - #ff33d6e2 - #ff17b8ce - #ff0797ae - #ff0b8599 - #ff0f6e84 - #ff035e73 - #ff083d4f - #ff002838 - #ffe9f8ff - #ffdcf2ff - #ffc7e4f9 - #ffa1d2f8 - #ff56adf5 - #ff3896e3 - #ff2b87d3 - #ff2079c3 - #ff116daa - #ff0c5689 - #ff0a3960 - #ff002138 - #fff2f2f9 - #ffeaeaf9 - #ffd8d7f9 - #ffc1c1f7 - #ffa193f2 - #ff9180f4 - #ff816fea - #ff6f5ed3 - #ff5e4eba - #ff483a9c - #ff2d246b - #ff1d1d38 - #fffef0ff - #fff9e3fc - #fff4c4f7 - #ffedadf2 - #fff282f5 - #ffdb61db - #ffc44eb9 - #ffac44a8 - #ff8f3896 - #ff6c2277 - #ff451551 - #ff29192d - #ffffe9f3 - #fffcdbeb - #ffffb5d5 - #ffff95c1 - #ffff76ae - #ffef588b - #ffe0447c - #ffce3665 - #ffb22f5b - #ff931847 - #ff561231 - #ff2b1721 - #ffffeae9 - #ffffd5d2 - #ffffb8b1 - #ffff9c8f - #ffff7f6e - #fff76054 - #ffed4c42 - #ffdb3e3e - #ffc63434 - #ff992222 - #ff6d1313 - #ff2b1111 - #ffffede3 - #fffcdccc - #ffffc6a4 - #ffffb180 - #ffff9c5d - #fffc8943 - #fff57d33 - #ffed7024 - #ffce5511 - #ff962c0b - #ff601700 - #ff2d130e - #ffffffff - #fff3f4f4 - #ffdee1e1 - #ffc8cccc - #ffb0b6b7 - #ff929a9b - #ff6e797a - #ff515e5f - #ff364141 - #ff273333 - #ff162020 - #ff040404 - #fffff8e2 - #fffdefcd - #ffffe99a - #ffffe16e - #ffffd943 - #ffffcd1c - #ffffbc00 - #ffdd9903 - #ffba7506 - #ff944c0c - #ff542a00 - #ff2d1a05 - #ff040404 - #ff273333 - #ff364141 - #ff0b8599 - #ff0b8599 - #ff6f5ed3 - #ff364141 - #ff6d1313 - #ff601700 - #ff08422f - 480.00dp - 12.00sp - 16.00sp - 24.00sp - 36.00sp - 8.00dp - 16.00dp - 16.00dp - 16.00dp - - -" -`; - -exports[`integration android android/resources with filter should match snapshot 1`] = ` -" - - - - #ffffffff - #fff3f4f4 - #ffdee1e1 - #ffffeae9 - #ffffede3 - #ffebf9eb - #ffe9f8ff - #ffdee1e1 - #ffc8cccc - #ff0b8599 - #ff6f5ed3 - #ffebf9eb - #ffd7f4d7 - #ffc2f2bd - #ff98e58e - #ff75dd66 - #ff59cb59 - #ff2bb656 - #ff0ca750 - #ff008b46 - #ff006b40 - #ff08422f - #ff002b20 - #ffe5f9f5 - #ffcdf7ef - #ffb3f2e6 - #ff7dead5 - #ff24e0c5 - #ff08c4b2 - #ff00a99c - #ff0b968f - #ff067c7c - #ff026661 - #ff083f3f - #ff002528 - #ffd9fcfb - #ffc5f9f9 - #ffa5f2f2 - #ff76e5e2 - #ff33d6e2 - #ff17b8ce - #ff0797ae - #ff0b8599 - #ff0f6e84 - #ff035e73 - #ff083d4f - #ff002838 - #ffe9f8ff - #ffdcf2ff - #ffc7e4f9 - #ffa1d2f8 - #ff56adf5 - #ff3896e3 - #ff2b87d3 - #ff2079c3 - #ff116daa - #ff0c5689 - #ff0a3960 - #ff002138 - #fff2f2f9 - #ffeaeaf9 - #ffd8d7f9 - #ffc1c1f7 - #ffa193f2 - #ff9180f4 - #ff816fea - #ff6f5ed3 - #ff5e4eba - #ff483a9c - #ff2d246b - #ff1d1d38 - #fffef0ff - #fff9e3fc - #fff4c4f7 - #ffedadf2 - #fff282f5 - #ffdb61db - #ffc44eb9 - #ffac44a8 - #ff8f3896 - #ff6c2277 - #ff451551 - #ff29192d - #ffffe9f3 - #fffcdbeb - #ffffb5d5 - #ffff95c1 - #ffff76ae - #ffef588b - #ffe0447c - #ffce3665 - #ffb22f5b - #ff931847 - #ff561231 - #ff2b1721 - #ffffeae9 - #ffffd5d2 - #ffffb8b1 - #ffff9c8f - #ffff7f6e - #fff76054 - #ffed4c42 - #ffdb3e3e - #ffc63434 - #ff992222 - #ff6d1313 - #ff2b1111 - #ffffede3 - #fffcdccc - #ffffc6a4 - #ffffb180 - #ffff9c5d - #fffc8943 - #fff57d33 - #ffed7024 - #ffce5511 - #ff962c0b - #ff601700 - #ff2d130e - #ffffffff - #fff3f4f4 - #ffdee1e1 - #ffc8cccc - #ffb0b6b7 - #ff929a9b - #ff6e797a - #ff515e5f - #ff364141 - #ff273333 - #ff162020 - #ff040404 - #fffff8e2 - #fffdefcd - #ffffe99a - #ffffe16e - #ffffd943 - #ffffcd1c - #ffffbc00 - #ffdd9903 - #ffba7506 - #ff944c0c - #ff542a00 - #ff2d1a05 - #ff040404 - #ff273333 - #ff364141 - #ff0b8599 - #ff0b8599 - #ff6f5ed3 - #ff364141 - #ff6d1313 - #ff601700 - #ff08422f - - -" -`; - -exports[`integration android android/resources with references should match snapshot 1`] = ` -" - - - - @color/color_core_neutral_0 - @color/color_core_neutral_100 - @color/color_core_neutral_200 - @color/color_core_red_0 - @color/color_core_orange_0 - @color/color_core_green_0 - @color/color_core_blue_0 - @color/color_background_tertiary - @color/color_core_neutral_300 - @color/color_core_aqua_700 - @color/color_core_purple_700 - #ffebf9eb - #ffd7f4d7 - #ffc2f2bd - #ff98e58e - #ff75dd66 - #ff59cb59 - #ff2bb656 - #ff0ca750 - #ff008b46 - #ff006b40 - #ff08422f - #ff002b20 - #ffe5f9f5 - #ffcdf7ef - #ffb3f2e6 - #ff7dead5 - #ff24e0c5 - #ff08c4b2 - #ff00a99c - #ff0b968f - #ff067c7c - #ff026661 - #ff083f3f - #ff002528 - #ffd9fcfb - #ffc5f9f9 - #ffa5f2f2 - #ff76e5e2 - #ff33d6e2 - #ff17b8ce - #ff0797ae - #ff0b8599 - #ff0f6e84 - #ff035e73 - #ff083d4f - #ff002838 - #ffe9f8ff - #ffdcf2ff - #ffc7e4f9 - #ffa1d2f8 - #ff56adf5 - #ff3896e3 - #ff2b87d3 - #ff2079c3 - #ff116daa - #ff0c5689 - #ff0a3960 - #ff002138 - #fff2f2f9 - #ffeaeaf9 - #ffd8d7f9 - #ffc1c1f7 - #ffa193f2 - #ff9180f4 - #ff816fea - #ff6f5ed3 - #ff5e4eba - #ff483a9c - #ff2d246b - #ff1d1d38 - #fffef0ff - #fff9e3fc - #fff4c4f7 - #ffedadf2 - #fff282f5 - #ffdb61db - #ffc44eb9 - #ffac44a8 - #ff8f3896 - #ff6c2277 - #ff451551 - #ff29192d - #ffffe9f3 - #fffcdbeb - #ffffb5d5 - #ffff95c1 - #ffff76ae - #ffef588b - #ffe0447c - #ffce3665 - #ffb22f5b - #ff931847 - #ff561231 - #ff2b1721 - #ffffeae9 - #ffffd5d2 - #ffffb8b1 - #ffff9c8f - #ffff7f6e - #fff76054 - #ffed4c42 - #ffdb3e3e - #ffc63434 - #ff992222 - #ff6d1313 - #ff2b1111 - #ffffede3 - #fffcdccc - #ffffc6a4 - #ffffb180 - #ffff9c5d - #fffc8943 - #fff57d33 - #ffed7024 - #ffce5511 - #ff962c0b - #ff601700 - #ff2d130e - #ffffffff - #fff3f4f4 - #ffdee1e1 - #ffc8cccc - #ffb0b6b7 - #ff929a9b - #ff6e797a - #ff515e5f - #ff364141 - #ff273333 - #ff162020 - #ff040404 - #fffff8e2 - #fffdefcd - #ffffe99a - #ffffe16e - #ffffd943 - #ffffcd1c - #ffffbc00 - #ffdd9903 - #ffba7506 - #ff944c0c - #ff542a00 - #ff2d1a05 - @color/color_core_neutral_1100 - @color/color_core_neutral_900 - @color/color_core_neutral_800 - @color/color_brand_primary - @color/color_brand_primary - @color/color_brand_secondary - @color/color_font_tertiary - @color/color_core_red_1000 - @color/color_core_orange_1000 - @color/color_core_green_1000 - 480.00dp - 12.00sp - 16.00sp - 24.00sp - 36.00sp - 8.00dp - 16.00dp - 16.00dp - 16.00dp - - -" -`; diff --git a/__integration__/__snapshots__/android.test.snap.js b/__integration__/__snapshots__/android.test.snap.js new file mode 100644 index 000000000..486edae29 --- /dev/null +++ b/__integration__/__snapshots__/android.test.snap.js @@ -0,0 +1,510 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration android android/resources should match snapshot"] = +` + + + + #ffffffff + #fff3f4f4 + #ffdee1e1 + #ffffeae9 + #ffffede3 + #ffebf9eb + #ffe9f8ff + #ffdee1e1 + #ffc8cccc + #ff0b8599 + #ff6f5ed3 + #ffebf9eb + #ffd7f4d7 + #ffc2f2bd + #ff98e58e + #ff75dd66 + #ff59cb59 + #ff2bb656 + #ff0ca750 + #ff008b46 + #ff006b40 + #ff08422f + #ff002b20 + #ffe5f9f5 + #ffcdf7ef + #ffb3f2e6 + #ff7dead5 + #ff24e0c5 + #ff08c4b2 + #ff00a99c + #ff0b968f + #ff067c7c + #ff026661 + #ff083f3f + #ff002528 + #ffd9fcfb + #ffc5f9f9 + #ffa5f2f2 + #ff76e5e2 + #ff33d6e2 + #ff17b8ce + #ff0797ae + #ff0b8599 + #ff0f6e84 + #ff035e73 + #ff083d4f + #ff002838 + #ffe9f8ff + #ffdcf2ff + #ffc7e4f9 + #ffa1d2f8 + #ff56adf5 + #ff3896e3 + #ff2b87d3 + #ff2079c3 + #ff116daa + #ff0c5689 + #ff0a3960 + #ff002138 + #fff2f2f9 + #ffeaeaf9 + #ffd8d7f9 + #ffc1c1f7 + #ffa193f2 + #ff9180f4 + #ff816fea + #ff6f5ed3 + #ff5e4eba + #ff483a9c + #ff2d246b + #ff1d1d38 + #fffef0ff + #fff9e3fc + #fff4c4f7 + #ffedadf2 + #fff282f5 + #ffdb61db + #ffc44eb9 + #ffac44a8 + #ff8f3896 + #ff6c2277 + #ff451551 + #ff29192d + #ffffe9f3 + #fffcdbeb + #ffffb5d5 + #ffff95c1 + #ffff76ae + #ffef588b + #ffe0447c + #ffce3665 + #ffb22f5b + #ff931847 + #ff561231 + #ff2b1721 + #ffffeae9 + #ffffd5d2 + #ffffb8b1 + #ffff9c8f + #ffff7f6e + #fff76054 + #ffed4c42 + #ffdb3e3e + #ffc63434 + #ff992222 + #ff6d1313 + #ff2b1111 + #ffffede3 + #fffcdccc + #ffffc6a4 + #ffffb180 + #ffff9c5d + #fffc8943 + #fff57d33 + #ffed7024 + #ffce5511 + #ff962c0b + #ff601700 + #ff2d130e + #ffffffff + #fff3f4f4 + #ffdee1e1 + #ffc8cccc + #ffb0b6b7 + #ff929a9b + #ff6e797a + #ff515e5f + #ff364141 + #ff273333 + #ff162020 + #ff040404 + #fffff8e2 + #fffdefcd + #ffffe99a + #ffffe16e + #ffffd943 + #ffffcd1c + #ffffbc00 + #ffdd9903 + #ffba7506 + #ff944c0c + #ff542a00 + #ff2d1a05 + #ff040404 + #ff273333 + #ff364141 + #ff0b8599 + #ff0b8599 + #ff6f5ed3 + #ff364141 + #ff6d1313 + #ff601700 + #ff08422f + 480.00dp + 12.00sp + 16.00sp + 24.00sp + 36.00sp + 8.00dp + 16.00dp + 16.00dp + 16.00dp +`; +/* end snapshot integration android android/resources should match snapshot */ + +snapshots["integration android android/resources with references should match snapshot"] = +` + + + + @color/color_core_neutral_0 + @color/color_core_neutral_100 + @color/color_core_neutral_200 + @color/color_core_red_0 + @color/color_core_orange_0 + @color/color_core_green_0 + @color/color_core_blue_0 + @color/color_background_tertiary + @color/color_core_neutral_300 + @color/color_core_aqua_700 + @color/color_core_purple_700 + #ffebf9eb + #ffd7f4d7 + #ffc2f2bd + #ff98e58e + #ff75dd66 + #ff59cb59 + #ff2bb656 + #ff0ca750 + #ff008b46 + #ff006b40 + #ff08422f + #ff002b20 + #ffe5f9f5 + #ffcdf7ef + #ffb3f2e6 + #ff7dead5 + #ff24e0c5 + #ff08c4b2 + #ff00a99c + #ff0b968f + #ff067c7c + #ff026661 + #ff083f3f + #ff002528 + #ffd9fcfb + #ffc5f9f9 + #ffa5f2f2 + #ff76e5e2 + #ff33d6e2 + #ff17b8ce + #ff0797ae + #ff0b8599 + #ff0f6e84 + #ff035e73 + #ff083d4f + #ff002838 + #ffe9f8ff + #ffdcf2ff + #ffc7e4f9 + #ffa1d2f8 + #ff56adf5 + #ff3896e3 + #ff2b87d3 + #ff2079c3 + #ff116daa + #ff0c5689 + #ff0a3960 + #ff002138 + #fff2f2f9 + #ffeaeaf9 + #ffd8d7f9 + #ffc1c1f7 + #ffa193f2 + #ff9180f4 + #ff816fea + #ff6f5ed3 + #ff5e4eba + #ff483a9c + #ff2d246b + #ff1d1d38 + #fffef0ff + #fff9e3fc + #fff4c4f7 + #ffedadf2 + #fff282f5 + #ffdb61db + #ffc44eb9 + #ffac44a8 + #ff8f3896 + #ff6c2277 + #ff451551 + #ff29192d + #ffffe9f3 + #fffcdbeb + #ffffb5d5 + #ffff95c1 + #ffff76ae + #ffef588b + #ffe0447c + #ffce3665 + #ffb22f5b + #ff931847 + #ff561231 + #ff2b1721 + #ffffeae9 + #ffffd5d2 + #ffffb8b1 + #ffff9c8f + #ffff7f6e + #fff76054 + #ffed4c42 + #ffdb3e3e + #ffc63434 + #ff992222 + #ff6d1313 + #ff2b1111 + #ffffede3 + #fffcdccc + #ffffc6a4 + #ffffb180 + #ffff9c5d + #fffc8943 + #fff57d33 + #ffed7024 + #ffce5511 + #ff962c0b + #ff601700 + #ff2d130e + #ffffffff + #fff3f4f4 + #ffdee1e1 + #ffc8cccc + #ffb0b6b7 + #ff929a9b + #ff6e797a + #ff515e5f + #ff364141 + #ff273333 + #ff162020 + #ff040404 + #fffff8e2 + #fffdefcd + #ffffe99a + #ffffe16e + #ffffd943 + #ffffcd1c + #ffffbc00 + #ffdd9903 + #ffba7506 + #ff944c0c + #ff542a00 + #ff2d1a05 + @color/color_core_neutral_1100 + @color/color_core_neutral_900 + @color/color_core_neutral_800 + @color/color_brand_primary + @color/color_brand_primary + @color/color_brand_secondary + @color/color_font_tertiary + @color/color_core_red_1000 + @color/color_core_orange_1000 + @color/color_core_green_1000 + 480.00dp + 12.00sp + 16.00sp + 24.00sp + 36.00sp + 8.00dp + 16.00dp + 16.00dp + 16.00dp +`; +/* end snapshot integration android android/resources with references should match snapshot */ + +snapshots["integration android android/resources with filter should match snapshot"] = +` + + + + #ffffffff + #fff3f4f4 + #ffdee1e1 + #ffffeae9 + #ffffede3 + #ffebf9eb + #ffe9f8ff + #ffdee1e1 + #ffc8cccc + #ff0b8599 + #ff6f5ed3 + #ffebf9eb + #ffd7f4d7 + #ffc2f2bd + #ff98e58e + #ff75dd66 + #ff59cb59 + #ff2bb656 + #ff0ca750 + #ff008b46 + #ff006b40 + #ff08422f + #ff002b20 + #ffe5f9f5 + #ffcdf7ef + #ffb3f2e6 + #ff7dead5 + #ff24e0c5 + #ff08c4b2 + #ff00a99c + #ff0b968f + #ff067c7c + #ff026661 + #ff083f3f + #ff002528 + #ffd9fcfb + #ffc5f9f9 + #ffa5f2f2 + #ff76e5e2 + #ff33d6e2 + #ff17b8ce + #ff0797ae + #ff0b8599 + #ff0f6e84 + #ff035e73 + #ff083d4f + #ff002838 + #ffe9f8ff + #ffdcf2ff + #ffc7e4f9 + #ffa1d2f8 + #ff56adf5 + #ff3896e3 + #ff2b87d3 + #ff2079c3 + #ff116daa + #ff0c5689 + #ff0a3960 + #ff002138 + #fff2f2f9 + #ffeaeaf9 + #ffd8d7f9 + #ffc1c1f7 + #ffa193f2 + #ff9180f4 + #ff816fea + #ff6f5ed3 + #ff5e4eba + #ff483a9c + #ff2d246b + #ff1d1d38 + #fffef0ff + #fff9e3fc + #fff4c4f7 + #ffedadf2 + #fff282f5 + #ffdb61db + #ffc44eb9 + #ffac44a8 + #ff8f3896 + #ff6c2277 + #ff451551 + #ff29192d + #ffffe9f3 + #fffcdbeb + #ffffb5d5 + #ffff95c1 + #ffff76ae + #ffef588b + #ffe0447c + #ffce3665 + #ffb22f5b + #ff931847 + #ff561231 + #ff2b1721 + #ffffeae9 + #ffffd5d2 + #ffffb8b1 + #ffff9c8f + #ffff7f6e + #fff76054 + #ffed4c42 + #ffdb3e3e + #ffc63434 + #ff992222 + #ff6d1313 + #ff2b1111 + #ffffede3 + #fffcdccc + #ffffc6a4 + #ffffb180 + #ffff9c5d + #fffc8943 + #fff57d33 + #ffed7024 + #ffce5511 + #ff962c0b + #ff601700 + #ff2d130e + #ffffffff + #fff3f4f4 + #ffdee1e1 + #ffc8cccc + #ffb0b6b7 + #ff929a9b + #ff6e797a + #ff515e5f + #ff364141 + #ff273333 + #ff162020 + #ff040404 + #fffff8e2 + #fffdefcd + #ffffe99a + #ffffe16e + #ffffd943 + #ffffcd1c + #ffffbc00 + #ffdd9903 + #ffba7506 + #ff944c0c + #ff542a00 + #ff2d1a05 + #ff040404 + #ff273333 + #ff364141 + #ff0b8599 + #ff0b8599 + #ff6f5ed3 + #ff364141 + #ff6d1313 + #ff601700 + #ff08422f +`; +/* end snapshot integration android android/resources with filter should match snapshot */ + diff --git a/__integration__/__snapshots__/async.test.snap.js b/__integration__/__snapshots__/async.test.snap.js new file mode 100644 index 000000000..77df7f2a4 --- /dev/null +++ b/__integration__/__snapshots__/async.test.snap.js @@ -0,0 +1,176 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration async hooks should match snapshot"] = +`/** + * foo + * bar + */ + +:root { + --color-background-primary: #ffffff; + --color-background-secondary: #f3f4f4; + --color-background-tertiary: #dee1e1; + --color-background-danger: #ffeae9; + --color-background-warning: #ffede3; + --color-background-success: #ebf9eb; + --color-background-disabled: #dee1e1; + --color-border-primary: #c8cccc; + --color-brand-primary: #0b8599; + --color-brand-secondary: #6f5ed3; + --color-core-green-0: #ebf9eb; + --color-core-green-100: #d7f4d7; + --color-core-green-200: #c2f2bd; + --color-core-green-300: #98e58e; + --color-core-green-400: #75dd66; + --color-core-green-500: #59cb59; + --color-core-green-600: #2bb656; + --color-core-green-700: #0ca750; + --color-core-green-800: #008b46; + --color-core-green-900: #006b40; + --color-core-green-1000: #08422f; + --color-core-green-1100: #002b20; + --color-core-teal-0: #e5f9f5; + --color-core-teal-100: #cdf7ef; + --color-core-teal-200: #b3f2e6; + --color-core-teal-300: #7dead5; + --color-core-teal-400: #24e0c5; + --color-core-teal-500: #08c4b2; + --color-core-teal-600: #00a99c; + --color-core-teal-700: #0b968f; + --color-core-teal-800: #067c7c; + --color-core-teal-900: #026661; + --color-core-teal-1000: #083f3f; + --color-core-teal-1100: #002528; + --color-core-aqua-0: #d9fcfb; + --color-core-aqua-100: #c5f9f9; + --color-core-aqua-200: #a5f2f2; + --color-core-aqua-300: #76e5e2; + --color-core-aqua-400: #33d6e2; + --color-core-aqua-500: #17b8ce; + --color-core-aqua-600: #0797ae; + --color-core-aqua-700: #0b8599; + --color-core-aqua-800: #0f6e84; + --color-core-aqua-900: #035e73; + --color-core-aqua-1000: #083d4f; + --color-core-aqua-1100: #002838; + --color-core-blue-0: #e9f8ff; + --color-core-blue-100: #dcf2ff; + --color-core-blue-200: #c7e4f9; + --color-core-blue-300: #a1d2f8; + --color-core-blue-400: #56adf5; + --color-core-blue-500: #3896e3; + --color-core-blue-600: #2b87d3; + --color-core-blue-700: #2079c3; + --color-core-blue-800: #116daa; + --color-core-blue-900: #0c5689; + --color-core-blue-1000: #0a3960; + --color-core-blue-1100: #002138; + --color-core-purple-0: #f2f2f9; + --color-core-purple-100: #eaeaf9; + --color-core-purple-200: #d8d7f9; + --color-core-purple-300: #c1c1f7; + --color-core-purple-400: #a193f2; + --color-core-purple-500: #9180f4; + --color-core-purple-600: #816fea; + --color-core-purple-700: #6f5ed3; + --color-core-purple-800: #5e4eba; + --color-core-purple-900: #483a9c; + --color-core-purple-1000: #2d246b; + --color-core-purple-1100: #1d1d38; + --color-core-magenta-0: #fef0ff; + --color-core-magenta-100: #f9e3fc; + --color-core-magenta-200: #f4c4f7; + --color-core-magenta-300: #edadf2; + --color-core-magenta-400: #f282f5; + --color-core-magenta-500: #db61db; + --color-core-magenta-600: #c44eb9; + --color-core-magenta-700: #ac44a8; + --color-core-magenta-800: #8f3896; + --color-core-magenta-900: #6c2277; + --color-core-magenta-1000: #451551; + --color-core-magenta-1100: #29192d; + --color-core-pink-0: #ffe9f3; + --color-core-pink-100: #fcdbeb; + --color-core-pink-200: #ffb5d5; + --color-core-pink-300: #ff95c1; + --color-core-pink-400: #ff76ae; + --color-core-pink-500: #ef588b; + --color-core-pink-600: #e0447c; + --color-core-pink-700: #ce3665; + --color-core-pink-800: #b22f5b; + --color-core-pink-900: #931847; + --color-core-pink-1000: #561231; + --color-core-pink-1100: #2b1721; + --color-core-red-0: #ffeae9; + --color-core-red-100: #ffd5d2; + --color-core-red-200: #ffb8b1; + --color-core-red-300: #ff9c8f; + --color-core-red-400: #ff7f6e; + --color-core-red-500: #f76054; + --color-core-red-600: #ed4c42; + --color-core-red-700: #db3e3e; + --color-core-red-800: #c63434; + --color-core-red-900: #992222; + --color-core-red-1000: #6d1313; + --color-core-red-1100: #2b1111; + --color-core-orange-0: #ffede3; + --color-core-orange-100: #fcdccc; + --color-core-orange-200: #ffc6a4; + --color-core-orange-300: #ffb180; + --color-core-orange-400: #ff9c5d; + --color-core-orange-500: #fc8943; + --color-core-orange-600: #f57d33; + --color-core-orange-700: #ed7024; + --color-core-orange-800: #ce5511; + --color-core-orange-900: #962c0b; + --color-core-orange-1000: #601700; + --color-core-orange-1100: #2d130e; + --color-core-neutral-0: #ffffff; + --color-core-neutral-100: #f3f4f4; + --color-core-neutral-200: #dee1e1; + --color-core-neutral-300: #c8cccc; + --color-core-neutral-400: #b0b6b7; + --color-core-neutral-500: #929a9b; + --color-core-neutral-600: #6e797a; + --color-core-neutral-700: #515e5f; + --color-core-neutral-800: #364141; + --color-core-neutral-900: #273333; + --color-core-neutral-1000: #162020; + --color-core-neutral-1100: #040404; + --color-core-yellow-0: #fff8e2; + --color-core-yellow-100: #fdefcd; + --color-core-yellow-200: #ffe99a; + --color-core-yellow-300: #ffe16e; + --color-core-yellow-400: #ffd943; + --color-core-yellow-500: #ffcd1c; + --color-core-yellow-600: #ffbc00; + --color-core-yellow-700: #dd9903; + --color-core-yellow-800: #ba7506; + --color-core-yellow-900: #944c0c; + --color-core-yellow-1000: #542a00; + --color-core-yellow-1100: #2d1a05; + --color-font-primary: #040404; + --color-font-secondary: #273333; + --color-font-tertiary: #364141; + --color-font-interactive: #0b8599; + --color-font-interactive-hover: #0b8599; + --color-font-interactive-active: #6f5ed3; + --color-font-interactive-disabled: #364141; + --color-font-danger: #6d1313; + --color-font-warning: #601700; + --color-font-success: #08422f; + --size-border-radius-large: 30rem; + --size-font-small: 0.75rem; + --size-font-medium: 1rem; + --size-font-large: 1.5rem; + --size-font-xl: 2.25rem; + --size-padding-small: 0.5rem; + --size-padding-medium: 1rem; + --size-padding-large: 1rem; + --size-padding-xl: 1rem; + --foo: bar; +} +`; +/* end snapshot integration async hooks should match snapshot */ + diff --git a/__integration__/__snapshots__/compose.test.js.snap b/__integration__/__snapshots__/compose.test.snap.js similarity index 96% rename from __integration__/__snapshots__/compose.test.js.snap rename to __integration__/__snapshots__/compose.test.snap.js index 08bd16106..319f1ac02 100644 --- a/__integration__/__snapshots__/compose.test.js.snap +++ b/__integration__/__snapshots__/compose.test.snap.js @@ -1,10 +1,10 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; -exports[`integration compose compose/object should match snapshot 1`] = ` -" +snapshots["integration compose compose/object should match snapshot"] = +` -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +// Do not edit directly, this file was auto-generated. @@ -176,15 +176,13 @@ object StyleDictionary { val sizePaddingMedium = 16.00.dp val sizePaddingSmall = 8.00.dp val sizePaddingXl = 16.00.dp -} -" -`; +}`; +/* end snapshot integration compose compose/object should match snapshot */ -exports[`integration compose compose/object with references should match snapshot 1`] = ` -" +snapshots["integration compose compose/object with references should match snapshot"] = +` -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +// Do not edit directly, this file was auto-generated. @@ -356,6 +354,6 @@ object StyleDictionary { val colorFontInteractiveHover = colorBrandPrimary val colorFontInteractive = colorBrandPrimary val colorBackgroundDisabled = colorBackgroundTertiary -} -" -`; +}`; +/* end snapshot integration compose compose/object with references should match snapshot */ + diff --git a/__integration__/__snapshots__/css.test.js.snap b/__integration__/__snapshots__/css.test.snap.js similarity index 66% rename from __integration__/__snapshots__/css.test.js.snap rename to __integration__/__snapshots__/css.test.snap.js index 7733336e8..b924ff480 100644 --- a/__integration__/__snapshots__/css.test.js.snap +++ b/__integration__/__snapshots__/css.test.snap.js @@ -1,185 +1,184 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; -exports[`integration css css/variables should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT +snapshots["integration css css/variables should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. */ :root { - --breakpoint-xs: 304px; - --breakpoint-sm: 768px; - --breakpoint-md: calc(304px / 768px); - --color-background-primary: #ffffff; - --color-background-secondary: #f3f4f4; - --color-background-tertiary: #dee1e1; - --color-background-danger: #ffeae9; - --color-background-warning: #ffede3; - --color-background-success: #ebf9eb; - --color-background-info: #e9f8ff; - --color-background-disabled: #dee1e1; - --color-border-primary: #c8cccc; - --color-brand-primary: #0b8599; - --color-brand-secondary: #6f5ed3; - --color-core-green-0: #ebf9eb; - --color-core-green-100: #d7f4d7; - --color-core-green-200: #c2f2bd; - --color-core-green-300: #98e58e; - --color-core-green-400: #75dd66; - --color-core-green-500: #59cb59; - --color-core-green-600: #2bb656; - --color-core-green-700: #0ca750; - --color-core-green-800: #008b46; - --color-core-green-900: #006b40; - --color-core-green-1000: #08422f; - --color-core-green-1100: #002b20; - --color-core-teal-0: #e5f9f5; - --color-core-teal-100: #cdf7ef; - --color-core-teal-200: #b3f2e6; - --color-core-teal-300: #7dead5; - --color-core-teal-400: #24e0c5; - --color-core-teal-500: #08c4b2; - --color-core-teal-600: #00a99c; - --color-core-teal-700: #0b968f; - --color-core-teal-800: #067c7c; - --color-core-teal-900: #026661; - --color-core-teal-1000: #083f3f; - --color-core-teal-1100: #002528; - --color-core-aqua-0: #d9fcfb; - --color-core-aqua-100: #c5f9f9; - --color-core-aqua-200: #a5f2f2; - --color-core-aqua-300: #76e5e2; - --color-core-aqua-400: #33d6e2; - --color-core-aqua-500: #17b8ce; - --color-core-aqua-600: #0797ae; - --color-core-aqua-700: #0b8599; - --color-core-aqua-800: #0f6e84; - --color-core-aqua-900: #035e73; - --color-core-aqua-1000: #083d4f; - --color-core-aqua-1100: #002838; - --color-core-blue-0: #e9f8ff; - --color-core-blue-100: #dcf2ff; - --color-core-blue-200: #c7e4f9; - --color-core-blue-300: #a1d2f8; - --color-core-blue-400: #56adf5; - --color-core-blue-500: #3896e3; - --color-core-blue-600: #2b87d3; - --color-core-blue-700: #2079c3; - --color-core-blue-800: #116daa; - --color-core-blue-900: #0c5689; - --color-core-blue-1000: #0a3960; - --color-core-blue-1100: #002138; - --color-core-purple-0: #f2f2f9; - --color-core-purple-100: #eaeaf9; - --color-core-purple-200: #d8d7f9; - --color-core-purple-300: #c1c1f7; - --color-core-purple-400: #a193f2; - --color-core-purple-500: #9180f4; - --color-core-purple-600: #816fea; - --color-core-purple-700: #6f5ed3; - --color-core-purple-800: #5e4eba; - --color-core-purple-900: #483a9c; - --color-core-purple-1000: #2d246b; - --color-core-purple-1100: #1d1d38; - --color-core-magenta-0: #fef0ff; - --color-core-magenta-100: #f9e3fc; - --color-core-magenta-200: #f4c4f7; - --color-core-magenta-300: #edadf2; - --color-core-magenta-400: #f282f5; - --color-core-magenta-500: #db61db; - --color-core-magenta-600: #c44eb9; - --color-core-magenta-700: #ac44a8; - --color-core-magenta-800: #8f3896; - --color-core-magenta-900: #6c2277; - --color-core-magenta-1000: #451551; - --color-core-magenta-1100: #29192d; - --color-core-pink-0: #ffe9f3; - --color-core-pink-100: #fcdbeb; - --color-core-pink-200: #ffb5d5; - --color-core-pink-300: #ff95c1; - --color-core-pink-400: #ff76ae; - --color-core-pink-500: #ef588b; - --color-core-pink-600: #e0447c; - --color-core-pink-700: #ce3665; - --color-core-pink-800: #b22f5b; - --color-core-pink-900: #931847; - --color-core-pink-1000: #561231; - --color-core-pink-1100: #2b1721; - --color-core-red-0: #ffeae9; - --color-core-red-100: #ffd5d2; - --color-core-red-200: #ffb8b1; - --color-core-red-300: #ff9c8f; - --color-core-red-400: #ff7f6e; - --color-core-red-500: #f76054; - --color-core-red-600: #ed4c42; - --color-core-red-700: #db3e3e; - --color-core-red-800: #c63434; - --color-core-red-900: #992222; - --color-core-red-1000: #6d1313; - --color-core-red-1100: #2b1111; - --color-core-orange-0: #ffede3; - --color-core-orange-100: #fcdccc; - --color-core-orange-200: #ffc6a4; - --color-core-orange-300: #ffb180; - --color-core-orange-400: #ff9c5d; - --color-core-orange-500: #fc8943; - --color-core-orange-600: #f57d33; - --color-core-orange-700: #ed7024; - --color-core-orange-800: #ce5511; - --color-core-orange-900: #962c0b; - --color-core-orange-1000: #601700; - --color-core-orange-1100: #2d130e; - --color-core-neutral-0: #ffffff; - --color-core-neutral-100: #f3f4f4; - --color-core-neutral-200: #dee1e1; - --color-core-neutral-300: #c8cccc; - --color-core-neutral-400: #b0b6b7; - --color-core-neutral-500: #929a9b; - --color-core-neutral-600: #6e797a; - --color-core-neutral-700: #515e5f; - --color-core-neutral-800: #364141; - --color-core-neutral-900: #273333; - --color-core-neutral-1000: #162020; - --color-core-neutral-1100: #040404; - --color-core-yellow-0: #fff8e2; - --color-core-yellow-100: #fdefcd; - --color-core-yellow-200: #ffe99a; - --color-core-yellow-300: #ffe16e; - --color-core-yellow-400: #ffd943; - --color-core-yellow-500: #ffcd1c; - --color-core-yellow-600: #ffbc00; - --color-core-yellow-700: #dd9903; - --color-core-yellow-800: #ba7506; - --color-core-yellow-900: #944c0c; - --color-core-yellow-1000: #542a00; - --color-core-yellow-1100: #2d1a05; - --color-font-primary: #040404; - --color-font-secondary: #273333; - --color-font-tertiary: #364141; - --color-font-interactive: #0b8599; - --color-font-interactive-hover: #0b8599; - --color-font-interactive-active: #6f5ed3; - --color-font-interactive-disabled: #364141; - --color-font-danger: #6d1313; - --color-font-warning: #601700; - --color-font-success: #08422f; - --size-border-radius-large: 30rem; - --size-font-small: 0.75rem; - --size-font-medium: 1rem; - --size-font-large: 1.5rem; - --size-font-xl: 2.25rem; - --size-padding-small: 0.5rem; - --size-padding-medium: 1rem; - --size-padding-large: 1rem; - --size-padding-xl: 1rem; + --breakpoint-xs: 304px; + --breakpoint-sm: 768px; + --breakpoint-md: calc(304px / 768px); + --color-background-primary: #ffffff; + --color-background-secondary: #f3f4f4; + --color-background-tertiary: #dee1e1; + --color-background-danger: #ffeae9; + --color-background-warning: #ffede3; + --color-background-success: #ebf9eb; + --color-background-info: #e9f8ff; + --color-background-disabled: #dee1e1; + --color-border-primary: #c8cccc; + --color-brand-primary: #0b8599; + --color-brand-secondary: #6f5ed3; + --color-core-green-0: #ebf9eb; + --color-core-green-100: #d7f4d7; + --color-core-green-200: #c2f2bd; + --color-core-green-300: #98e58e; + --color-core-green-400: #75dd66; + --color-core-green-500: #59cb59; + --color-core-green-600: #2bb656; + --color-core-green-700: #0ca750; + --color-core-green-800: #008b46; + --color-core-green-900: #006b40; + --color-core-green-1000: #08422f; + --color-core-green-1100: #002b20; + --color-core-teal-0: #e5f9f5; + --color-core-teal-100: #cdf7ef; + --color-core-teal-200: #b3f2e6; + --color-core-teal-300: #7dead5; + --color-core-teal-400: #24e0c5; + --color-core-teal-500: #08c4b2; + --color-core-teal-600: #00a99c; + --color-core-teal-700: #0b968f; + --color-core-teal-800: #067c7c; + --color-core-teal-900: #026661; + --color-core-teal-1000: #083f3f; + --color-core-teal-1100: #002528; + --color-core-aqua-0: #d9fcfb; + --color-core-aqua-100: #c5f9f9; + --color-core-aqua-200: #a5f2f2; + --color-core-aqua-300: #76e5e2; + --color-core-aqua-400: #33d6e2; + --color-core-aqua-500: #17b8ce; + --color-core-aqua-600: #0797ae; + --color-core-aqua-700: #0b8599; + --color-core-aqua-800: #0f6e84; + --color-core-aqua-900: #035e73; + --color-core-aqua-1000: #083d4f; + --color-core-aqua-1100: #002838; + --color-core-blue-0: #e9f8ff; + --color-core-blue-100: #dcf2ff; + --color-core-blue-200: #c7e4f9; + --color-core-blue-300: #a1d2f8; + --color-core-blue-400: #56adf5; + --color-core-blue-500: #3896e3; + --color-core-blue-600: #2b87d3; + --color-core-blue-700: #2079c3; + --color-core-blue-800: #116daa; + --color-core-blue-900: #0c5689; + --color-core-blue-1000: #0a3960; + --color-core-blue-1100: #002138; + --color-core-purple-0: #f2f2f9; + --color-core-purple-100: #eaeaf9; + --color-core-purple-200: #d8d7f9; + --color-core-purple-300: #c1c1f7; + --color-core-purple-400: #a193f2; + --color-core-purple-500: #9180f4; + --color-core-purple-600: #816fea; + --color-core-purple-700: #6f5ed3; + --color-core-purple-800: #5e4eba; + --color-core-purple-900: #483a9c; + --color-core-purple-1000: #2d246b; + --color-core-purple-1100: #1d1d38; + --color-core-magenta-0: #fef0ff; + --color-core-magenta-100: #f9e3fc; + --color-core-magenta-200: #f4c4f7; + --color-core-magenta-300: #edadf2; + --color-core-magenta-400: #f282f5; + --color-core-magenta-500: #db61db; + --color-core-magenta-600: #c44eb9; + --color-core-magenta-700: #ac44a8; + --color-core-magenta-800: #8f3896; + --color-core-magenta-900: #6c2277; + --color-core-magenta-1000: #451551; + --color-core-magenta-1100: #29192d; + --color-core-pink-0: #ffe9f3; + --color-core-pink-100: #fcdbeb; + --color-core-pink-200: #ffb5d5; + --color-core-pink-300: #ff95c1; + --color-core-pink-400: #ff76ae; + --color-core-pink-500: #ef588b; + --color-core-pink-600: #e0447c; + --color-core-pink-700: #ce3665; + --color-core-pink-800: #b22f5b; + --color-core-pink-900: #931847; + --color-core-pink-1000: #561231; + --color-core-pink-1100: #2b1721; + --color-core-red-0: #ffeae9; + --color-core-red-100: #ffd5d2; + --color-core-red-200: #ffb8b1; + --color-core-red-300: #ff9c8f; + --color-core-red-400: #ff7f6e; + --color-core-red-500: #f76054; + --color-core-red-600: #ed4c42; + --color-core-red-700: #db3e3e; + --color-core-red-800: #c63434; + --color-core-red-900: #992222; + --color-core-red-1000: #6d1313; + --color-core-red-1100: #2b1111; + --color-core-orange-0: #ffede3; + --color-core-orange-100: #fcdccc; + --color-core-orange-200: #ffc6a4; + --color-core-orange-300: #ffb180; + --color-core-orange-400: #ff9c5d; + --color-core-orange-500: #fc8943; + --color-core-orange-600: #f57d33; + --color-core-orange-700: #ed7024; + --color-core-orange-800: #ce5511; + --color-core-orange-900: #962c0b; + --color-core-orange-1000: #601700; + --color-core-orange-1100: #2d130e; + --color-core-neutral-0: #ffffff; + --color-core-neutral-100: #f3f4f4; + --color-core-neutral-200: #dee1e1; + --color-core-neutral-300: #c8cccc; + --color-core-neutral-400: #b0b6b7; + --color-core-neutral-500: #929a9b; + --color-core-neutral-600: #6e797a; + --color-core-neutral-700: #515e5f; + --color-core-neutral-800: #364141; + --color-core-neutral-900: #273333; + --color-core-neutral-1000: #162020; + --color-core-neutral-1100: #040404; + --color-core-yellow-0: #fff8e2; + --color-core-yellow-100: #fdefcd; + --color-core-yellow-200: #ffe99a; + --color-core-yellow-300: #ffe16e; + --color-core-yellow-400: #ffd943; + --color-core-yellow-500: #ffcd1c; + --color-core-yellow-600: #ffbc00; + --color-core-yellow-700: #dd9903; + --color-core-yellow-800: #ba7506; + --color-core-yellow-900: #944c0c; + --color-core-yellow-1000: #542a00; + --color-core-yellow-1100: #2d1a05; + --color-font-primary: #040404; + --color-font-secondary: #273333; + --color-font-tertiary: #364141; + --color-font-interactive: #0b8599; + --color-font-interactive-hover: #0b8599; + --color-font-interactive-active: #6f5ed3; + --color-font-interactive-disabled: #364141; + --color-font-danger: #6d1313; + --color-font-warning: #601700; + --color-font-success: #08422f; + --size-border-radius-large: 30rem; + --size-font-small: 0.75rem; + --size-font-medium: 1rem; + --size-font-large: 1.5rem; + --size-font-xl: 2.25rem; + --size-padding-small: 0.5rem; + --size-padding-medium: 1rem; + --size-padding-large: 1rem; + --size-padding-xl: 1rem; } -" `; +/* end snapshot integration css css/variables should match snapshot */ -exports[`integration css css/variables with references should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT +snapshots["integration css css/variables with references should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. */ :root { @@ -349,13 +348,12 @@ exports[`integration css css/variables with references should match snapshot 1`] --color-font-interactive: var(--color-brand-primary); --color-background-disabled: var(--color-background-tertiary); } -" `; +/* end snapshot integration css css/variables with references should match snapshot */ -exports[`integration css css/variables with selector should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT +snapshots["integration css css/variables with selector should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. */ .test { @@ -525,5 +523,181 @@ exports[`integration css css/variables with selector should match snapshot 1`] = --size-padding-large: 1rem; --size-padding-xl: 1rem; } -" `; +/* end snapshot integration css css/variables with selector should match snapshot */ + +snapshots["integration css css/variables with referenceFallbacks should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --size-padding-xl: 1rem; + --size-padding-large: 1rem; + --size-padding-medium: 1rem; + --size-padding-small: 0.5rem; + --size-font-xl: 2.25rem; + --size-font-large: 1.5rem; + --size-font-medium: 1rem; + --size-font-small: 0.75rem; + --size-border-radius-large: 30rem; + --color-core-yellow-1100: #2d1a05; + --color-core-yellow-1000: #542a00; + --color-core-yellow-900: #944c0c; + --color-core-yellow-800: #ba7506; + --color-core-yellow-700: #dd9903; + --color-core-yellow-600: #ffbc00; + --color-core-yellow-500: #ffcd1c; + --color-core-yellow-400: #ffd943; + --color-core-yellow-300: #ffe16e; + --color-core-yellow-200: #ffe99a; + --color-core-yellow-100: #fdefcd; + --color-core-yellow-0: #fff8e2; + --color-core-neutral-1100: #040404; + --color-core-neutral-1000: #162020; + --color-core-neutral-900: #273333; + --color-core-neutral-800: #364141; + --color-core-neutral-700: #515e5f; + --color-core-neutral-600: #6e797a; + --color-core-neutral-500: #929a9b; + --color-core-neutral-400: #b0b6b7; + --color-core-neutral-300: #c8cccc; + --color-core-neutral-200: #dee1e1; + --color-core-neutral-100: #f3f4f4; + --color-core-neutral-0: #ffffff; + --color-core-orange-1100: #2d130e; + --color-core-orange-1000: #601700; + --color-core-orange-900: #962c0b; + --color-core-orange-800: #ce5511; + --color-core-orange-700: #ed7024; + --color-core-orange-600: #f57d33; + --color-core-orange-500: #fc8943; + --color-core-orange-400: #ff9c5d; + --color-core-orange-300: #ffb180; + --color-core-orange-200: #ffc6a4; + --color-core-orange-100: #fcdccc; + --color-core-orange-0: #ffede3; + --color-core-red-1100: #2b1111; + --color-core-red-1000: #6d1313; + --color-core-red-900: #992222; + --color-core-red-800: #c63434; + --color-core-red-700: #db3e3e; + --color-core-red-600: #ed4c42; + --color-core-red-500: #f76054; + --color-core-red-400: #ff7f6e; + --color-core-red-300: #ff9c8f; + --color-core-red-200: #ffb8b1; + --color-core-red-100: #ffd5d2; + --color-core-red-0: #ffeae9; + --color-core-pink-1100: #2b1721; + --color-core-pink-1000: #561231; + --color-core-pink-900: #931847; + --color-core-pink-800: #b22f5b; + --color-core-pink-700: #ce3665; + --color-core-pink-600: #e0447c; + --color-core-pink-500: #ef588b; + --color-core-pink-400: #ff76ae; + --color-core-pink-300: #ff95c1; + --color-core-pink-200: #ffb5d5; + --color-core-pink-100: #fcdbeb; + --color-core-pink-0: #ffe9f3; + --color-core-magenta-1100: #29192d; + --color-core-magenta-1000: #451551; + --color-core-magenta-900: #6c2277; + --color-core-magenta-800: #8f3896; + --color-core-magenta-700: #ac44a8; + --color-core-magenta-600: #c44eb9; + --color-core-magenta-500: #db61db; + --color-core-magenta-400: #f282f5; + --color-core-magenta-300: #edadf2; + --color-core-magenta-200: #f4c4f7; + --color-core-magenta-100: #f9e3fc; + --color-core-magenta-0: #fef0ff; + --color-core-purple-1100: #1d1d38; + --color-core-purple-1000: #2d246b; + --color-core-purple-900: #483a9c; + --color-core-purple-800: #5e4eba; + --color-core-purple-700: #6f5ed3; + --color-core-purple-600: #816fea; + --color-core-purple-500: #9180f4; + --color-core-purple-400: #a193f2; + --color-core-purple-300: #c1c1f7; + --color-core-purple-200: #d8d7f9; + --color-core-purple-100: #eaeaf9; + --color-core-purple-0: #f2f2f9; + --color-core-blue-1100: #002138; + --color-core-blue-1000: #0a3960; + --color-core-blue-900: #0c5689; + --color-core-blue-800: #116daa; + --color-core-blue-700: #2079c3; + --color-core-blue-600: #2b87d3; + --color-core-blue-500: #3896e3; + --color-core-blue-400: #56adf5; + --color-core-blue-300: #a1d2f8; + --color-core-blue-200: #c7e4f9; + --color-core-blue-100: #dcf2ff; + --color-core-blue-0: #e9f8ff; + --color-core-aqua-1100: #002838; + --color-core-aqua-1000: #083d4f; + --color-core-aqua-900: #035e73; + --color-core-aqua-800: #0f6e84; + --color-core-aqua-700: #0b8599; + --color-core-aqua-600: #0797ae; + --color-core-aqua-500: #17b8ce; + --color-core-aqua-400: #33d6e2; + --color-core-aqua-300: #76e5e2; + --color-core-aqua-200: #a5f2f2; + --color-core-aqua-100: #c5f9f9; + --color-core-aqua-0: #d9fcfb; + --color-core-teal-1100: #002528; + --color-core-teal-1000: #083f3f; + --color-core-teal-900: #026661; + --color-core-teal-800: #067c7c; + --color-core-teal-700: #0b968f; + --color-core-teal-600: #00a99c; + --color-core-teal-500: #08c4b2; + --color-core-teal-400: #24e0c5; + --color-core-teal-300: #7dead5; + --color-core-teal-200: #b3f2e6; + --color-core-teal-100: #cdf7ef; + --color-core-teal-0: #e5f9f5; + --color-core-green-1100: #002b20; + --color-core-green-1000: #08422f; + --color-core-green-900: #006b40; + --color-core-green-800: #008b46; + --color-core-green-700: #0ca750; + --color-core-green-600: #2bb656; + --color-core-green-500: #59cb59; + --color-core-green-400: #75dd66; + --color-core-green-300: #98e58e; + --color-core-green-200: #c2f2bd; + --color-core-green-100: #d7f4d7; + --color-core-green-0: #ebf9eb; + --breakpoint-sm: 768px; + --breakpoint-xs: 304px; + --color-font-success: var(--color-core-green-1000, #08422f); + --color-font-warning: var(--color-core-orange-1000, #601700); + --color-font-danger: var(--color-core-red-1000, #6d1313); + --color-font-tertiary: var(--color-core-neutral-800, #364141); + --color-font-secondary: var(--color-core-neutral-900, #273333); + --color-font-primary: var(--color-core-neutral-1100, #040404); + --color-brand-secondary: var(--color-core-purple-700, #6f5ed3); + --color-brand-primary: var(--color-core-aqua-700, #0b8599); + --color-border-primary: var(--color-core-neutral-300, #c8cccc); + --color-background-info: var(--color-core-blue-0, #e9f8ff); + --color-background-success: var(--color-core-green-0, #ebf9eb); + --color-background-warning: var(--color-core-orange-0, #ffede3); + --color-background-danger: var(--color-core-red-0, #ffeae9); + --color-background-tertiary: var(--color-core-neutral-200, #dee1e1); + --color-background-secondary: var(--color-core-neutral-100, #f3f4f4); + --color-background-primary: var(--color-core-neutral-0, #ffffff); + --breakpoint-md: calc(var(--breakpoint-xs, 304px) / var(--breakpoint-sm, 768px)); + --color-font-interactive-disabled: var(--color-font-tertiary, #364141); + --color-font-interactive-active: var(--color-brand-secondary, #6f5ed3); + --color-font-interactive-hover: var(--color-brand-primary, #0b8599); + --color-font-interactive: var(--color-brand-primary, #0b8599); + --color-background-disabled: var(--color-background-tertiary, #dee1e1); +} +`; +/* end snapshot integration css css/variables with referenceFallbacks should match snapshot */ + diff --git a/__integration__/__snapshots__/customFileHeader.test.js.snap b/__integration__/__snapshots__/customFileHeader.test.js.snap deleted file mode 100644 index 4108afcab..000000000 --- a/__integration__/__snapshots__/customFileHeader.test.js.snap +++ /dev/null @@ -1,117 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration valid custom file headers file options config file header should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - * hello, world! - */ - -:root { - --color-red: #ff0000; -} -" -`; - -exports[`integration valid custom file headers file options inline file header should match snapshot 1`] = ` -"/** - * build version 1.0.0 - */ - -:root { - --color-red: #ff0000; -} -" -`; - -exports[`integration valid custom file headers file options registered file header should match snapshot 1`] = ` -"/** - * hello - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --color-red: #ff0000; -} -" -`; - -exports[`integration valid custom file headers platform options file header override should match snapshot 1`] = ` -"/** - * Header overridden - */ - -module.exports = { - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#ff0000\\", - \\"original\\": { - \\"value\\": \\"#ff0000\\" - }, - \\"name\\": \\"ColorRed\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -}; -" -`; - -exports[`integration valid custom file headers platform options no file options should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - * hello, world! - */ - -module.exports = { - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#ff0000\\", - \\"original\\": { - \\"value\\": \\"#ff0000\\" - }, - \\"name\\": \\"ColorRed\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -}; -" -`; - -exports[`integration valid custom file headers platform options showFileHeader should match snapshot 1`] = ` -"module.exports = { - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#ff0000\\", - \\"original\\": { - \\"value\\": \\"#ff0000\\" - }, - \\"name\\": \\"ColorRed\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -}; -" -`; diff --git a/__integration__/__snapshots__/customFileHeader.test.snap.js b/__integration__/__snapshots__/customFileHeader.test.snap.js new file mode 100644 index 000000000..72ed4100c --- /dev/null +++ b/__integration__/__snapshots__/customFileHeader.test.snap.js @@ -0,0 +1,116 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration valid custom file headers file options registered file header should match snapshot"] = +`/** + * hello + * Do not edit directly, this file was auto-generated. + */ + +:root { + --color-red: #ff0000; +} +`; +/* end snapshot integration valid custom file headers file options registered file header should match snapshot */ + +snapshots["integration valid custom file headers file options config file header should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + * hello, world! + */ + +:root { + --color-red: #ff0000; +} +`; +/* end snapshot integration valid custom file headers file options config file header should match snapshot */ + +snapshots["integration valid custom file headers file options inline file header should match snapshot"] = +`/** + * build version 1.0.0 + */ + +:root { + --color-red: #ff0000; +} +`; +/* end snapshot integration valid custom file headers file options inline file header should match snapshot */ + +snapshots["integration valid custom file headers platform options no file options should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + * hello, world! + */ + +module.exports = { + "color": { + "red": { + "value": "#ff0000", + "original": { + "value": "#ff0000" + }, + "name": "ColorRed", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot integration valid custom file headers platform options no file options should match snapshot */ + +snapshots["integration valid custom file headers platform options showFileHeader should match snapshot"] = +`module.exports = { + "color": { + "red": { + "value": "#ff0000", + "original": { + "value": "#ff0000" + }, + "name": "ColorRed", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot integration valid custom file headers platform options showFileHeader should match snapshot */ + +snapshots["integration valid custom file headers platform options file header override should match snapshot"] = +`/** + * Header overridden + */ + +module.exports = { + "color": { + "red": { + "value": "#ff0000", + "original": { + "value": "#ff0000" + }, + "name": "ColorRed", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot integration valid custom file headers platform options file header override should match snapshot */ + diff --git a/__integration__/__snapshots__/customFormats.test.js.snap b/__integration__/__snapshots__/customFormats.test.js.snap deleted file mode 100644 index efb4a37f9..000000000 --- a/__integration__/__snapshots__/customFormats.test.js.snap +++ /dev/null @@ -1,3207 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration custom formats inline custom with new args should match snapshot 1`] = ` -"{ - \\"dictionary\\": { - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"_properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"platform\\": { - \\"transformGroup\\": \\"js\\", - \\"buildPath\\": \\"__integration__/build/\\", - \\"options\\": { - \\"otherOption\\": \\"platform option\\" - }, - \\"files\\": [ - { - \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - }, - { - \\"destination\\": \\"inlineCustomFormatWithNewArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } - ], - \\"transforms\\": [ - { - \\"type\\": \\"attribute\\" - }, - { - \\"type\\": \\"name\\" - }, - { - \\"type\\": \\"value\\" - }, - { - \\"type\\": \\"value\\" - } - ], - \\"actions\\": [] - }, - \\"file\\": { - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - }, - \\"destination\\": \\"inlineCustomFormatWithNewArgs.json\\" - }, - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - } -}" -`; - -exports[`integration custom formats inline custom with old args should match snapshot 1`] = ` -"{ - \\"dictionary\\": { - \\"dictionary\\": { - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"_properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"platform\\": { - \\"transformGroup\\": \\"js\\", - \\"buildPath\\": \\"__integration__/build/\\", - \\"options\\": { - \\"otherOption\\": \\"platform option\\" - }, - \\"files\\": [ - { - \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - }, - { - \\"destination\\": \\"inlineCustomFormatWithNewArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } - ], - \\"transforms\\": [ - { - \\"type\\": \\"attribute\\" - }, - { - \\"type\\": \\"name\\" - }, - { - \\"type\\": \\"value\\" - }, - { - \\"type\\": \\"value\\" - } - ], - \\"actions\\": [] - }, - \\"file\\": { - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - }, - \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\" - }, - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - } - }, - \\"platform\\": { - \\"transformGroup\\": \\"js\\", - \\"buildPath\\": \\"__integration__/build/\\", - \\"options\\": { - \\"otherOption\\": \\"platform option\\" - }, - \\"files\\": [ - { - \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - }, - { - \\"destination\\": \\"inlineCustomFormatWithNewArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } - ], - \\"transforms\\": [ - { - \\"type\\": \\"attribute\\" - }, - { - \\"type\\": \\"name\\" - }, - { - \\"type\\": \\"value\\" - }, - { - \\"type\\": \\"value\\" - } - ], - \\"actions\\": [] - }, - \\"file\\": { - \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } -}" -`; - -exports[`integration custom formats register custom format with new args should match snapshot 1`] = ` -"{ - \\"dictionary\\": { - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"_properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"platform\\": { - \\"transformGroup\\": \\"js\\", - \\"buildPath\\": \\"__integration__/build/\\", - \\"options\\": { - \\"otherOption\\": \\"platform option\\" - }, - \\"files\\": [ - { - \\"destination\\": \\"registerCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - }, - { - \\"destination\\": \\"registerCustomFormatWithNewArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } - ], - \\"transforms\\": [ - { - \\"type\\": \\"attribute\\" - }, - { - \\"type\\": \\"name\\" - }, - { - \\"type\\": \\"value\\" - }, - { - \\"type\\": \\"value\\" - } - ], - \\"actions\\": [] - }, - \\"file\\": { - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - }, - \\"destination\\": \\"registerCustomFormatWithNewArgs.json\\" - }, - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - } -}" -`; - -exports[`integration custom formats register custom format with old args should match snapshot 1`] = ` -"{ - \\"dictionary\\": { - \\"dictionary\\": { - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"_properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - } - }, - \\"allProperties\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"properties\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"allTokens\\": [ - { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - ], - \\"tokens\\": { - \\"size\\": { - \\"padding\\": { - \\"small\\": { - \\"value\\": \\"0.5rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 0.5 - }, - \\"name\\": \\"SizePaddingSmall\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"small\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"small\\" - ] - }, - \\"medium\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingMedium\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"medium\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"medium\\" - ] - }, - \\"large\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingLarge\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"large\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"large\\" - ] - }, - \\"xl\\": { - \\"value\\": \\"1rem\\", - \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", - \\"isSource\\": true, - \\"original\\": { - \\"value\\": 1 - }, - \\"name\\": \\"SizePaddingXl\\", - \\"attributes\\": { - \\"category\\": \\"size\\", - \\"type\\": \\"padding\\", - \\"item\\": \\"xl\\" - }, - \\"path\\": [ - \\"size\\", - \\"padding\\", - \\"xl\\" - ] - } - } - } - }, - \\"platform\\": { - \\"transformGroup\\": \\"js\\", - \\"buildPath\\": \\"__integration__/build/\\", - \\"options\\": { - \\"otherOption\\": \\"platform option\\" - }, - \\"files\\": [ - { - \\"destination\\": \\"registerCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - }, - { - \\"destination\\": \\"registerCustomFormatWithNewArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } - ], - \\"transforms\\": [ - { - \\"type\\": \\"attribute\\" - }, - { - \\"type\\": \\"name\\" - }, - { - \\"type\\": \\"value\\" - }, - { - \\"type\\": \\"value\\" - } - ], - \\"actions\\": [] - }, - \\"file\\": { - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - }, - \\"destination\\": \\"registerCustomFormatWithOldArgs.json\\" - }, - \\"options\\": { - \\"otherOption\\": \\"Test\\", - \\"showFileHeader\\": true - } - }, - \\"platform\\": { - \\"transformGroup\\": \\"js\\", - \\"buildPath\\": \\"__integration__/build/\\", - \\"options\\": { - \\"otherOption\\": \\"platform option\\" - }, - \\"files\\": [ - { - \\"destination\\": \\"registerCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - }, - { - \\"destination\\": \\"registerCustomFormatWithNewArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } - ], - \\"transforms\\": [ - { - \\"type\\": \\"attribute\\" - }, - { - \\"type\\": \\"name\\" - }, - { - \\"type\\": \\"value\\" - }, - { - \\"type\\": \\"value\\" - } - ], - \\"actions\\": [] - }, - \\"file\\": { - \\"destination\\": \\"registerCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } -}" -`; diff --git a/__integration__/__snapshots__/customFormats.test.snap.js b/__integration__/__snapshots__/customFormats.test.snap.js new file mode 100644 index 000000000..4e4a4bad9 --- /dev/null +++ b/__integration__/__snapshots__/customFormats.test.snap.js @@ -0,0 +1,1914 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration custom formats inline custom with new args should match snapshot"] = +`{ + "dictionary": { + "tokens": { + "size": { + "padding": { + "small": { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + "medium": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + "large": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + "xl": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + } + } + }, + "allTokens": [ + { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + ], + "unfilteredTokens": { + "size": { + "padding": { + "small": { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + "medium": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + "large": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + "xl": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + } + } + }, + "unfilteredAllTokens": [ + { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + ] + }, + "allTokens": [ + { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + ], + "tokens": { + "size": { + "padding": { + "small": { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + "medium": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + "large": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + "xl": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + } + } + }, + "platform": { + "transformGroup": "js", + "buildPath": "__integration__/build/", + "options": { + "otherOption": "platform option" + }, + "files": [ + { + "destination": "inlineCustomFormatWithOldArgs.json", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + }, + { + "destination": "inlineCustomFormatWithNewArgs.json", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + } + ], + "log": { + "warnings": "warn", + "verbosity": "default", + "errors": { + "brokenReferences": "throw" + } + }, + "transforms": [ + { + "type": "attribute" + }, + { + "type": "name" + }, + { + "type": "value" + }, + { + "type": "value" + } + ], + "actions": [] + }, + "file": { + "options": { + "otherOption": "Test", + "showFileHeader": true + }, + "destination": "inlineCustomFormatWithNewArgs.json" + }, + "options": { + "hooks": { + "parsers": {}, + "preprocessors": {}, + "transformGroups": { + "web": [ + "attribute/cti", + "name/kebab", + "size/px", + "color/css" + ], + "js": [ + "attribute/cti", + "name/pascal", + "size/rem", + "color/hex" + ], + "scss": [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "size/rem", + "color/css", + "asset/url", + "fontFamily/css", + "cubicBezier/css", + "strokeStyle/css/shorthand", + "border/css/shorthand", + "typography/css/shorthand", + "transition/css/shorthand", + "shadow/css/shorthand" + ], + "css": [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "size/rem", + "color/css", + "asset/url", + "fontFamily/css", + "cubicBezier/css", + "strokeStyle/css/shorthand", + "border/css/shorthand", + "typography/css/shorthand", + "transition/css/shorthand", + "shadow/css/shorthand" + ], + "less": [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "size/rem", + "color/hex", + "asset/url", + "fontFamily/css", + "cubicBezier/css", + "strokeStyle/css/shorthand", + "border/css/shorthand", + "typography/css/shorthand", + "transition/css/shorthand", + "shadow/css/shorthand" + ], + "html": [ + "attribute/cti", + "attribute/color", + "name/human" + ], + "android": [ + "attribute/cti", + "name/snake", + "color/hex8android", + "size/remToSp", + "size/remToDp" + ], + "compose": [ + "attribute/cti", + "name/camel", + "color/composeColor", + "size/compose/em", + "size/compose/remToSp", + "size/compose/remToDp" + ], + "ios": [ + "attribute/cti", + "name/pascal", + "color/UIColor", + "content/objC/literal", + "asset/objC/literal", + "size/remToPt" + ], + "ios-swift": [ + "attribute/cti", + "name/camel", + "color/UIColorSwift", + "content/swift/literal", + "asset/swift/literal", + "size/swift/remToCGFloat" + ], + "ios-swift-separate": [ + "attribute/cti", + "name/camel", + "color/UIColorSwift", + "content/swift/literal", + "asset/swift/literal", + "size/swift/remToCGFloat" + ], + "assets": [ + "attribute/cti" + ], + "flutter": [ + "attribute/cti", + "name/camel", + "color/hex8flutter", + "size/flutter/remToDouble", + "content/flutter/literal", + "asset/flutter/literal" + ], + "flutter-separate": [ + "attribute/cti", + "name/camel", + "color/hex8flutter", + "size/flutter/remToDouble", + "content/flutter/literal", + "asset/flutter/literal" + ], + "react-native": [ + "name/camel", + "color/css", + "size/object" + ] + }, + "transforms": { + "attribute/cti": { + "type": "attribute" + }, + "attribute/color": { + "type": "attribute" + }, + "name/human": { + "type": "name" + }, + "name/camel": { + "type": "name" + }, + "name/kebab": { + "type": "name" + }, + "name/snake": { + "type": "name" + }, + "name/constant": { + "type": "name" + }, + "name/pascal": { + "type": "name" + }, + "color/rgb": { + "type": "value" + }, + "color/hsl": { + "type": "value" + }, + "color/hsl-4": { + "type": "value" + }, + "color/hex": { + "type": "value" + }, + "color/hex8": { + "type": "value" + }, + "color/hex8android": { + "type": "value" + }, + "color/composeColor": { + "type": "value" + }, + "color/UIColor": { + "type": "value" + }, + "color/UIColorSwift": { + "type": "value" + }, + "color/ColorSwiftUI": { + "type": "value" + }, + "color/css": { + "type": "value" + }, + "color/sketch": { + "type": "value" + }, + "size/sp": { + "type": "value" + }, + "size/dp": { + "type": "value" + }, + "size/object": { + "type": "value" + }, + "size/remToSp": { + "type": "value" + }, + "size/remToDp": { + "type": "value" + }, + "size/px": { + "type": "value" + }, + "size/rem": { + "type": "value" + }, + "size/remToPt": { + "type": "value" + }, + "size/compose/remToSp": { + "type": "value" + }, + "size/compose/remToDp": { + "type": "value" + }, + "size/compose/em": { + "type": "value" + }, + "size/swift/remToCGFloat": { + "type": "value" + }, + "size/remToPx": { + "type": "value" + }, + "size/pxToRem": { + "type": "value" + }, + "html/icon": { + "type": "value" + }, + "content/quote": { + "type": "value" + }, + "content/objC/literal": { + "type": "value" + }, + "content/swift/literal": { + "type": "value" + }, + "time/seconds": { + "type": "value" + }, + "fontFamily/css": { + "type": "value" + }, + "cubicBezier/css": { + "type": "value" + }, + "strokeStyle/css/shorthand": { + "type": "value", + "transitive": true + }, + "border/css/shorthand": { + "type": "value", + "transitive": true + }, + "typography/css/shorthand": { + "type": "value", + "transitive": true + }, + "transition/css/shorthand": { + "type": "value", + "transitive": true + }, + "shadow/css/shorthand": { + "type": "value", + "transitive": true + }, + "asset/url": { + "type": "value" + }, + "asset/base64": { + "type": "value" + }, + "asset/path": { + "type": "value" + }, + "asset/objC/literal": { + "type": "value" + }, + "asset/swift/literal": { + "type": "value" + }, + "color/hex8flutter": { + "type": "value" + }, + "content/flutter/literal": { + "type": "value" + }, + "asset/flutter/literal": { + "type": "value" + }, + "size/flutter/remToDouble": { + "type": "value" + } + }, + "formats": {}, + "fileHeaders": {}, + "filters": {}, + "actions": { + "android/copyImages": {}, + "copy_assets": {} + } + }, + "source": [ + "__integration__/tokens/size/padding.json" + ], + "platforms": { + "inlineCustomFormats": { + "transformGroup": "js", + "buildPath": "__integration__/build/", + "options": { + "otherOption": "platform option" + }, + "files": [ + { + "destination": "inlineCustomFormatWithOldArgs.json", + "format": "inlineCustomFormatWithOldArgs", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + }, + { + "destination": "inlineCustomFormatWithNewArgs.json", + "format": "inlineCustomFormatWithNewArgs", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + } + ] + }, + "customFormats": { + "transformGroup": "js", + "buildPath": "__integration__/build/", + "options": { + "otherOption": "platform option" + }, + "files": [ + { + "destination": "registerCustomFormatWithNewArgs.json", + "format": "registerCustomFormatWithNewArgs", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + } + ] + } + }, + "log": { + "warnings": "warn", + "verbosity": "default", + "errors": { + "brokenReferences": "throw" + } + }, + "usesDtcg": false, + "otherOption": "Test", + "showFileHeader": true + } +}`; +/* end snapshot integration custom formats inline custom with new args should match snapshot */ + +snapshots["integration custom formats register custom format with new args should match snapshot"] = +`{ + "dictionary": { + "tokens": { + "size": { + "padding": { + "small": { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + "medium": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + "large": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + "xl": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + } + } + }, + "allTokens": [ + { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + ], + "unfilteredTokens": { + "size": { + "padding": { + "small": { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + "medium": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + "large": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + "xl": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + } + } + }, + "unfilteredAllTokens": [ + { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + ] + }, + "allTokens": [ + { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + ], + "tokens": { + "size": { + "padding": { + "small": { + "value": "0.5rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 0.5, + "type": "dimension" + }, + "name": "SizePaddingSmall", + "attributes": { + "category": "size", + "type": "padding", + "item": "small" + }, + "path": [ + "size", + "padding", + "small" + ] + }, + "medium": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingMedium", + "attributes": { + "category": "size", + "type": "padding", + "item": "medium" + }, + "path": [ + "size", + "padding", + "medium" + ] + }, + "large": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingLarge", + "attributes": { + "category": "size", + "type": "padding", + "item": "large" + }, + "path": [ + "size", + "padding", + "large" + ] + }, + "xl": { + "value": "1rem", + "type": "dimension", + "filePath": "__integration__/tokens/size/padding.json", + "isSource": true, + "original": { + "value": 1, + "type": "dimension" + }, + "name": "SizePaddingXl", + "attributes": { + "category": "size", + "type": "padding", + "item": "xl" + }, + "path": [ + "size", + "padding", + "xl" + ] + } + } + } + }, + "platform": { + "transformGroup": "js", + "buildPath": "__integration__/build/", + "options": { + "otherOption": "platform option" + }, + "files": [ + { + "destination": "registerCustomFormatWithNewArgs.json", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + } + ], + "log": { + "warnings": "warn", + "verbosity": "default", + "errors": { + "brokenReferences": "throw" + } + }, + "transforms": [ + { + "type": "attribute" + }, + { + "type": "name" + }, + { + "type": "value" + }, + { + "type": "value" + } + ], + "actions": [] + }, + "file": { + "options": { + "otherOption": "Test", + "showFileHeader": true + }, + "destination": "registerCustomFormatWithNewArgs.json" + }, + "options": { + "hooks": { + "parsers": {}, + "preprocessors": {}, + "transformGroups": { + "web": [ + "attribute/cti", + "name/kebab", + "size/px", + "color/css" + ], + "js": [ + "attribute/cti", + "name/pascal", + "size/rem", + "color/hex" + ], + "scss": [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "size/rem", + "color/css", + "asset/url", + "fontFamily/css", + "cubicBezier/css", + "strokeStyle/css/shorthand", + "border/css/shorthand", + "typography/css/shorthand", + "transition/css/shorthand", + "shadow/css/shorthand" + ], + "css": [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "size/rem", + "color/css", + "asset/url", + "fontFamily/css", + "cubicBezier/css", + "strokeStyle/css/shorthand", + "border/css/shorthand", + "typography/css/shorthand", + "transition/css/shorthand", + "shadow/css/shorthand" + ], + "less": [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "size/rem", + "color/hex", + "asset/url", + "fontFamily/css", + "cubicBezier/css", + "strokeStyle/css/shorthand", + "border/css/shorthand", + "typography/css/shorthand", + "transition/css/shorthand", + "shadow/css/shorthand" + ], + "html": [ + "attribute/cti", + "attribute/color", + "name/human" + ], + "android": [ + "attribute/cti", + "name/snake", + "color/hex8android", + "size/remToSp", + "size/remToDp" + ], + "compose": [ + "attribute/cti", + "name/camel", + "color/composeColor", + "size/compose/em", + "size/compose/remToSp", + "size/compose/remToDp" + ], + "ios": [ + "attribute/cti", + "name/pascal", + "color/UIColor", + "content/objC/literal", + "asset/objC/literal", + "size/remToPt" + ], + "ios-swift": [ + "attribute/cti", + "name/camel", + "color/UIColorSwift", + "content/swift/literal", + "asset/swift/literal", + "size/swift/remToCGFloat" + ], + "ios-swift-separate": [ + "attribute/cti", + "name/camel", + "color/UIColorSwift", + "content/swift/literal", + "asset/swift/literal", + "size/swift/remToCGFloat" + ], + "assets": [ + "attribute/cti" + ], + "flutter": [ + "attribute/cti", + "name/camel", + "color/hex8flutter", + "size/flutter/remToDouble", + "content/flutter/literal", + "asset/flutter/literal" + ], + "flutter-separate": [ + "attribute/cti", + "name/camel", + "color/hex8flutter", + "size/flutter/remToDouble", + "content/flutter/literal", + "asset/flutter/literal" + ], + "react-native": [ + "name/camel", + "color/css", + "size/object" + ] + }, + "transforms": { + "attribute/cti": { + "type": "attribute" + }, + "attribute/color": { + "type": "attribute" + }, + "name/human": { + "type": "name" + }, + "name/camel": { + "type": "name" + }, + "name/kebab": { + "type": "name" + }, + "name/snake": { + "type": "name" + }, + "name/constant": { + "type": "name" + }, + "name/pascal": { + "type": "name" + }, + "color/rgb": { + "type": "value" + }, + "color/hsl": { + "type": "value" + }, + "color/hsl-4": { + "type": "value" + }, + "color/hex": { + "type": "value" + }, + "color/hex8": { + "type": "value" + }, + "color/hex8android": { + "type": "value" + }, + "color/composeColor": { + "type": "value" + }, + "color/UIColor": { + "type": "value" + }, + "color/UIColorSwift": { + "type": "value" + }, + "color/ColorSwiftUI": { + "type": "value" + }, + "color/css": { + "type": "value" + }, + "color/sketch": { + "type": "value" + }, + "size/sp": { + "type": "value" + }, + "size/dp": { + "type": "value" + }, + "size/object": { + "type": "value" + }, + "size/remToSp": { + "type": "value" + }, + "size/remToDp": { + "type": "value" + }, + "size/px": { + "type": "value" + }, + "size/rem": { + "type": "value" + }, + "size/remToPt": { + "type": "value" + }, + "size/compose/remToSp": { + "type": "value" + }, + "size/compose/remToDp": { + "type": "value" + }, + "size/compose/em": { + "type": "value" + }, + "size/swift/remToCGFloat": { + "type": "value" + }, + "size/remToPx": { + "type": "value" + }, + "size/pxToRem": { + "type": "value" + }, + "html/icon": { + "type": "value" + }, + "content/quote": { + "type": "value" + }, + "content/objC/literal": { + "type": "value" + }, + "content/swift/literal": { + "type": "value" + }, + "time/seconds": { + "type": "value" + }, + "fontFamily/css": { + "type": "value" + }, + "cubicBezier/css": { + "type": "value" + }, + "strokeStyle/css/shorthand": { + "type": "value", + "transitive": true + }, + "border/css/shorthand": { + "type": "value", + "transitive": true + }, + "typography/css/shorthand": { + "type": "value", + "transitive": true + }, + "transition/css/shorthand": { + "type": "value", + "transitive": true + }, + "shadow/css/shorthand": { + "type": "value", + "transitive": true + }, + "asset/url": { + "type": "value" + }, + "asset/base64": { + "type": "value" + }, + "asset/path": { + "type": "value" + }, + "asset/objC/literal": { + "type": "value" + }, + "asset/swift/literal": { + "type": "value" + }, + "color/hex8flutter": { + "type": "value" + }, + "content/flutter/literal": { + "type": "value" + }, + "asset/flutter/literal": { + "type": "value" + }, + "size/flutter/remToDouble": { + "type": "value" + } + }, + "formats": {}, + "fileHeaders": {}, + "filters": {}, + "actions": { + "android/copyImages": {}, + "copy_assets": {} + } + }, + "source": [ + "__integration__/tokens/size/padding.json" + ], + "platforms": { + "inlineCustomFormats": { + "transformGroup": "js", + "buildPath": "__integration__/build/", + "options": { + "otherOption": "platform option" + }, + "files": [ + { + "destination": "inlineCustomFormatWithOldArgs.json", + "format": "inlineCustomFormatWithOldArgs", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + }, + { + "destination": "inlineCustomFormatWithNewArgs.json", + "format": "inlineCustomFormatWithNewArgs", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + } + ] + }, + "customFormats": { + "transformGroup": "js", + "buildPath": "__integration__/build/", + "options": { + "otherOption": "platform option" + }, + "files": [ + { + "destination": "registerCustomFormatWithNewArgs.json", + "format": "registerCustomFormatWithNewArgs", + "options": { + "showFileHeader": true, + "otherOption": "Test" + } + } + ] + } + }, + "log": { + "warnings": "warn", + "verbosity": "default", + "errors": { + "brokenReferences": "throw" + } + }, + "usesDtcg": false, + "otherOption": "Test", + "showFileHeader": true + } +}`; +/* end snapshot integration custom formats register custom format with new args should match snapshot */ + diff --git a/__integration__/__snapshots__/flutter.test.js.snap b/__integration__/__snapshots__/flutter.test.snap.js similarity index 65% rename from __integration__/__snapshots__/flutter.test.js.snap rename to __integration__/__snapshots__/flutter.test.snap.js index fdb6fbc35..0f33c5397 100644 --- a/__integration__/__snapshots__/flutter.test.js.snap +++ b/__integration__/__snapshots__/flutter.test.snap.js @@ -1,193 +1,20 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; -exports[`integration flutter flutter/class.dart separate should match snapshot 1`] = ` -" -// -// style_dictionary_color.dart -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - - -import 'dart:ui'; - -class StyleDictionaryColor { - StyleDictionaryColor._(); - - static const backgroundDanger = Color(0xFFFFEAE9); - static const backgroundDisabled = Color(0xFFDEE1E1); - static const backgroundInfo = Color(0xFFE9F8FF); - static const backgroundPrimary = Color(0xFFFFFFFF); - static const backgroundSecondary = Color(0xFFF3F4F4); - static const backgroundSuccess = Color(0xFFEBF9EB); - static const backgroundTertiary = Color(0xFFDEE1E1); - static const backgroundWarning = Color(0xFFFFEDE3); - static const borderPrimary = Color(0xFFC8CCCC); - static const brandPrimary = Color(0xFF0B8599); - static const brandSecondary = Color(0xFF6F5ED3); - static const coreAqua0 = Color(0xFFD9FCFB); - static const coreAqua100 = Color(0xFFC5F9F9); - static const coreAqua1000 = Color(0xFF083D4F); - static const coreAqua1100 = Color(0xFF002838); - static const coreAqua200 = Color(0xFFA5F2F2); - static const coreAqua300 = Color(0xFF76E5E2); - static const coreAqua400 = Color(0xFF33D6E2); - static const coreAqua500 = Color(0xFF17B8CE); - static const coreAqua600 = Color(0xFF0797AE); - static const coreAqua700 = Color(0xFF0B8599); - static const coreAqua800 = Color(0xFF0F6E84); - static const coreAqua900 = Color(0xFF035E73); - static const coreBlue0 = Color(0xFFE9F8FF); - static const coreBlue100 = Color(0xFFDCF2FF); - static const coreBlue1000 = Color(0xFF0A3960); - static const coreBlue1100 = Color(0xFF002138); - static const coreBlue200 = Color(0xFFC7E4F9); - static const coreBlue300 = Color(0xFFA1D2F8); - static const coreBlue400 = Color(0xFF56ADF5); - static const coreBlue500 = Color(0xFF3896E3); - static const coreBlue600 = Color(0xFF2B87D3); - static const coreBlue700 = Color(0xFF2079C3); - static const coreBlue800 = Color(0xFF116DAA); - static const coreBlue900 = Color(0xFF0C5689); - static const coreGreen0 = Color(0xFFEBF9EB); - static const coreGreen100 = Color(0xFFD7F4D7); - static const coreGreen1000 = Color(0xFF08422F); - static const coreGreen1100 = Color(0xFF002B20); - static const coreGreen200 = Color(0xFFC2F2BD); - static const coreGreen300 = Color(0xFF98E58E); - static const coreGreen400 = Color(0xFF75DD66); - static const coreGreen500 = Color(0xFF59CB59); - static const coreGreen600 = Color(0xFF2BB656); - static const coreGreen700 = Color(0xFF0CA750); - static const coreGreen800 = Color(0xFF008B46); - static const coreGreen900 = Color(0xFF006B40); - static const coreMagenta0 = Color(0xFFFEF0FF); - static const coreMagenta100 = Color(0xFFF9E3FC); - static const coreMagenta1000 = Color(0xFF451551); - static const coreMagenta1100 = Color(0xFF29192D); - static const coreMagenta200 = Color(0xFFF4C4F7); - static const coreMagenta300 = Color(0xFFEDADF2); - static const coreMagenta400 = Color(0xFFF282F5); - static const coreMagenta500 = Color(0xFFDB61DB); - static const coreMagenta600 = Color(0xFFC44EB9); - static const coreMagenta700 = Color(0xFFAC44A8); - static const coreMagenta800 = Color(0xFF8F3896); - static const coreMagenta900 = Color(0xFF6C2277); - static const coreNeutral0 = Color(0xFFFFFFFF); - static const coreNeutral100 = Color(0xFFF3F4F4); - static const coreNeutral1000 = Color(0xFF162020); - static const coreNeutral1100 = Color(0xFF040404); - static const coreNeutral200 = Color(0xFFDEE1E1); - static const coreNeutral300 = Color(0xFFC8CCCC); - static const coreNeutral400 = Color(0xFFB0B6B7); - static const coreNeutral500 = Color(0xFF929A9B); - static const coreNeutral600 = Color(0xFF6E797A); - static const coreNeutral700 = Color(0xFF515E5F); - static const coreNeutral800 = Color(0xFF364141); - static const coreNeutral900 = Color(0xFF273333); - static const coreOrange0 = Color(0xFFFFEDE3); - static const coreOrange100 = Color(0xFFFCDCCC); - static const coreOrange1000 = Color(0xFF601700); - static const coreOrange1100 = Color(0xFF2D130E); - static const coreOrange200 = Color(0xFFFFC6A4); - static const coreOrange300 = Color(0xFFFFB180); - static const coreOrange400 = Color(0xFFFF9C5D); - static const coreOrange500 = Color(0xFFFC8943); - static const coreOrange600 = Color(0xFFF57D33); - static const coreOrange700 = Color(0xFFED7024); - static const coreOrange800 = Color(0xFFCE5511); - static const coreOrange900 = Color(0xFF962C0B); - static const corePink0 = Color(0xFFFFE9F3); - static const corePink100 = Color(0xFFFCDBEB); - static const corePink1000 = Color(0xFF561231); - static const corePink1100 = Color(0xFF2B1721); - static const corePink200 = Color(0xFFFFB5D5); - static const corePink300 = Color(0xFFFF95C1); - static const corePink400 = Color(0xFFFF76AE); - static const corePink500 = Color(0xFFEF588B); - static const corePink600 = Color(0xFFE0447C); - static const corePink700 = Color(0xFFCE3665); - static const corePink800 = Color(0xFFB22F5B); - static const corePink900 = Color(0xFF931847); - static const corePurple0 = Color(0xFFF2F2F9); - static const corePurple100 = Color(0xFFEAEAF9); - static const corePurple1000 = Color(0xFF2D246B); - static const corePurple1100 = Color(0xFF1D1D38); - static const corePurple200 = Color(0xFFD8D7F9); - static const corePurple300 = Color(0xFFC1C1F7); - static const corePurple400 = Color(0xFFA193F2); - static const corePurple500 = Color(0xFF9180F4); - static const corePurple600 = Color(0xFF816FEA); - static const corePurple700 = Color(0xFF6F5ED3); - static const corePurple800 = Color(0xFF5E4EBA); - static const corePurple900 = Color(0xFF483A9C); - static const coreRed0 = Color(0xFFFFEAE9); - static const coreRed100 = Color(0xFFFFD5D2); - static const coreRed1000 = Color(0xFF6D1313); - static const coreRed1100 = Color(0xFF2B1111); - static const coreRed200 = Color(0xFFFFB8B1); - static const coreRed300 = Color(0xFFFF9C8F); - static const coreRed400 = Color(0xFFFF7F6E); - static const coreRed500 = Color(0xFFF76054); - static const coreRed600 = Color(0xFFED4C42); - static const coreRed700 = Color(0xFFDB3E3E); - static const coreRed800 = Color(0xFFC63434); - static const coreRed900 = Color(0xFF992222); - static const coreTeal0 = Color(0xFFE5F9F5); - static const coreTeal100 = Color(0xFFCDF7EF); - static const coreTeal1000 = Color(0xFF083F3F); - static const coreTeal1100 = Color(0xFF002528); - static const coreTeal200 = Color(0xFFB3F2E6); - static const coreTeal300 = Color(0xFF7DEAD5); - static const coreTeal400 = Color(0xFF24E0C5); - static const coreTeal500 = Color(0xFF08C4B2); - static const coreTeal600 = Color(0xFF00A99C); - static const coreTeal700 = Color(0xFF0B968F); - static const coreTeal800 = Color(0xFF067C7C); - static const coreTeal900 = Color(0xFF026661); - static const coreYellow0 = Color(0xFFFFF8E2); - static const coreYellow100 = Color(0xFFFDEFCD); - static const coreYellow1000 = Color(0xFF542A00); - static const coreYellow1100 = Color(0xFF2D1A05); - static const coreYellow200 = Color(0xFFFFE99A); - static const coreYellow300 = Color(0xFFFFE16E); - static const coreYellow400 = Color(0xFFFFD943); - static const coreYellow500 = Color(0xFFFFCD1C); - static const coreYellow600 = Color(0xFFFFBC00); - static const coreYellow700 = Color(0xFFDD9903); - static const coreYellow800 = Color(0xFFBA7506); - static const coreYellow900 = Color(0xFF944C0C); - static const fontDanger = Color(0xFF6D1313); - static const fontInteractive = Color(0xFF0B8599); - static const fontInteractiveActive = Color(0xFF6F5ED3); - static const fontInteractiveDisabled = Color(0xFF364141); - static const fontInteractiveHover = Color(0xFF0B8599); - static const fontPrimary = Color(0xFF040404); - static const fontSecondary = Color(0xFF273333); - static const fontSuccess = Color(0xFF08422F); - static const fontTertiary = Color(0xFF364141); - static const fontWarning = Color(0xFF601700); -} -" -`; - -exports[`integration flutter flutter/class.dart should match snapshot 1`] = ` -" +snapshots["integration flutter flutter/class.dart should match snapshot"] = +` // // style_dictionary.dart // -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +// Do not edit directly, this file was auto-generated. import 'dart:ui'; class StyleDictionary { - StyleDictionary._(); + StyleDictionary._(); static const colorBackgroundDanger = Color(0xFFFFEAE9); static const colorBackgroundDisabled = Color(0xFFDEE1E1); @@ -351,25 +178,23 @@ class StyleDictionary { static const sizePaddingMedium = 16.00; static const sizePaddingSmall = 8.00; static const sizePaddingXl = 16.00; -} -" -`; +}`; +/* end snapshot integration flutter flutter/class.dart should match snapshot */ -exports[`integration flutter flutter/class.dart with references should match snapshot 1`] = ` -" +snapshots["integration flutter flutter/class.dart with references should match snapshot"] = +` // // style_dictionary_with_references.dart // -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +// Do not edit directly, this file was auto-generated. import 'dart:ui'; class StyleDictionary { - StyleDictionary._(); + StyleDictionary._(); static const sizePaddingXl = 16.00; static const sizePaddingLarge = 16.00; @@ -533,6 +358,177 @@ class StyleDictionary { static const colorFontInteractiveHover = colorBrandPrimary; static const colorFontInteractive = colorBrandPrimary; static const colorBackgroundDisabled = colorBackgroundTertiary; -} -" -`; +}`; +/* end snapshot integration flutter flutter/class.dart with references should match snapshot */ + +snapshots["integration flutter flutter/class.dart separate should match snapshot"] = +` +// +// style_dictionary_color.dart +// + +// Do not edit directly, this file was auto-generated. + + + +import 'dart:ui'; + +class StyleDictionaryColor { + StyleDictionaryColor._(); + + static const colorBackgroundDanger = Color(0xFFFFEAE9); + static const colorBackgroundDisabled = Color(0xFFDEE1E1); + static const colorBackgroundInfo = Color(0xFFE9F8FF); + static const colorBackgroundPrimary = Color(0xFFFFFFFF); + static const colorBackgroundSecondary = Color(0xFFF3F4F4); + static const colorBackgroundSuccess = Color(0xFFEBF9EB); + static const colorBackgroundTertiary = Color(0xFFDEE1E1); + static const colorBackgroundWarning = Color(0xFFFFEDE3); + static const colorBorderPrimary = Color(0xFFC8CCCC); + static const colorBrandPrimary = Color(0xFF0B8599); + static const colorBrandSecondary = Color(0xFF6F5ED3); + static const colorCoreAqua0 = Color(0xFFD9FCFB); + static const colorCoreAqua100 = Color(0xFFC5F9F9); + static const colorCoreAqua1000 = Color(0xFF083D4F); + static const colorCoreAqua1100 = Color(0xFF002838); + static const colorCoreAqua200 = Color(0xFFA5F2F2); + static const colorCoreAqua300 = Color(0xFF76E5E2); + static const colorCoreAqua400 = Color(0xFF33D6E2); + static const colorCoreAqua500 = Color(0xFF17B8CE); + static const colorCoreAqua600 = Color(0xFF0797AE); + static const colorCoreAqua700 = Color(0xFF0B8599); + static const colorCoreAqua800 = Color(0xFF0F6E84); + static const colorCoreAqua900 = Color(0xFF035E73); + static const colorCoreBlue0 = Color(0xFFE9F8FF); + static const colorCoreBlue100 = Color(0xFFDCF2FF); + static const colorCoreBlue1000 = Color(0xFF0A3960); + static const colorCoreBlue1100 = Color(0xFF002138); + static const colorCoreBlue200 = Color(0xFFC7E4F9); + static const colorCoreBlue300 = Color(0xFFA1D2F8); + static const colorCoreBlue400 = Color(0xFF56ADF5); + static const colorCoreBlue500 = Color(0xFF3896E3); + static const colorCoreBlue600 = Color(0xFF2B87D3); + static const colorCoreBlue700 = Color(0xFF2079C3); + static const colorCoreBlue800 = Color(0xFF116DAA); + static const colorCoreBlue900 = Color(0xFF0C5689); + static const colorCoreGreen0 = Color(0xFFEBF9EB); + static const colorCoreGreen100 = Color(0xFFD7F4D7); + static const colorCoreGreen1000 = Color(0xFF08422F); + static const colorCoreGreen1100 = Color(0xFF002B20); + static const colorCoreGreen200 = Color(0xFFC2F2BD); + static const colorCoreGreen300 = Color(0xFF98E58E); + static const colorCoreGreen400 = Color(0xFF75DD66); + static const colorCoreGreen500 = Color(0xFF59CB59); + static const colorCoreGreen600 = Color(0xFF2BB656); + static const colorCoreGreen700 = Color(0xFF0CA750); + static const colorCoreGreen800 = Color(0xFF008B46); + static const colorCoreGreen900 = Color(0xFF006B40); + static const colorCoreMagenta0 = Color(0xFFFEF0FF); + static const colorCoreMagenta100 = Color(0xFFF9E3FC); + static const colorCoreMagenta1000 = Color(0xFF451551); + static const colorCoreMagenta1100 = Color(0xFF29192D); + static const colorCoreMagenta200 = Color(0xFFF4C4F7); + static const colorCoreMagenta300 = Color(0xFFEDADF2); + static const colorCoreMagenta400 = Color(0xFFF282F5); + static const colorCoreMagenta500 = Color(0xFFDB61DB); + static const colorCoreMagenta600 = Color(0xFFC44EB9); + static const colorCoreMagenta700 = Color(0xFFAC44A8); + static const colorCoreMagenta800 = Color(0xFF8F3896); + static const colorCoreMagenta900 = Color(0xFF6C2277); + static const colorCoreNeutral0 = Color(0xFFFFFFFF); + static const colorCoreNeutral100 = Color(0xFFF3F4F4); + static const colorCoreNeutral1000 = Color(0xFF162020); + static const colorCoreNeutral1100 = Color(0xFF040404); + static const colorCoreNeutral200 = Color(0xFFDEE1E1); + static const colorCoreNeutral300 = Color(0xFFC8CCCC); + static const colorCoreNeutral400 = Color(0xFFB0B6B7); + static const colorCoreNeutral500 = Color(0xFF929A9B); + static const colorCoreNeutral600 = Color(0xFF6E797A); + static const colorCoreNeutral700 = Color(0xFF515E5F); + static const colorCoreNeutral800 = Color(0xFF364141); + static const colorCoreNeutral900 = Color(0xFF273333); + static const colorCoreOrange0 = Color(0xFFFFEDE3); + static const colorCoreOrange100 = Color(0xFFFCDCCC); + static const colorCoreOrange1000 = Color(0xFF601700); + static const colorCoreOrange1100 = Color(0xFF2D130E); + static const colorCoreOrange200 = Color(0xFFFFC6A4); + static const colorCoreOrange300 = Color(0xFFFFB180); + static const colorCoreOrange400 = Color(0xFFFF9C5D); + static const colorCoreOrange500 = Color(0xFFFC8943); + static const colorCoreOrange600 = Color(0xFFF57D33); + static const colorCoreOrange700 = Color(0xFFED7024); + static const colorCoreOrange800 = Color(0xFFCE5511); + static const colorCoreOrange900 = Color(0xFF962C0B); + static const colorCorePink0 = Color(0xFFFFE9F3); + static const colorCorePink100 = Color(0xFFFCDBEB); + static const colorCorePink1000 = Color(0xFF561231); + static const colorCorePink1100 = Color(0xFF2B1721); + static const colorCorePink200 = Color(0xFFFFB5D5); + static const colorCorePink300 = Color(0xFFFF95C1); + static const colorCorePink400 = Color(0xFFFF76AE); + static const colorCorePink500 = Color(0xFFEF588B); + static const colorCorePink600 = Color(0xFFE0447C); + static const colorCorePink700 = Color(0xFFCE3665); + static const colorCorePink800 = Color(0xFFB22F5B); + static const colorCorePink900 = Color(0xFF931847); + static const colorCorePurple0 = Color(0xFFF2F2F9); + static const colorCorePurple100 = Color(0xFFEAEAF9); + static const colorCorePurple1000 = Color(0xFF2D246B); + static const colorCorePurple1100 = Color(0xFF1D1D38); + static const colorCorePurple200 = Color(0xFFD8D7F9); + static const colorCorePurple300 = Color(0xFFC1C1F7); + static const colorCorePurple400 = Color(0xFFA193F2); + static const colorCorePurple500 = Color(0xFF9180F4); + static const colorCorePurple600 = Color(0xFF816FEA); + static const colorCorePurple700 = Color(0xFF6F5ED3); + static const colorCorePurple800 = Color(0xFF5E4EBA); + static const colorCorePurple900 = Color(0xFF483A9C); + static const colorCoreRed0 = Color(0xFFFFEAE9); + static const colorCoreRed100 = Color(0xFFFFD5D2); + static const colorCoreRed1000 = Color(0xFF6D1313); + static const colorCoreRed1100 = Color(0xFF2B1111); + static const colorCoreRed200 = Color(0xFFFFB8B1); + static const colorCoreRed300 = Color(0xFFFF9C8F); + static const colorCoreRed400 = Color(0xFFFF7F6E); + static const colorCoreRed500 = Color(0xFFF76054); + static const colorCoreRed600 = Color(0xFFED4C42); + static const colorCoreRed700 = Color(0xFFDB3E3E); + static const colorCoreRed800 = Color(0xFFC63434); + static const colorCoreRed900 = Color(0xFF992222); + static const colorCoreTeal0 = Color(0xFFE5F9F5); + static const colorCoreTeal100 = Color(0xFFCDF7EF); + static const colorCoreTeal1000 = Color(0xFF083F3F); + static const colorCoreTeal1100 = Color(0xFF002528); + static const colorCoreTeal200 = Color(0xFFB3F2E6); + static const colorCoreTeal300 = Color(0xFF7DEAD5); + static const colorCoreTeal400 = Color(0xFF24E0C5); + static const colorCoreTeal500 = Color(0xFF08C4B2); + static const colorCoreTeal600 = Color(0xFF00A99C); + static const colorCoreTeal700 = Color(0xFF0B968F); + static const colorCoreTeal800 = Color(0xFF067C7C); + static const colorCoreTeal900 = Color(0xFF026661); + static const colorCoreYellow0 = Color(0xFFFFF8E2); + static const colorCoreYellow100 = Color(0xFFFDEFCD); + static const colorCoreYellow1000 = Color(0xFF542A00); + static const colorCoreYellow1100 = Color(0xFF2D1A05); + static const colorCoreYellow200 = Color(0xFFFFE99A); + static const colorCoreYellow300 = Color(0xFFFFE16E); + static const colorCoreYellow400 = Color(0xFFFFD943); + static const colorCoreYellow500 = Color(0xFFFFCD1C); + static const colorCoreYellow600 = Color(0xFFFFBC00); + static const colorCoreYellow700 = Color(0xFFDD9903); + static const colorCoreYellow800 = Color(0xFFBA7506); + static const colorCoreYellow900 = Color(0xFF944C0C); + static const colorFontDanger = Color(0xFF6D1313); + static const colorFontInteractive = Color(0xFF0B8599); + static const colorFontInteractiveActive = Color(0xFF6F5ED3); + static const colorFontInteractiveDisabled = Color(0xFF364141); + static const colorFontInteractiveHover = Color(0xFF0B8599); + static const colorFontPrimary = Color(0xFF040404); + static const colorFontSecondary = Color(0xFF273333); + static const colorFontSuccess = Color(0xFF08422F); + static const colorFontTertiary = Color(0xFF364141); + static const colorFontWarning = Color(0xFF601700); +}`; +/* end snapshot integration flutter flutter/class.dart separate should match snapshot */ + diff --git a/__integration__/__snapshots__/iOSObjectiveC.test.js.snap b/__integration__/__snapshots__/iOSObjectiveC.test.js.snap deleted file mode 100644 index 2b1d7a3d3..000000000 --- a/__integration__/__snapshots__/iOSObjectiveC.test.js.snap +++ /dev/null @@ -1,1975 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration ios objective-c ios/color.h should match snapshot 1`] = ` -" -// -// color.h -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import - -typedef NS_ENUM(NSInteger, StyleDictionaryColorName) { -ColorBackgroundPrimary, -ColorBackgroundSecondary, -ColorBackgroundTertiary, -ColorBackgroundDanger, -ColorBackgroundWarning, -ColorBackgroundSuccess, -ColorBackgroundInfo, -ColorBackgroundDisabled, -ColorBorderPrimary, -ColorBrandPrimary, -ColorBrandSecondary, -ColorCoreGreen0, -ColorCoreGreen100, -ColorCoreGreen200, -ColorCoreGreen300, -ColorCoreGreen400, -ColorCoreGreen500, -ColorCoreGreen600, -ColorCoreGreen700, -ColorCoreGreen800, -ColorCoreGreen900, -ColorCoreGreen1000, -ColorCoreGreen1100, -ColorCoreTeal0, -ColorCoreTeal100, -ColorCoreTeal200, -ColorCoreTeal300, -ColorCoreTeal400, -ColorCoreTeal500, -ColorCoreTeal600, -ColorCoreTeal700, -ColorCoreTeal800, -ColorCoreTeal900, -ColorCoreTeal1000, -ColorCoreTeal1100, -ColorCoreAqua0, -ColorCoreAqua100, -ColorCoreAqua200, -ColorCoreAqua300, -ColorCoreAqua400, -ColorCoreAqua500, -ColorCoreAqua600, -ColorCoreAqua700, -ColorCoreAqua800, -ColorCoreAqua900, -ColorCoreAqua1000, -ColorCoreAqua1100, -ColorCoreBlue0, -ColorCoreBlue100, -ColorCoreBlue200, -ColorCoreBlue300, -ColorCoreBlue400, -ColorCoreBlue500, -ColorCoreBlue600, -ColorCoreBlue700, -ColorCoreBlue800, -ColorCoreBlue900, -ColorCoreBlue1000, -ColorCoreBlue1100, -ColorCorePurple0, -ColorCorePurple100, -ColorCorePurple200, -ColorCorePurple300, -ColorCorePurple400, -ColorCorePurple500, -ColorCorePurple600, -ColorCorePurple700, -ColorCorePurple800, -ColorCorePurple900, -ColorCorePurple1000, -ColorCorePurple1100, -ColorCoreMagenta0, -ColorCoreMagenta100, -ColorCoreMagenta200, -ColorCoreMagenta300, -ColorCoreMagenta400, -ColorCoreMagenta500, -ColorCoreMagenta600, -ColorCoreMagenta700, -ColorCoreMagenta800, -ColorCoreMagenta900, -ColorCoreMagenta1000, -ColorCoreMagenta1100, -ColorCorePink0, -ColorCorePink100, -ColorCorePink200, -ColorCorePink300, -ColorCorePink400, -ColorCorePink500, -ColorCorePink600, -ColorCorePink700, -ColorCorePink800, -ColorCorePink900, -ColorCorePink1000, -ColorCorePink1100, -ColorCoreRed0, -ColorCoreRed100, -ColorCoreRed200, -ColorCoreRed300, -ColorCoreRed400, -ColorCoreRed500, -ColorCoreRed600, -ColorCoreRed700, -ColorCoreRed800, -ColorCoreRed900, -ColorCoreRed1000, -ColorCoreRed1100, -ColorCoreOrange0, -ColorCoreOrange100, -ColorCoreOrange200, -ColorCoreOrange300, -ColorCoreOrange400, -ColorCoreOrange500, -ColorCoreOrange600, -ColorCoreOrange700, -ColorCoreOrange800, -ColorCoreOrange900, -ColorCoreOrange1000, -ColorCoreOrange1100, -ColorCoreNeutral0, -ColorCoreNeutral100, -ColorCoreNeutral200, -ColorCoreNeutral300, -ColorCoreNeutral400, -ColorCoreNeutral500, -ColorCoreNeutral600, -ColorCoreNeutral700, -ColorCoreNeutral800, -ColorCoreNeutral900, -ColorCoreNeutral1000, -ColorCoreNeutral1100, -ColorCoreYellow0, -ColorCoreYellow100, -ColorCoreYellow200, -ColorCoreYellow300, -ColorCoreYellow400, -ColorCoreYellow500, -ColorCoreYellow600, -ColorCoreYellow700, -ColorCoreYellow800, -ColorCoreYellow900, -ColorCoreYellow1000, -ColorCoreYellow1100, -ColorFontPrimary, -ColorFontSecondary, -ColorFontTertiary, -ColorFontInteractive, -ColorFontInteractiveHover, -ColorFontInteractiveActive, -ColorFontInteractiveDisabled, -ColorFontDanger, -ColorFontWarning, -ColorFontSuccess -}; - -@interface StyleDictionaryColor : NSObject -+ (NSArray *)values; -+ (UIColor *)color:(StyleDictionaryColorName)color; -@end -" -`; - -exports[`integration ios objective-c ios/color.m should match snapshot 1`] = ` -" -// -// color.m -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\"StyleDictionaryColor.h\\" - -@implementation StyleDictionaryColor - -+ (UIColor *)color:(StyleDictionaryColorName)colorEnum{ - return [[self values] objectAtIndex:colorEnum]; -} - -+ (NSArray *)values { - static NSArray* colorArray; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - colorArray = @[ -[UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], -[UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], -[UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], -[UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], -[UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], -[UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], -[UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], -[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], -[UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], -[UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], -[UIColor colorWithRed:0.843f green:0.957f blue:0.843f alpha:1.000f], -[UIColor colorWithRed:0.761f green:0.949f blue:0.741f alpha:1.000f], -[UIColor colorWithRed:0.596f green:0.898f blue:0.557f alpha:1.000f], -[UIColor colorWithRed:0.459f green:0.867f blue:0.400f alpha:1.000f], -[UIColor colorWithRed:0.349f green:0.796f blue:0.349f alpha:1.000f], -[UIColor colorWithRed:0.169f green:0.714f blue:0.337f alpha:1.000f], -[UIColor colorWithRed:0.047f green:0.655f blue:0.314f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.545f blue:0.275f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.420f blue:0.251f alpha:1.000f], -[UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.169f blue:0.125f alpha:1.000f], -[UIColor colorWithRed:0.898f green:0.976f blue:0.961f alpha:1.000f], -[UIColor colorWithRed:0.804f green:0.969f blue:0.937f alpha:1.000f], -[UIColor colorWithRed:0.702f green:0.949f blue:0.902f alpha:1.000f], -[UIColor colorWithRed:0.490f green:0.918f blue:0.835f alpha:1.000f], -[UIColor colorWithRed:0.141f green:0.878f blue:0.773f alpha:1.000f], -[UIColor colorWithRed:0.031f green:0.769f blue:0.698f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.663f blue:0.612f alpha:1.000f], -[UIColor colorWithRed:0.043f green:0.588f blue:0.561f alpha:1.000f], -[UIColor colorWithRed:0.024f green:0.486f blue:0.486f alpha:1.000f], -[UIColor colorWithRed:0.008f green:0.400f blue:0.380f alpha:1.000f], -[UIColor colorWithRed:0.031f green:0.247f blue:0.247f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.145f blue:0.157f alpha:1.000f], -[UIColor colorWithRed:0.851f green:0.988f blue:0.984f alpha:1.000f], -[UIColor colorWithRed:0.773f green:0.976f blue:0.976f alpha:1.000f], -[UIColor colorWithRed:0.647f green:0.949f blue:0.949f alpha:1.000f], -[UIColor colorWithRed:0.463f green:0.898f blue:0.886f alpha:1.000f], -[UIColor colorWithRed:0.200f green:0.839f blue:0.886f alpha:1.000f], -[UIColor colorWithRed:0.090f green:0.722f blue:0.808f alpha:1.000f], -[UIColor colorWithRed:0.027f green:0.592f blue:0.682f alpha:1.000f], -[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], -[UIColor colorWithRed:0.059f green:0.431f blue:0.518f alpha:1.000f], -[UIColor colorWithRed:0.012f green:0.369f blue:0.451f alpha:1.000f], -[UIColor colorWithRed:0.031f green:0.239f blue:0.310f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.157f blue:0.220f alpha:1.000f], -[UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], -[UIColor colorWithRed:0.863f green:0.949f blue:1.000f alpha:1.000f], -[UIColor colorWithRed:0.780f green:0.894f blue:0.976f alpha:1.000f], -[UIColor colorWithRed:0.631f green:0.824f blue:0.973f alpha:1.000f], -[UIColor colorWithRed:0.337f green:0.678f blue:0.961f alpha:1.000f], -[UIColor colorWithRed:0.220f green:0.588f blue:0.890f alpha:1.000f], -[UIColor colorWithRed:0.169f green:0.529f blue:0.827f alpha:1.000f], -[UIColor colorWithRed:0.125f green:0.475f blue:0.765f alpha:1.000f], -[UIColor colorWithRed:0.067f green:0.427f blue:0.667f alpha:1.000f], -[UIColor colorWithRed:0.047f green:0.337f blue:0.537f alpha:1.000f], -[UIColor colorWithRed:0.039f green:0.224f blue:0.376f alpha:1.000f], -[UIColor colorWithRed:0.000f green:0.129f blue:0.220f alpha:1.000f], -[UIColor colorWithRed:0.949f green:0.949f blue:0.976f alpha:1.000f], -[UIColor colorWithRed:0.918f green:0.918f blue:0.976f alpha:1.000f], -[UIColor colorWithRed:0.847f green:0.843f blue:0.976f alpha:1.000f], -[UIColor colorWithRed:0.757f green:0.757f blue:0.969f alpha:1.000f], -[UIColor colorWithRed:0.631f green:0.576f blue:0.949f alpha:1.000f], -[UIColor colorWithRed:0.569f green:0.502f blue:0.957f alpha:1.000f], -[UIColor colorWithRed:0.506f green:0.435f blue:0.918f alpha:1.000f], -[UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], -[UIColor colorWithRed:0.369f green:0.306f blue:0.729f alpha:1.000f], -[UIColor colorWithRed:0.282f green:0.227f blue:0.612f alpha:1.000f], -[UIColor colorWithRed:0.176f green:0.141f blue:0.420f alpha:1.000f], -[UIColor colorWithRed:0.114f green:0.114f blue:0.220f alpha:1.000f], -[UIColor colorWithRed:0.996f green:0.941f blue:1.000f alpha:1.000f], -[UIColor colorWithRed:0.976f green:0.890f blue:0.988f alpha:1.000f], -[UIColor colorWithRed:0.957f green:0.769f blue:0.969f alpha:1.000f], -[UIColor colorWithRed:0.929f green:0.678f blue:0.949f alpha:1.000f], -[UIColor colorWithRed:0.949f green:0.510f blue:0.961f alpha:1.000f], -[UIColor colorWithRed:0.859f green:0.380f blue:0.859f alpha:1.000f], -[UIColor colorWithRed:0.769f green:0.306f blue:0.725f alpha:1.000f], -[UIColor colorWithRed:0.675f green:0.267f blue:0.659f alpha:1.000f], -[UIColor colorWithRed:0.561f green:0.220f blue:0.588f alpha:1.000f], -[UIColor colorWithRed:0.424f green:0.133f blue:0.467f alpha:1.000f], -[UIColor colorWithRed:0.271f green:0.082f blue:0.318f alpha:1.000f], -[UIColor colorWithRed:0.161f green:0.098f blue:0.176f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.914f blue:0.953f alpha:1.000f], -[UIColor colorWithRed:0.988f green:0.859f blue:0.922f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.710f blue:0.835f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.584f blue:0.757f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.463f blue:0.682f alpha:1.000f], -[UIColor colorWithRed:0.937f green:0.345f blue:0.545f alpha:1.000f], -[UIColor colorWithRed:0.878f green:0.267f blue:0.486f alpha:1.000f], -[UIColor colorWithRed:0.808f green:0.212f blue:0.396f alpha:1.000f], -[UIColor colorWithRed:0.698f green:0.184f blue:0.357f alpha:1.000f], -[UIColor colorWithRed:0.576f green:0.094f blue:0.278f alpha:1.000f], -[UIColor colorWithRed:0.337f green:0.071f blue:0.192f alpha:1.000f], -[UIColor colorWithRed:0.169f green:0.090f blue:0.129f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.835f blue:0.824f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.722f blue:0.694f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.612f blue:0.561f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.498f blue:0.431f alpha:1.000f], -[UIColor colorWithRed:0.969f green:0.376f blue:0.329f alpha:1.000f], -[UIColor colorWithRed:0.929f green:0.298f blue:0.259f alpha:1.000f], -[UIColor colorWithRed:0.859f green:0.243f blue:0.243f alpha:1.000f], -[UIColor colorWithRed:0.776f green:0.204f blue:0.204f alpha:1.000f], -[UIColor colorWithRed:0.600f green:0.133f blue:0.133f alpha:1.000f], -[UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], -[UIColor colorWithRed:0.169f green:0.067f blue:0.067f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], -[UIColor colorWithRed:0.988f green:0.863f blue:0.800f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.776f blue:0.643f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.694f blue:0.502f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.612f blue:0.365f alpha:1.000f], -[UIColor colorWithRed:0.988f green:0.537f blue:0.263f alpha:1.000f], -[UIColor colorWithRed:0.961f green:0.490f blue:0.200f alpha:1.000f], -[UIColor colorWithRed:0.929f green:0.439f blue:0.141f alpha:1.000f], -[UIColor colorWithRed:0.808f green:0.333f blue:0.067f alpha:1.000f], -[UIColor colorWithRed:0.588f green:0.173f blue:0.043f alpha:1.000f], -[UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], -[UIColor colorWithRed:0.176f green:0.075f blue:0.055f alpha:1.000f], -[UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], -[UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], -[UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], -[UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], -[UIColor colorWithRed:0.690f green:0.714f blue:0.718f alpha:1.000f], -[UIColor colorWithRed:0.573f green:0.604f blue:0.608f alpha:1.000f], -[UIColor colorWithRed:0.431f green:0.475f blue:0.478f alpha:1.000f], -[UIColor colorWithRed:0.318f green:0.369f blue:0.373f alpha:1.000f], -[UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], -[UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], -[UIColor colorWithRed:0.086f green:0.125f blue:0.125f alpha:1.000f], -[UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.973f blue:0.886f alpha:1.000f], -[UIColor colorWithRed:0.992f green:0.937f blue:0.804f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.914f blue:0.604f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.882f blue:0.431f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.851f blue:0.263f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.804f blue:0.110f alpha:1.000f], -[UIColor colorWithRed:1.000f green:0.737f blue:0.000f alpha:1.000f], -[UIColor colorWithRed:0.867f green:0.600f blue:0.012f alpha:1.000f], -[UIColor colorWithRed:0.729f green:0.459f blue:0.024f alpha:1.000f], -[UIColor colorWithRed:0.580f green:0.298f blue:0.047f alpha:1.000f], -[UIColor colorWithRed:0.329f green:0.165f blue:0.000f alpha:1.000f], -[UIColor colorWithRed:0.176f green:0.102f blue:0.020f alpha:1.000f], -[UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], -[UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], -[UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], -[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], -[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], -[UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], -[UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], -[UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], -[UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], -[UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f] - ]; - }); - - return colorArray; -} - -@end -" -`; - -exports[`integration ios objective-c ios/macros.h should match snapshot 1`] = ` -" -// -// macros.h -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import -#import - -#define ColorBackgroundPrimary [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f] -#define ColorBackgroundSecondary [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f] -#define ColorBackgroundTertiary [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f] -#define ColorBackgroundDanger [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f] -#define ColorBackgroundWarning [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f] -#define ColorBackgroundSuccess [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f] -#define ColorBackgroundInfo [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f] -#define ColorBackgroundDisabled [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f] -#define ColorBorderPrimary [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f] -#define ColorBrandPrimary [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] -#define ColorBrandSecondary [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f] -#define ColorCoreGreen0 [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f] -#define ColorCoreGreen100 [UIColor colorWithRed:0.843f green:0.957f blue:0.843f alpha:1.000f] -#define ColorCoreGreen200 [UIColor colorWithRed:0.761f green:0.949f blue:0.741f alpha:1.000f] -#define ColorCoreGreen300 [UIColor colorWithRed:0.596f green:0.898f blue:0.557f alpha:1.000f] -#define ColorCoreGreen400 [UIColor colorWithRed:0.459f green:0.867f blue:0.400f alpha:1.000f] -#define ColorCoreGreen500 [UIColor colorWithRed:0.349f green:0.796f blue:0.349f alpha:1.000f] -#define ColorCoreGreen600 [UIColor colorWithRed:0.169f green:0.714f blue:0.337f alpha:1.000f] -#define ColorCoreGreen700 [UIColor colorWithRed:0.047f green:0.655f blue:0.314f alpha:1.000f] -#define ColorCoreGreen800 [UIColor colorWithRed:0.000f green:0.545f blue:0.275f alpha:1.000f] -#define ColorCoreGreen900 [UIColor colorWithRed:0.000f green:0.420f blue:0.251f alpha:1.000f] -#define ColorCoreGreen1000 [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f] -#define ColorCoreGreen1100 [UIColor colorWithRed:0.000f green:0.169f blue:0.125f alpha:1.000f] -#define ColorCoreTeal0 [UIColor colorWithRed:0.898f green:0.976f blue:0.961f alpha:1.000f] -#define ColorCoreTeal100 [UIColor colorWithRed:0.804f green:0.969f blue:0.937f alpha:1.000f] -#define ColorCoreTeal200 [UIColor colorWithRed:0.702f green:0.949f blue:0.902f alpha:1.000f] -#define ColorCoreTeal300 [UIColor colorWithRed:0.490f green:0.918f blue:0.835f alpha:1.000f] -#define ColorCoreTeal400 [UIColor colorWithRed:0.141f green:0.878f blue:0.773f alpha:1.000f] -#define ColorCoreTeal500 [UIColor colorWithRed:0.031f green:0.769f blue:0.698f alpha:1.000f] -#define ColorCoreTeal600 [UIColor colorWithRed:0.000f green:0.663f blue:0.612f alpha:1.000f] -#define ColorCoreTeal700 [UIColor colorWithRed:0.043f green:0.588f blue:0.561f alpha:1.000f] -#define ColorCoreTeal800 [UIColor colorWithRed:0.024f green:0.486f blue:0.486f alpha:1.000f] -#define ColorCoreTeal900 [UIColor colorWithRed:0.008f green:0.400f blue:0.380f alpha:1.000f] -#define ColorCoreTeal1000 [UIColor colorWithRed:0.031f green:0.247f blue:0.247f alpha:1.000f] -#define ColorCoreTeal1100 [UIColor colorWithRed:0.000f green:0.145f blue:0.157f alpha:1.000f] -#define ColorCoreAqua0 [UIColor colorWithRed:0.851f green:0.988f blue:0.984f alpha:1.000f] -#define ColorCoreAqua100 [UIColor colorWithRed:0.773f green:0.976f blue:0.976f alpha:1.000f] -#define ColorCoreAqua200 [UIColor colorWithRed:0.647f green:0.949f blue:0.949f alpha:1.000f] -#define ColorCoreAqua300 [UIColor colorWithRed:0.463f green:0.898f blue:0.886f alpha:1.000f] -#define ColorCoreAqua400 [UIColor colorWithRed:0.200f green:0.839f blue:0.886f alpha:1.000f] -#define ColorCoreAqua500 [UIColor colorWithRed:0.090f green:0.722f blue:0.808f alpha:1.000f] -#define ColorCoreAqua600 [UIColor colorWithRed:0.027f green:0.592f blue:0.682f alpha:1.000f] -#define ColorCoreAqua700 [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] -#define ColorCoreAqua800 [UIColor colorWithRed:0.059f green:0.431f blue:0.518f alpha:1.000f] -#define ColorCoreAqua900 [UIColor colorWithRed:0.012f green:0.369f blue:0.451f alpha:1.000f] -#define ColorCoreAqua1000 [UIColor colorWithRed:0.031f green:0.239f blue:0.310f alpha:1.000f] -#define ColorCoreAqua1100 [UIColor colorWithRed:0.000f green:0.157f blue:0.220f alpha:1.000f] -#define ColorCoreBlue0 [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f] -#define ColorCoreBlue100 [UIColor colorWithRed:0.863f green:0.949f blue:1.000f alpha:1.000f] -#define ColorCoreBlue200 [UIColor colorWithRed:0.780f green:0.894f blue:0.976f alpha:1.000f] -#define ColorCoreBlue300 [UIColor colorWithRed:0.631f green:0.824f blue:0.973f alpha:1.000f] -#define ColorCoreBlue400 [UIColor colorWithRed:0.337f green:0.678f blue:0.961f alpha:1.000f] -#define ColorCoreBlue500 [UIColor colorWithRed:0.220f green:0.588f blue:0.890f alpha:1.000f] -#define ColorCoreBlue600 [UIColor colorWithRed:0.169f green:0.529f blue:0.827f alpha:1.000f] -#define ColorCoreBlue700 [UIColor colorWithRed:0.125f green:0.475f blue:0.765f alpha:1.000f] -#define ColorCoreBlue800 [UIColor colorWithRed:0.067f green:0.427f blue:0.667f alpha:1.000f] -#define ColorCoreBlue900 [UIColor colorWithRed:0.047f green:0.337f blue:0.537f alpha:1.000f] -#define ColorCoreBlue1000 [UIColor colorWithRed:0.039f green:0.224f blue:0.376f alpha:1.000f] -#define ColorCoreBlue1100 [UIColor colorWithRed:0.000f green:0.129f blue:0.220f alpha:1.000f] -#define ColorCorePurple0 [UIColor colorWithRed:0.949f green:0.949f blue:0.976f alpha:1.000f] -#define ColorCorePurple100 [UIColor colorWithRed:0.918f green:0.918f blue:0.976f alpha:1.000f] -#define ColorCorePurple200 [UIColor colorWithRed:0.847f green:0.843f blue:0.976f alpha:1.000f] -#define ColorCorePurple300 [UIColor colorWithRed:0.757f green:0.757f blue:0.969f alpha:1.000f] -#define ColorCorePurple400 [UIColor colorWithRed:0.631f green:0.576f blue:0.949f alpha:1.000f] -#define ColorCorePurple500 [UIColor colorWithRed:0.569f green:0.502f blue:0.957f alpha:1.000f] -#define ColorCorePurple600 [UIColor colorWithRed:0.506f green:0.435f blue:0.918f alpha:1.000f] -#define ColorCorePurple700 [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f] -#define ColorCorePurple800 [UIColor colorWithRed:0.369f green:0.306f blue:0.729f alpha:1.000f] -#define ColorCorePurple900 [UIColor colorWithRed:0.282f green:0.227f blue:0.612f alpha:1.000f] -#define ColorCorePurple1000 [UIColor colorWithRed:0.176f green:0.141f blue:0.420f alpha:1.000f] -#define ColorCorePurple1100 [UIColor colorWithRed:0.114f green:0.114f blue:0.220f alpha:1.000f] -#define ColorCoreMagenta0 [UIColor colorWithRed:0.996f green:0.941f blue:1.000f alpha:1.000f] -#define ColorCoreMagenta100 [UIColor colorWithRed:0.976f green:0.890f blue:0.988f alpha:1.000f] -#define ColorCoreMagenta200 [UIColor colorWithRed:0.957f green:0.769f blue:0.969f alpha:1.000f] -#define ColorCoreMagenta300 [UIColor colorWithRed:0.929f green:0.678f blue:0.949f alpha:1.000f] -#define ColorCoreMagenta400 [UIColor colorWithRed:0.949f green:0.510f blue:0.961f alpha:1.000f] -#define ColorCoreMagenta500 [UIColor colorWithRed:0.859f green:0.380f blue:0.859f alpha:1.000f] -#define ColorCoreMagenta600 [UIColor colorWithRed:0.769f green:0.306f blue:0.725f alpha:1.000f] -#define ColorCoreMagenta700 [UIColor colorWithRed:0.675f green:0.267f blue:0.659f alpha:1.000f] -#define ColorCoreMagenta800 [UIColor colorWithRed:0.561f green:0.220f blue:0.588f alpha:1.000f] -#define ColorCoreMagenta900 [UIColor colorWithRed:0.424f green:0.133f blue:0.467f alpha:1.000f] -#define ColorCoreMagenta1000 [UIColor colorWithRed:0.271f green:0.082f blue:0.318f alpha:1.000f] -#define ColorCoreMagenta1100 [UIColor colorWithRed:0.161f green:0.098f blue:0.176f alpha:1.000f] -#define ColorCorePink0 [UIColor colorWithRed:1.000f green:0.914f blue:0.953f alpha:1.000f] -#define ColorCorePink100 [UIColor colorWithRed:0.988f green:0.859f blue:0.922f alpha:1.000f] -#define ColorCorePink200 [UIColor colorWithRed:1.000f green:0.710f blue:0.835f alpha:1.000f] -#define ColorCorePink300 [UIColor colorWithRed:1.000f green:0.584f blue:0.757f alpha:1.000f] -#define ColorCorePink400 [UIColor colorWithRed:1.000f green:0.463f blue:0.682f alpha:1.000f] -#define ColorCorePink500 [UIColor colorWithRed:0.937f green:0.345f blue:0.545f alpha:1.000f] -#define ColorCorePink600 [UIColor colorWithRed:0.878f green:0.267f blue:0.486f alpha:1.000f] -#define ColorCorePink700 [UIColor colorWithRed:0.808f green:0.212f blue:0.396f alpha:1.000f] -#define ColorCorePink800 [UIColor colorWithRed:0.698f green:0.184f blue:0.357f alpha:1.000f] -#define ColorCorePink900 [UIColor colorWithRed:0.576f green:0.094f blue:0.278f alpha:1.000f] -#define ColorCorePink1000 [UIColor colorWithRed:0.337f green:0.071f blue:0.192f alpha:1.000f] -#define ColorCorePink1100 [UIColor colorWithRed:0.169f green:0.090f blue:0.129f alpha:1.000f] -#define ColorCoreRed0 [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f] -#define ColorCoreRed100 [UIColor colorWithRed:1.000f green:0.835f blue:0.824f alpha:1.000f] -#define ColorCoreRed200 [UIColor colorWithRed:1.000f green:0.722f blue:0.694f alpha:1.000f] -#define ColorCoreRed300 [UIColor colorWithRed:1.000f green:0.612f blue:0.561f alpha:1.000f] -#define ColorCoreRed400 [UIColor colorWithRed:1.000f green:0.498f blue:0.431f alpha:1.000f] -#define ColorCoreRed500 [UIColor colorWithRed:0.969f green:0.376f blue:0.329f alpha:1.000f] -#define ColorCoreRed600 [UIColor colorWithRed:0.929f green:0.298f blue:0.259f alpha:1.000f] -#define ColorCoreRed700 [UIColor colorWithRed:0.859f green:0.243f blue:0.243f alpha:1.000f] -#define ColorCoreRed800 [UIColor colorWithRed:0.776f green:0.204f blue:0.204f alpha:1.000f] -#define ColorCoreRed900 [UIColor colorWithRed:0.600f green:0.133f blue:0.133f alpha:1.000f] -#define ColorCoreRed1000 [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f] -#define ColorCoreRed1100 [UIColor colorWithRed:0.169f green:0.067f blue:0.067f alpha:1.000f] -#define ColorCoreOrange0 [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f] -#define ColorCoreOrange100 [UIColor colorWithRed:0.988f green:0.863f blue:0.800f alpha:1.000f] -#define ColorCoreOrange200 [UIColor colorWithRed:1.000f green:0.776f blue:0.643f alpha:1.000f] -#define ColorCoreOrange300 [UIColor colorWithRed:1.000f green:0.694f blue:0.502f alpha:1.000f] -#define ColorCoreOrange400 [UIColor colorWithRed:1.000f green:0.612f blue:0.365f alpha:1.000f] -#define ColorCoreOrange500 [UIColor colorWithRed:0.988f green:0.537f blue:0.263f alpha:1.000f] -#define ColorCoreOrange600 [UIColor colorWithRed:0.961f green:0.490f blue:0.200f alpha:1.000f] -#define ColorCoreOrange700 [UIColor colorWithRed:0.929f green:0.439f blue:0.141f alpha:1.000f] -#define ColorCoreOrange800 [UIColor colorWithRed:0.808f green:0.333f blue:0.067f alpha:1.000f] -#define ColorCoreOrange900 [UIColor colorWithRed:0.588f green:0.173f blue:0.043f alpha:1.000f] -#define ColorCoreOrange1000 [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f] -#define ColorCoreOrange1100 [UIColor colorWithRed:0.176f green:0.075f blue:0.055f alpha:1.000f] -#define ColorCoreNeutral0 [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f] -#define ColorCoreNeutral100 [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f] -#define ColorCoreNeutral200 [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f] -#define ColorCoreNeutral300 [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f] -#define ColorCoreNeutral400 [UIColor colorWithRed:0.690f green:0.714f blue:0.718f alpha:1.000f] -#define ColorCoreNeutral500 [UIColor colorWithRed:0.573f green:0.604f blue:0.608f alpha:1.000f] -#define ColorCoreNeutral600 [UIColor colorWithRed:0.431f green:0.475f blue:0.478f alpha:1.000f] -#define ColorCoreNeutral700 [UIColor colorWithRed:0.318f green:0.369f blue:0.373f alpha:1.000f] -#define ColorCoreNeutral800 [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f] -#define ColorCoreNeutral900 [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f] -#define ColorCoreNeutral1000 [UIColor colorWithRed:0.086f green:0.125f blue:0.125f alpha:1.000f] -#define ColorCoreNeutral1100 [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f] -#define ColorCoreYellow0 [UIColor colorWithRed:1.000f green:0.973f blue:0.886f alpha:1.000f] -#define ColorCoreYellow100 [UIColor colorWithRed:0.992f green:0.937f blue:0.804f alpha:1.000f] -#define ColorCoreYellow200 [UIColor colorWithRed:1.000f green:0.914f blue:0.604f alpha:1.000f] -#define ColorCoreYellow300 [UIColor colorWithRed:1.000f green:0.882f blue:0.431f alpha:1.000f] -#define ColorCoreYellow400 [UIColor colorWithRed:1.000f green:0.851f blue:0.263f alpha:1.000f] -#define ColorCoreYellow500 [UIColor colorWithRed:1.000f green:0.804f blue:0.110f alpha:1.000f] -#define ColorCoreYellow600 [UIColor colorWithRed:1.000f green:0.737f blue:0.000f alpha:1.000f] -#define ColorCoreYellow700 [UIColor colorWithRed:0.867f green:0.600f blue:0.012f alpha:1.000f] -#define ColorCoreYellow800 [UIColor colorWithRed:0.729f green:0.459f blue:0.024f alpha:1.000f] -#define ColorCoreYellow900 [UIColor colorWithRed:0.580f green:0.298f blue:0.047f alpha:1.000f] -#define ColorCoreYellow1000 [UIColor colorWithRed:0.329f green:0.165f blue:0.000f alpha:1.000f] -#define ColorCoreYellow1100 [UIColor colorWithRed:0.176f green:0.102f blue:0.020f alpha:1.000f] -#define ColorFontPrimary [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f] -#define ColorFontSecondary [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f] -#define ColorFontTertiary [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f] -#define ColorFontInteractive [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] -#define ColorFontInteractiveHover [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] -#define ColorFontInteractiveActive [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f] -#define ColorFontInteractiveDisabled [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f] -#define ColorFontDanger [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f] -#define ColorFontWarning [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f] -#define ColorFontSuccess [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f] -#define SizeBorderRadiusLarge 480.00f -#define SizeFontSmall 12.00f -#define SizeFontMedium 16.00f -#define SizeFontLarge 24.00f -#define SizeFontXl 36.00f -#define SizePaddingSmall 8.00f -#define SizePaddingMedium 16.00f -#define SizePaddingLarge 16.00f -#define SizePaddingXl 16.00f - -" -`; - -exports[`integration ios objective-c ios/singleton.h should match snapshot 1`] = ` -" -// -// singleton.h -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import -#import - -@interface StyleDictionary : NSObject - -+ (NSDictionary *)properties; -+ (NSDictionary *)getProperty:(NSString *)keyPath; -+ (nonnull)getValue:(NSString *)keyPath; - -@end -" -`; - -exports[`integration ios objective-c ios/singleton.m should match snapshot 1`] = ` -" -// -// singleton.m -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\"StyleDictionary.h\\" - -@implementation StyleDictionary - -+ (NSDictionary *)getProperty:(NSString *)keyPath { - return [[self properties] valueForKeyPath:keyPath]; -} - -+ (nonnull)getValue:(NSString *)keyPath { - return [[self properties] valueForKeyPath:[NSString stringWithFormat:@\\"%@.value\\", keyPath]]; -} - -+ (NSDictionary *)properties { - static NSDictionary * dictionary; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - dictionary = @{ - @\\"color\\": @{ - @\\"background\\": @{ - @\\"primary\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundPrimary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"primary\\" - }, - @\\"secondary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundSecondary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"secondary\\" - }, - @\\"tertiary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundTertiary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"tertiary\\" - }, - @\\"danger\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundDanger\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"danger\\" - }, - @\\"warning\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundWarning\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"warning\\" - }, - @\\"success\\": @{ - @\\"value\\": [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundSuccess\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"success\\" - }, - @\\"info\\": @{ - @\\"value\\": [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundInfo\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"info\\" - }, - @\\"disabled\\": @{ - @\\"value\\": [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], - @\\"name\\": @\\"ColorBackgroundDisabled\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"background\\", - @\\"item\\": @\\"disabled\\" - } - }, - @\\"border\\": @{ - @\\"primary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], - @\\"name\\": @\\"ColorBorderPrimary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"border\\", - @\\"item\\": @\\"primary\\" - }, - @\\"secondary\\": @ - }, - @\\"tertiary\\": @ - } - }, - @\\"brand\\": @{ - @\\"primary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], - @\\"name\\": @\\"ColorBrandPrimary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"brand\\", - @\\"item\\": @\\"primary\\" - }, - @\\"secondary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], - @\\"name\\": @\\"ColorBrandSecondary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"brand\\", - @\\"item\\": @\\"secondary\\" - } - }, - @\\"core\\": @{ - @\\"green\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.843f green:0.957f blue:0.843f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.761f green:0.949f blue:0.741f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.596f green:0.898f blue:0.557f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.459f green:0.867f blue:0.400f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.349f green:0.796f blue:0.349f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.169f green:0.714f blue:0.337f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.047f green:0.655f blue:0.314f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.545f blue:0.275f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.420f blue:0.251f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.169f blue:0.125f alpha:1.000f], - @\\"name\\": @\\"ColorCoreGreen1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"green\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"teal\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:0.898f green:0.976f blue:0.961f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.804f green:0.969f blue:0.937f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.702f green:0.949f blue:0.902f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.490f green:0.918f blue:0.835f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.141f green:0.878f blue:0.773f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.031f green:0.769f blue:0.698f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.663f blue:0.612f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.043f green:0.588f blue:0.561f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.024f green:0.486f blue:0.486f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.008f green:0.400f blue:0.380f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.031f green:0.247f blue:0.247f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.145f blue:0.157f alpha:1.000f], - @\\"name\\": @\\"ColorCoreTeal1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"teal\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"aqua\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:0.851f green:0.988f blue:0.984f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.773f green:0.976f blue:0.976f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.647f green:0.949f blue:0.949f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.463f green:0.898f blue:0.886f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.200f green:0.839f blue:0.886f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.090f green:0.722f blue:0.808f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.027f green:0.592f blue:0.682f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.059f green:0.431f blue:0.518f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.012f green:0.369f blue:0.451f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.031f green:0.239f blue:0.310f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.157f blue:0.220f alpha:1.000f], - @\\"name\\": @\\"ColorCoreAqua1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"aqua\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"blue\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.863f green:0.949f blue:1.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.780f green:0.894f blue:0.976f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.631f green:0.824f blue:0.973f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.337f green:0.678f blue:0.961f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.220f green:0.588f blue:0.890f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.169f green:0.529f blue:0.827f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.125f green:0.475f blue:0.765f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.067f green:0.427f blue:0.667f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.047f green:0.337f blue:0.537f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.039f green:0.224f blue:0.376f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.000f green:0.129f blue:0.220f alpha:1.000f], - @\\"name\\": @\\"ColorCoreBlue1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"blue\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"purple\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:0.949f green:0.949f blue:0.976f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.918f green:0.918f blue:0.976f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.847f green:0.843f blue:0.976f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.757f green:0.757f blue:0.969f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.631f green:0.576f blue:0.949f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.569f green:0.502f blue:0.957f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.506f green:0.435f blue:0.918f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.369f green:0.306f blue:0.729f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.282f green:0.227f blue:0.612f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.176f green:0.141f blue:0.420f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.114f green:0.114f blue:0.220f alpha:1.000f], - @\\"name\\": @\\"ColorCorePurple1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"purple\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"magenta\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:0.996f green:0.941f blue:1.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.976f green:0.890f blue:0.988f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.957f green:0.769f blue:0.969f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.929f green:0.678f blue:0.949f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.949f green:0.510f blue:0.961f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.859f green:0.380f blue:0.859f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.769f green:0.306f blue:0.725f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.675f green:0.267f blue:0.659f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.561f green:0.220f blue:0.588f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.424f green:0.133f blue:0.467f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.271f green:0.082f blue:0.318f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.161f green:0.098f blue:0.176f alpha:1.000f], - @\\"name\\": @\\"ColorCoreMagenta1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"magenta\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"pink\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.914f blue:0.953f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.988f green:0.859f blue:0.922f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.710f blue:0.835f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.584f blue:0.757f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.463f blue:0.682f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.937f green:0.345f blue:0.545f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.878f green:0.267f blue:0.486f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.808f green:0.212f blue:0.396f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.698f green:0.184f blue:0.357f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.576f green:0.094f blue:0.278f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.337f green:0.071f blue:0.192f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.169f green:0.090f blue:0.129f alpha:1.000f], - @\\"name\\": @\\"ColorCorePink1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"pink\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"red\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.835f blue:0.824f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.722f blue:0.694f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.612f blue:0.561f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.498f blue:0.431f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.969f green:0.376f blue:0.329f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.929f green:0.298f blue:0.259f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.859f green:0.243f blue:0.243f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.776f green:0.204f blue:0.204f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.600f green:0.133f blue:0.133f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.169f green:0.067f blue:0.067f alpha:1.000f], - @\\"name\\": @\\"ColorCoreRed1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"red\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"orange\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.988f green:0.863f blue:0.800f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.776f blue:0.643f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.694f blue:0.502f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.612f blue:0.365f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.988f green:0.537f blue:0.263f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.961f green:0.490f blue:0.200f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.929f green:0.439f blue:0.141f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.808f green:0.333f blue:0.067f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.588f green:0.173f blue:0.043f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.176f green:0.075f blue:0.055f alpha:1.000f], - @\\"name\\": @\\"ColorCoreOrange1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"orange\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"neutral\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:0.690f green:0.714f blue:0.718f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:0.573f green:0.604f blue:0.608f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:0.431f green:0.475f blue:0.478f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.318f green:0.369f blue:0.373f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.086f green:0.125f blue:0.125f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], - @\\"name\\": @\\"ColorCoreNeutral1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"neutral\\", - @\\"subitem\\": @\\"1100\\" - } - }, - @\\"yellow\\": @{ - @\\"0\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.973f blue:0.886f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow0\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"0\\" - }, - @\\"100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.992f green:0.937f blue:0.804f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"100\\" - }, - @\\"200\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.914f blue:0.604f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow200\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"200\\" - }, - @\\"300\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.882f blue:0.431f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow300\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"300\\" - }, - @\\"400\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.851f blue:0.263f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow400\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"400\\" - }, - @\\"500\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.804f blue:0.110f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow500\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"500\\" - }, - @\\"600\\": @{ - @\\"value\\": [UIColor colorWithRed:1.000f green:0.737f blue:0.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow600\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"600\\" - }, - @\\"700\\": @{ - @\\"value\\": [UIColor colorWithRed:0.867f green:0.600f blue:0.012f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow700\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"700\\" - }, - @\\"800\\": @{ - @\\"value\\": [UIColor colorWithRed:0.729f green:0.459f blue:0.024f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow800\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"800\\" - }, - @\\"900\\": @{ - @\\"value\\": [UIColor colorWithRed:0.580f green:0.298f blue:0.047f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow900\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"900\\" - }, - @\\"1000\\": @{ - @\\"value\\": [UIColor colorWithRed:0.329f green:0.165f blue:0.000f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow1000\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"1000\\" - }, - @\\"1100\\": @{ - @\\"value\\": [UIColor colorWithRed:0.176f green:0.102f blue:0.020f alpha:1.000f], - @\\"name\\": @\\"ColorCoreYellow1100\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"core\\", - @\\"item\\": @\\"yellow\\", - @\\"subitem\\": @\\"1100\\" - } - } - }, - @\\"font\\": @{ - @\\"primary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], - @\\"name\\": @\\"ColorFontPrimary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"primary\\" - }, - @\\"secondary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], - @\\"name\\": @\\"ColorFontSecondary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"secondary\\" - }, - @\\"tertiary\\": @{ - @\\"value\\": [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], - @\\"name\\": @\\"ColorFontTertiary\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"tertiary\\" - }, - @\\"interactive\\": @{ - @\\"_\\": @{ - @\\"value\\": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], - @\\"name\\": @\\"ColorFontInteractive\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"interactive\\", - @\\"subitem\\": @\\"_\\" - }, - @\\"hover\\": @{ - @\\"value\\": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], - @\\"name\\": @\\"ColorFontInteractiveHover\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"interactive\\", - @\\"subitem\\": @\\"hover\\" - }, - @\\"active\\": @{ - @\\"value\\": [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], - @\\"name\\": @\\"ColorFontInteractiveActive\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"interactive\\", - @\\"subitem\\": @\\"active\\" - }, - @\\"disabled\\": @{ - @\\"value\\": [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], - @\\"name\\": @\\"ColorFontInteractiveDisabled\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"interactive\\", - @\\"subitem\\": @\\"disabled\\" - } - }, - @\\"danger\\": @{ - @\\"value\\": [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], - @\\"name\\": @\\"ColorFontDanger\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"danger\\" - }, - @\\"warning\\": @{ - @\\"value\\": [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], - @\\"name\\": @\\"ColorFontWarning\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"warning\\" - }, - @\\"success\\": @{ - @\\"value\\": [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f], - @\\"name\\": @\\"ColorFontSuccess\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"success\\" - } - } - }, - @\\"size\\": @{ - @\\"border\\": @{ - @\\"radius\\": @{ - @\\"large\\": @{ - @\\"value\\": @480.00f, - @\\"name\\": @\\"SizeBorderRadiusLarge\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"border\\", - @\\"item\\": @\\"radius\\", - @\\"subitem\\": @\\"large\\" - } - } - }, - @\\"font\\": @{ - @\\"small\\": @{ - @\\"value\\": @12.00f, - @\\"name\\": @\\"SizeFontSmall\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"small\\" - }, - @\\"medium\\": @{ - @\\"value\\": @16.00f, - @\\"name\\": @\\"SizeFontMedium\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"medium\\" - }, - @\\"large\\": @{ - @\\"value\\": @24.00f, - @\\"name\\": @\\"SizeFontLarge\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"large\\" - }, - @\\"xl\\": @{ - @\\"value\\": @36.00f, - @\\"name\\": @\\"SizeFontXl\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"font\\", - @\\"item\\": @\\"xl\\" - } - }, - @\\"padding\\": @{ - @\\"small\\": @{ - @\\"value\\": @8.00f, - @\\"name\\": @\\"SizePaddingSmall\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"padding\\", - @\\"item\\": @\\"small\\" - }, - @\\"medium\\": @{ - @\\"value\\": @16.00f, - @\\"name\\": @\\"SizePaddingMedium\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"padding\\", - @\\"item\\": @\\"medium\\" - }, - @\\"large\\": @{ - @\\"value\\": @16.00f, - @\\"name\\": @\\"SizePaddingLarge\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"padding\\", - @\\"item\\": @\\"large\\" - }, - @\\"xl\\": @{ - @\\"value\\": @16.00f, - @\\"name\\": @\\"SizePaddingXl\\", - @\\"category\\": @\\"size\\", - @\\"type\\": @\\"padding\\", - @\\"item\\": @\\"xl\\" - } - } - } - }; - }); - - return dictionary; -} - -@end - - -" -`; - -exports[`integration ios objective-c ios/static.h should match snapshot 1`] = ` -" -// static.h -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import - - -extern CGFloat const SizeBorderRadiusLarge; -extern CGFloat const SizeFontSmall; -extern CGFloat const SizeFontMedium; -extern CGFloat const SizeFontLarge; -extern CGFloat const SizeFontXl; -extern CGFloat const SizePaddingSmall; -extern CGFloat const SizePaddingMedium; -extern CGFloat const SizePaddingLarge; -extern CGFloat const SizePaddingXl; -" -`; - -exports[`integration ios objective-c ios/static.m should match snapshot 1`] = ` -" -// -// static.m -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\"StyleDictionaryStatic.h\\" - - -CGFloat const SizeBorderRadiusLarge = 480.00f; -CGFloat const SizeFontSmall = 12.00f; -CGFloat const SizeFontMedium = 16.00f; -CGFloat const SizeFontLarge = 24.00f; -CGFloat const SizeFontXl = 36.00f; -CGFloat const SizePaddingSmall = 8.00f; -CGFloat const SizePaddingMedium = 16.00f; -CGFloat const SizePaddingLarge = 16.00f; -CGFloat const SizePaddingXl = 16.00f; -" -`; diff --git a/__integration__/__snapshots__/iOSObjectiveC.test.snap.js b/__integration__/__snapshots__/iOSObjectiveC.test.snap.js new file mode 100644 index 000000000..305123056 --- /dev/null +++ b/__integration__/__snapshots__/iOSObjectiveC.test.snap.js @@ -0,0 +1,1963 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration ios objective-c ios/singleton.m should match snapshot"] = +` +// +// singleton.m +// + +// Do not edit directly, this file was auto-generated. + + +#import "StyleDictionary.h" + +@implementation StyleDictionary + ++ (NSDictionary *)getProperty:(NSString *)keyPath { + return [[self properties] valueForKeyPath:keyPath]; +} + ++ (nonnull)getValue:(NSString *)keyPath { + return [[self properties] valueForKeyPath:[NSString stringWithFormat:@"%@.value", keyPath]]; +} + ++ (NSDictionary *)properties { + static NSDictionary * dictionary; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + dictionary = @{ + @"color": @{ + @"background": @{ + @"primary": @{ + @"value": [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], + @"name": @"ColorBackgroundPrimary", + @"category": @"color", + @"type": @"background", + @"item": @"primary" + }, + @"secondary": @{ + @"value": [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], + @"name": @"ColorBackgroundSecondary", + @"category": @"color", + @"type": @"background", + @"item": @"secondary" + }, + @"tertiary": @{ + @"value": [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], + @"name": @"ColorBackgroundTertiary", + @"category": @"color", + @"type": @"background", + @"item": @"tertiary" + }, + @"danger": @{ + @"value": [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], + @"name": @"ColorBackgroundDanger", + @"category": @"color", + @"type": @"background", + @"item": @"danger" + }, + @"warning": @{ + @"value": [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], + @"name": @"ColorBackgroundWarning", + @"category": @"color", + @"type": @"background", + @"item": @"warning" + }, + @"success": @{ + @"value": [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], + @"name": @"ColorBackgroundSuccess", + @"category": @"color", + @"type": @"background", + @"item": @"success" + }, + @"info": @{ + @"value": [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], + @"name": @"ColorBackgroundInfo", + @"category": @"color", + @"type": @"background", + @"item": @"info" + }, + @"disabled": @{ + @"value": [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], + @"name": @"ColorBackgroundDisabled", + @"category": @"color", + @"type": @"background", + @"item": @"disabled" + } + }, + @"border": @{ + @"primary": @{ + @"value": [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], + @"name": @"ColorBorderPrimary", + @"category": @"color", + @"type": @"border", + @"item": @"primary" + }, + @"secondary": @ + }, + @"tertiary": @ + } + }, + @"brand": @{ + @"primary": @{ + @"value": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], + @"name": @"ColorBrandPrimary", + @"category": @"color", + @"type": @"brand", + @"item": @"primary" + }, + @"secondary": @{ + @"value": [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], + @"name": @"ColorBrandSecondary", + @"category": @"color", + @"type": @"brand", + @"item": @"secondary" + } + }, + @"core": @{ + @"green": @{ + @"0": @{ + @"value": [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], + @"name": @"ColorCoreGreen0", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.843f green:0.957f blue:0.843f alpha:1.000f], + @"name": @"ColorCoreGreen100", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.761f green:0.949f blue:0.741f alpha:1.000f], + @"name": @"ColorCoreGreen200", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.596f green:0.898f blue:0.557f alpha:1.000f], + @"name": @"ColorCoreGreen300", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.459f green:0.867f blue:0.400f alpha:1.000f], + @"name": @"ColorCoreGreen400", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.349f green:0.796f blue:0.349f alpha:1.000f], + @"name": @"ColorCoreGreen500", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.169f green:0.714f blue:0.337f alpha:1.000f], + @"name": @"ColorCoreGreen600", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.047f green:0.655f blue:0.314f alpha:1.000f], + @"name": @"ColorCoreGreen700", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.000f green:0.545f blue:0.275f alpha:1.000f], + @"name": @"ColorCoreGreen800", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.000f green:0.420f blue:0.251f alpha:1.000f], + @"name": @"ColorCoreGreen900", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f], + @"name": @"ColorCoreGreen1000", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.000f green:0.169f blue:0.125f alpha:1.000f], + @"name": @"ColorCoreGreen1100", + @"category": @"color", + @"type": @"core", + @"item": @"green", + @"subitem": @"1100" + } + }, + @"teal": @{ + @"0": @{ + @"value": [UIColor colorWithRed:0.898f green:0.976f blue:0.961f alpha:1.000f], + @"name": @"ColorCoreTeal0", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.804f green:0.969f blue:0.937f alpha:1.000f], + @"name": @"ColorCoreTeal100", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.702f green:0.949f blue:0.902f alpha:1.000f], + @"name": @"ColorCoreTeal200", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.490f green:0.918f blue:0.835f alpha:1.000f], + @"name": @"ColorCoreTeal300", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.141f green:0.878f blue:0.773f alpha:1.000f], + @"name": @"ColorCoreTeal400", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.031f green:0.769f blue:0.698f alpha:1.000f], + @"name": @"ColorCoreTeal500", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.000f green:0.663f blue:0.612f alpha:1.000f], + @"name": @"ColorCoreTeal600", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.043f green:0.588f blue:0.561f alpha:1.000f], + @"name": @"ColorCoreTeal700", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.024f green:0.486f blue:0.486f alpha:1.000f], + @"name": @"ColorCoreTeal800", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.008f green:0.400f blue:0.380f alpha:1.000f], + @"name": @"ColorCoreTeal900", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.031f green:0.247f blue:0.247f alpha:1.000f], + @"name": @"ColorCoreTeal1000", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.000f green:0.145f blue:0.157f alpha:1.000f], + @"name": @"ColorCoreTeal1100", + @"category": @"color", + @"type": @"core", + @"item": @"teal", + @"subitem": @"1100" + } + }, + @"aqua": @{ + @"0": @{ + @"value": [UIColor colorWithRed:0.851f green:0.988f blue:0.984f alpha:1.000f], + @"name": @"ColorCoreAqua0", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.773f green:0.976f blue:0.976f alpha:1.000f], + @"name": @"ColorCoreAqua100", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.647f green:0.949f blue:0.949f alpha:1.000f], + @"name": @"ColorCoreAqua200", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.463f green:0.898f blue:0.886f alpha:1.000f], + @"name": @"ColorCoreAqua300", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.200f green:0.839f blue:0.886f alpha:1.000f], + @"name": @"ColorCoreAqua400", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.090f green:0.722f blue:0.808f alpha:1.000f], + @"name": @"ColorCoreAqua500", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.027f green:0.592f blue:0.682f alpha:1.000f], + @"name": @"ColorCoreAqua600", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], + @"name": @"ColorCoreAqua700", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.059f green:0.431f blue:0.518f alpha:1.000f], + @"name": @"ColorCoreAqua800", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.012f green:0.369f blue:0.451f alpha:1.000f], + @"name": @"ColorCoreAqua900", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.031f green:0.239f blue:0.310f alpha:1.000f], + @"name": @"ColorCoreAqua1000", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.000f green:0.157f blue:0.220f alpha:1.000f], + @"name": @"ColorCoreAqua1100", + @"category": @"color", + @"type": @"core", + @"item": @"aqua", + @"subitem": @"1100" + } + }, + @"blue": @{ + @"0": @{ + @"value": [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], + @"name": @"ColorCoreBlue0", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.863f green:0.949f blue:1.000f alpha:1.000f], + @"name": @"ColorCoreBlue100", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.780f green:0.894f blue:0.976f alpha:1.000f], + @"name": @"ColorCoreBlue200", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.631f green:0.824f blue:0.973f alpha:1.000f], + @"name": @"ColorCoreBlue300", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.337f green:0.678f blue:0.961f alpha:1.000f], + @"name": @"ColorCoreBlue400", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.220f green:0.588f blue:0.890f alpha:1.000f], + @"name": @"ColorCoreBlue500", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.169f green:0.529f blue:0.827f alpha:1.000f], + @"name": @"ColorCoreBlue600", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.125f green:0.475f blue:0.765f alpha:1.000f], + @"name": @"ColorCoreBlue700", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.067f green:0.427f blue:0.667f alpha:1.000f], + @"name": @"ColorCoreBlue800", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.047f green:0.337f blue:0.537f alpha:1.000f], + @"name": @"ColorCoreBlue900", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.039f green:0.224f blue:0.376f alpha:1.000f], + @"name": @"ColorCoreBlue1000", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.000f green:0.129f blue:0.220f alpha:1.000f], + @"name": @"ColorCoreBlue1100", + @"category": @"color", + @"type": @"core", + @"item": @"blue", + @"subitem": @"1100" + } + }, + @"purple": @{ + @"0": @{ + @"value": [UIColor colorWithRed:0.949f green:0.949f blue:0.976f alpha:1.000f], + @"name": @"ColorCorePurple0", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.918f green:0.918f blue:0.976f alpha:1.000f], + @"name": @"ColorCorePurple100", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.847f green:0.843f blue:0.976f alpha:1.000f], + @"name": @"ColorCorePurple200", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.757f green:0.757f blue:0.969f alpha:1.000f], + @"name": @"ColorCorePurple300", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.631f green:0.576f blue:0.949f alpha:1.000f], + @"name": @"ColorCorePurple400", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.569f green:0.502f blue:0.957f alpha:1.000f], + @"name": @"ColorCorePurple500", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.506f green:0.435f blue:0.918f alpha:1.000f], + @"name": @"ColorCorePurple600", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], + @"name": @"ColorCorePurple700", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.369f green:0.306f blue:0.729f alpha:1.000f], + @"name": @"ColorCorePurple800", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.282f green:0.227f blue:0.612f alpha:1.000f], + @"name": @"ColorCorePurple900", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.176f green:0.141f blue:0.420f alpha:1.000f], + @"name": @"ColorCorePurple1000", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.114f green:0.114f blue:0.220f alpha:1.000f], + @"name": @"ColorCorePurple1100", + @"category": @"color", + @"type": @"core", + @"item": @"purple", + @"subitem": @"1100" + } + }, + @"magenta": @{ + @"0": @{ + @"value": [UIColor colorWithRed:0.996f green:0.941f blue:1.000f alpha:1.000f], + @"name": @"ColorCoreMagenta0", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.976f green:0.890f blue:0.988f alpha:1.000f], + @"name": @"ColorCoreMagenta100", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.957f green:0.769f blue:0.969f alpha:1.000f], + @"name": @"ColorCoreMagenta200", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.929f green:0.678f blue:0.949f alpha:1.000f], + @"name": @"ColorCoreMagenta300", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.949f green:0.510f blue:0.961f alpha:1.000f], + @"name": @"ColorCoreMagenta400", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.859f green:0.380f blue:0.859f alpha:1.000f], + @"name": @"ColorCoreMagenta500", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.769f green:0.306f blue:0.725f alpha:1.000f], + @"name": @"ColorCoreMagenta600", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.675f green:0.267f blue:0.659f alpha:1.000f], + @"name": @"ColorCoreMagenta700", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.561f green:0.220f blue:0.588f alpha:1.000f], + @"name": @"ColorCoreMagenta800", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.424f green:0.133f blue:0.467f alpha:1.000f], + @"name": @"ColorCoreMagenta900", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.271f green:0.082f blue:0.318f alpha:1.000f], + @"name": @"ColorCoreMagenta1000", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.161f green:0.098f blue:0.176f alpha:1.000f], + @"name": @"ColorCoreMagenta1100", + @"category": @"color", + @"type": @"core", + @"item": @"magenta", + @"subitem": @"1100" + } + }, + @"pink": @{ + @"0": @{ + @"value": [UIColor colorWithRed:1.000f green:0.914f blue:0.953f alpha:1.000f], + @"name": @"ColorCorePink0", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.988f green:0.859f blue:0.922f alpha:1.000f], + @"name": @"ColorCorePink100", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:1.000f green:0.710f blue:0.835f alpha:1.000f], + @"name": @"ColorCorePink200", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:1.000f green:0.584f blue:0.757f alpha:1.000f], + @"name": @"ColorCorePink300", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:1.000f green:0.463f blue:0.682f alpha:1.000f], + @"name": @"ColorCorePink400", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.937f green:0.345f blue:0.545f alpha:1.000f], + @"name": @"ColorCorePink500", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.878f green:0.267f blue:0.486f alpha:1.000f], + @"name": @"ColorCorePink600", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.808f green:0.212f blue:0.396f alpha:1.000f], + @"name": @"ColorCorePink700", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.698f green:0.184f blue:0.357f alpha:1.000f], + @"name": @"ColorCorePink800", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.576f green:0.094f blue:0.278f alpha:1.000f], + @"name": @"ColorCorePink900", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.337f green:0.071f blue:0.192f alpha:1.000f], + @"name": @"ColorCorePink1000", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.169f green:0.090f blue:0.129f alpha:1.000f], + @"name": @"ColorCorePink1100", + @"category": @"color", + @"type": @"core", + @"item": @"pink", + @"subitem": @"1100" + } + }, + @"red": @{ + @"0": @{ + @"value": [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], + @"name": @"ColorCoreRed0", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:1.000f green:0.835f blue:0.824f alpha:1.000f], + @"name": @"ColorCoreRed100", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:1.000f green:0.722f blue:0.694f alpha:1.000f], + @"name": @"ColorCoreRed200", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:1.000f green:0.612f blue:0.561f alpha:1.000f], + @"name": @"ColorCoreRed300", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:1.000f green:0.498f blue:0.431f alpha:1.000f], + @"name": @"ColorCoreRed400", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.969f green:0.376f blue:0.329f alpha:1.000f], + @"name": @"ColorCoreRed500", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.929f green:0.298f blue:0.259f alpha:1.000f], + @"name": @"ColorCoreRed600", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.859f green:0.243f blue:0.243f alpha:1.000f], + @"name": @"ColorCoreRed700", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.776f green:0.204f blue:0.204f alpha:1.000f], + @"name": @"ColorCoreRed800", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.600f green:0.133f blue:0.133f alpha:1.000f], + @"name": @"ColorCoreRed900", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], + @"name": @"ColorCoreRed1000", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.169f green:0.067f blue:0.067f alpha:1.000f], + @"name": @"ColorCoreRed1100", + @"category": @"color", + @"type": @"core", + @"item": @"red", + @"subitem": @"1100" + } + }, + @"orange": @{ + @"0": @{ + @"value": [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], + @"name": @"ColorCoreOrange0", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.988f green:0.863f blue:0.800f alpha:1.000f], + @"name": @"ColorCoreOrange100", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:1.000f green:0.776f blue:0.643f alpha:1.000f], + @"name": @"ColorCoreOrange200", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:1.000f green:0.694f blue:0.502f alpha:1.000f], + @"name": @"ColorCoreOrange300", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:1.000f green:0.612f blue:0.365f alpha:1.000f], + @"name": @"ColorCoreOrange400", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.988f green:0.537f blue:0.263f alpha:1.000f], + @"name": @"ColorCoreOrange500", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.961f green:0.490f blue:0.200f alpha:1.000f], + @"name": @"ColorCoreOrange600", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.929f green:0.439f blue:0.141f alpha:1.000f], + @"name": @"ColorCoreOrange700", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.808f green:0.333f blue:0.067f alpha:1.000f], + @"name": @"ColorCoreOrange800", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.588f green:0.173f blue:0.043f alpha:1.000f], + @"name": @"ColorCoreOrange900", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], + @"name": @"ColorCoreOrange1000", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.176f green:0.075f blue:0.055f alpha:1.000f], + @"name": @"ColorCoreOrange1100", + @"category": @"color", + @"type": @"core", + @"item": @"orange", + @"subitem": @"1100" + } + }, + @"neutral": @{ + @"0": @{ + @"value": [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], + @"name": @"ColorCoreNeutral0", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], + @"name": @"ColorCoreNeutral100", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], + @"name": @"ColorCoreNeutral200", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], + @"name": @"ColorCoreNeutral300", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:0.690f green:0.714f blue:0.718f alpha:1.000f], + @"name": @"ColorCoreNeutral400", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:0.573f green:0.604f blue:0.608f alpha:1.000f], + @"name": @"ColorCoreNeutral500", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:0.431f green:0.475f blue:0.478f alpha:1.000f], + @"name": @"ColorCoreNeutral600", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.318f green:0.369f blue:0.373f alpha:1.000f], + @"name": @"ColorCoreNeutral700", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], + @"name": @"ColorCoreNeutral800", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], + @"name": @"ColorCoreNeutral900", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.086f green:0.125f blue:0.125f alpha:1.000f], + @"name": @"ColorCoreNeutral1000", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], + @"name": @"ColorCoreNeutral1100", + @"category": @"color", + @"type": @"core", + @"item": @"neutral", + @"subitem": @"1100" + } + }, + @"yellow": @{ + @"0": @{ + @"value": [UIColor colorWithRed:1.000f green:0.973f blue:0.886f alpha:1.000f], + @"name": @"ColorCoreYellow0", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"0" + }, + @"100": @{ + @"value": [UIColor colorWithRed:0.992f green:0.937f blue:0.804f alpha:1.000f], + @"name": @"ColorCoreYellow100", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"100" + }, + @"200": @{ + @"value": [UIColor colorWithRed:1.000f green:0.914f blue:0.604f alpha:1.000f], + @"name": @"ColorCoreYellow200", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"200" + }, + @"300": @{ + @"value": [UIColor colorWithRed:1.000f green:0.882f blue:0.431f alpha:1.000f], + @"name": @"ColorCoreYellow300", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"300" + }, + @"400": @{ + @"value": [UIColor colorWithRed:1.000f green:0.851f blue:0.263f alpha:1.000f], + @"name": @"ColorCoreYellow400", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"400" + }, + @"500": @{ + @"value": [UIColor colorWithRed:1.000f green:0.804f blue:0.110f alpha:1.000f], + @"name": @"ColorCoreYellow500", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"500" + }, + @"600": @{ + @"value": [UIColor colorWithRed:1.000f green:0.737f blue:0.000f alpha:1.000f], + @"name": @"ColorCoreYellow600", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"600" + }, + @"700": @{ + @"value": [UIColor colorWithRed:0.867f green:0.600f blue:0.012f alpha:1.000f], + @"name": @"ColorCoreYellow700", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"700" + }, + @"800": @{ + @"value": [UIColor colorWithRed:0.729f green:0.459f blue:0.024f alpha:1.000f], + @"name": @"ColorCoreYellow800", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"800" + }, + @"900": @{ + @"value": [UIColor colorWithRed:0.580f green:0.298f blue:0.047f alpha:1.000f], + @"name": @"ColorCoreYellow900", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"900" + }, + @"1000": @{ + @"value": [UIColor colorWithRed:0.329f green:0.165f blue:0.000f alpha:1.000f], + @"name": @"ColorCoreYellow1000", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"1000" + }, + @"1100": @{ + @"value": [UIColor colorWithRed:0.176f green:0.102f blue:0.020f alpha:1.000f], + @"name": @"ColorCoreYellow1100", + @"category": @"color", + @"type": @"core", + @"item": @"yellow", + @"subitem": @"1100" + } + } + }, + @"font": @{ + @"primary": @{ + @"value": [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], + @"name": @"ColorFontPrimary", + @"category": @"color", + @"type": @"font", + @"item": @"primary" + }, + @"secondary": @{ + @"value": [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], + @"name": @"ColorFontSecondary", + @"category": @"color", + @"type": @"font", + @"item": @"secondary" + }, + @"tertiary": @{ + @"value": [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], + @"name": @"ColorFontTertiary", + @"category": @"color", + @"type": @"font", + @"item": @"tertiary" + }, + @"interactive": @{ + @"_": @{ + @"value": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], + @"name": @"ColorFontInteractive", + @"category": @"color", + @"type": @"font", + @"item": @"interactive", + @"subitem": @"_" + }, + @"hover": @{ + @"value": [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], + @"name": @"ColorFontInteractiveHover", + @"category": @"color", + @"type": @"font", + @"item": @"interactive", + @"subitem": @"hover" + }, + @"active": @{ + @"value": [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], + @"name": @"ColorFontInteractiveActive", + @"category": @"color", + @"type": @"font", + @"item": @"interactive", + @"subitem": @"active" + }, + @"disabled": @{ + @"value": [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], + @"name": @"ColorFontInteractiveDisabled", + @"category": @"color", + @"type": @"font", + @"item": @"interactive", + @"subitem": @"disabled" + } + }, + @"danger": @{ + @"value": [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], + @"name": @"ColorFontDanger", + @"category": @"color", + @"type": @"font", + @"item": @"danger" + }, + @"warning": @{ + @"value": [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], + @"name": @"ColorFontWarning", + @"category": @"color", + @"type": @"font", + @"item": @"warning" + }, + @"success": @{ + @"value": [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f], + @"name": @"ColorFontSuccess", + @"category": @"color", + @"type": @"font", + @"item": @"success" + } + } + }, + @"size": @{ + @"border": @{ + @"radius": @{ + @"large": @{ + @"value": @480.00f, + @"name": @"SizeBorderRadiusLarge", + @"category": @"size", + @"type": @"border", + @"item": @"radius", + @"subitem": @"large" + } + } + }, + @"font": @{ + @"small": @{ + @"value": @12.00f, + @"name": @"SizeFontSmall", + @"category": @"size", + @"type": @"font", + @"item": @"small" + }, + @"medium": @{ + @"value": @16.00f, + @"name": @"SizeFontMedium", + @"category": @"size", + @"type": @"font", + @"item": @"medium" + }, + @"large": @{ + @"value": @24.00f, + @"name": @"SizeFontLarge", + @"category": @"size", + @"type": @"font", + @"item": @"large" + }, + @"xl": @{ + @"value": @36.00f, + @"name": @"SizeFontXl", + @"category": @"size", + @"type": @"font", + @"item": @"xl" + } + }, + @"padding": @{ + @"small": @{ + @"value": @8.00f, + @"name": @"SizePaddingSmall", + @"category": @"size", + @"type": @"padding", + @"item": @"small" + }, + @"medium": @{ + @"value": @16.00f, + @"name": @"SizePaddingMedium", + @"category": @"size", + @"type": @"padding", + @"item": @"medium" + }, + @"large": @{ + @"value": @16.00f, + @"name": @"SizePaddingLarge", + @"category": @"size", + @"type": @"padding", + @"item": @"large" + }, + @"xl": @{ + @"value": @16.00f, + @"name": @"SizePaddingXl", + @"category": @"size", + @"type": @"padding", + @"item": @"xl" + } + } + } + }; + }); + + return dictionary; +} + +@end + +`; +/* end snapshot integration ios objective-c ios/singleton.m should match snapshot */ + +snapshots["integration ios objective-c ios/singleton.h should match snapshot"] = +` +// +// singleton.h +// + +// Do not edit directly, this file was auto-generated. + + +#import +#import + +@interface StyleDictionary : NSObject + ++ (NSDictionary *)properties; ++ (NSDictionary *)getProperty:(NSString *)keyPath; ++ (nonnull)getValue:(NSString *)keyPath; + +@end`; +/* end snapshot integration ios objective-c ios/singleton.h should match snapshot */ + +snapshots["integration ios objective-c ios/color.m should match snapshot"] = +` +// +// color.m +// + +// Do not edit directly, this file was auto-generated. + + +#import "StyleDictionaryColor.h" + +@implementation StyleDictionaryColor + ++ (UIColor *)color:(StyleDictionaryColorName)colorEnum{ + return [[self values] objectAtIndex:colorEnum]; +} + ++ (NSArray *)values { + static NSArray* colorArray; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + colorArray = @[ +[UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], +[UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], +[UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], +[UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], +[UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], +[UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], +[UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], +[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], +[UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], +[UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f], +[UIColor colorWithRed:0.843f green:0.957f blue:0.843f alpha:1.000f], +[UIColor colorWithRed:0.761f green:0.949f blue:0.741f alpha:1.000f], +[UIColor colorWithRed:0.596f green:0.898f blue:0.557f alpha:1.000f], +[UIColor colorWithRed:0.459f green:0.867f blue:0.400f alpha:1.000f], +[UIColor colorWithRed:0.349f green:0.796f blue:0.349f alpha:1.000f], +[UIColor colorWithRed:0.169f green:0.714f blue:0.337f alpha:1.000f], +[UIColor colorWithRed:0.047f green:0.655f blue:0.314f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.545f blue:0.275f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.420f blue:0.251f alpha:1.000f], +[UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.169f blue:0.125f alpha:1.000f], +[UIColor colorWithRed:0.898f green:0.976f blue:0.961f alpha:1.000f], +[UIColor colorWithRed:0.804f green:0.969f blue:0.937f alpha:1.000f], +[UIColor colorWithRed:0.702f green:0.949f blue:0.902f alpha:1.000f], +[UIColor colorWithRed:0.490f green:0.918f blue:0.835f alpha:1.000f], +[UIColor colorWithRed:0.141f green:0.878f blue:0.773f alpha:1.000f], +[UIColor colorWithRed:0.031f green:0.769f blue:0.698f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.663f blue:0.612f alpha:1.000f], +[UIColor colorWithRed:0.043f green:0.588f blue:0.561f alpha:1.000f], +[UIColor colorWithRed:0.024f green:0.486f blue:0.486f alpha:1.000f], +[UIColor colorWithRed:0.008f green:0.400f blue:0.380f alpha:1.000f], +[UIColor colorWithRed:0.031f green:0.247f blue:0.247f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.145f blue:0.157f alpha:1.000f], +[UIColor colorWithRed:0.851f green:0.988f blue:0.984f alpha:1.000f], +[UIColor colorWithRed:0.773f green:0.976f blue:0.976f alpha:1.000f], +[UIColor colorWithRed:0.647f green:0.949f blue:0.949f alpha:1.000f], +[UIColor colorWithRed:0.463f green:0.898f blue:0.886f alpha:1.000f], +[UIColor colorWithRed:0.200f green:0.839f blue:0.886f alpha:1.000f], +[UIColor colorWithRed:0.090f green:0.722f blue:0.808f alpha:1.000f], +[UIColor colorWithRed:0.027f green:0.592f blue:0.682f alpha:1.000f], +[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], +[UIColor colorWithRed:0.059f green:0.431f blue:0.518f alpha:1.000f], +[UIColor colorWithRed:0.012f green:0.369f blue:0.451f alpha:1.000f], +[UIColor colorWithRed:0.031f green:0.239f blue:0.310f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.157f blue:0.220f alpha:1.000f], +[UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f], +[UIColor colorWithRed:0.863f green:0.949f blue:1.000f alpha:1.000f], +[UIColor colorWithRed:0.780f green:0.894f blue:0.976f alpha:1.000f], +[UIColor colorWithRed:0.631f green:0.824f blue:0.973f alpha:1.000f], +[UIColor colorWithRed:0.337f green:0.678f blue:0.961f alpha:1.000f], +[UIColor colorWithRed:0.220f green:0.588f blue:0.890f alpha:1.000f], +[UIColor colorWithRed:0.169f green:0.529f blue:0.827f alpha:1.000f], +[UIColor colorWithRed:0.125f green:0.475f blue:0.765f alpha:1.000f], +[UIColor colorWithRed:0.067f green:0.427f blue:0.667f alpha:1.000f], +[UIColor colorWithRed:0.047f green:0.337f blue:0.537f alpha:1.000f], +[UIColor colorWithRed:0.039f green:0.224f blue:0.376f alpha:1.000f], +[UIColor colorWithRed:0.000f green:0.129f blue:0.220f alpha:1.000f], +[UIColor colorWithRed:0.949f green:0.949f blue:0.976f alpha:1.000f], +[UIColor colorWithRed:0.918f green:0.918f blue:0.976f alpha:1.000f], +[UIColor colorWithRed:0.847f green:0.843f blue:0.976f alpha:1.000f], +[UIColor colorWithRed:0.757f green:0.757f blue:0.969f alpha:1.000f], +[UIColor colorWithRed:0.631f green:0.576f blue:0.949f alpha:1.000f], +[UIColor colorWithRed:0.569f green:0.502f blue:0.957f alpha:1.000f], +[UIColor colorWithRed:0.506f green:0.435f blue:0.918f alpha:1.000f], +[UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], +[UIColor colorWithRed:0.369f green:0.306f blue:0.729f alpha:1.000f], +[UIColor colorWithRed:0.282f green:0.227f blue:0.612f alpha:1.000f], +[UIColor colorWithRed:0.176f green:0.141f blue:0.420f alpha:1.000f], +[UIColor colorWithRed:0.114f green:0.114f blue:0.220f alpha:1.000f], +[UIColor colorWithRed:0.996f green:0.941f blue:1.000f alpha:1.000f], +[UIColor colorWithRed:0.976f green:0.890f blue:0.988f alpha:1.000f], +[UIColor colorWithRed:0.957f green:0.769f blue:0.969f alpha:1.000f], +[UIColor colorWithRed:0.929f green:0.678f blue:0.949f alpha:1.000f], +[UIColor colorWithRed:0.949f green:0.510f blue:0.961f alpha:1.000f], +[UIColor colorWithRed:0.859f green:0.380f blue:0.859f alpha:1.000f], +[UIColor colorWithRed:0.769f green:0.306f blue:0.725f alpha:1.000f], +[UIColor colorWithRed:0.675f green:0.267f blue:0.659f alpha:1.000f], +[UIColor colorWithRed:0.561f green:0.220f blue:0.588f alpha:1.000f], +[UIColor colorWithRed:0.424f green:0.133f blue:0.467f alpha:1.000f], +[UIColor colorWithRed:0.271f green:0.082f blue:0.318f alpha:1.000f], +[UIColor colorWithRed:0.161f green:0.098f blue:0.176f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.914f blue:0.953f alpha:1.000f], +[UIColor colorWithRed:0.988f green:0.859f blue:0.922f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.710f blue:0.835f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.584f blue:0.757f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.463f blue:0.682f alpha:1.000f], +[UIColor colorWithRed:0.937f green:0.345f blue:0.545f alpha:1.000f], +[UIColor colorWithRed:0.878f green:0.267f blue:0.486f alpha:1.000f], +[UIColor colorWithRed:0.808f green:0.212f blue:0.396f alpha:1.000f], +[UIColor colorWithRed:0.698f green:0.184f blue:0.357f alpha:1.000f], +[UIColor colorWithRed:0.576f green:0.094f blue:0.278f alpha:1.000f], +[UIColor colorWithRed:0.337f green:0.071f blue:0.192f alpha:1.000f], +[UIColor colorWithRed:0.169f green:0.090f blue:0.129f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.835f blue:0.824f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.722f blue:0.694f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.612f blue:0.561f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.498f blue:0.431f alpha:1.000f], +[UIColor colorWithRed:0.969f green:0.376f blue:0.329f alpha:1.000f], +[UIColor colorWithRed:0.929f green:0.298f blue:0.259f alpha:1.000f], +[UIColor colorWithRed:0.859f green:0.243f blue:0.243f alpha:1.000f], +[UIColor colorWithRed:0.776f green:0.204f blue:0.204f alpha:1.000f], +[UIColor colorWithRed:0.600f green:0.133f blue:0.133f alpha:1.000f], +[UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], +[UIColor colorWithRed:0.169f green:0.067f blue:0.067f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f], +[UIColor colorWithRed:0.988f green:0.863f blue:0.800f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.776f blue:0.643f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.694f blue:0.502f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.612f blue:0.365f alpha:1.000f], +[UIColor colorWithRed:0.988f green:0.537f blue:0.263f alpha:1.000f], +[UIColor colorWithRed:0.961f green:0.490f blue:0.200f alpha:1.000f], +[UIColor colorWithRed:0.929f green:0.439f blue:0.141f alpha:1.000f], +[UIColor colorWithRed:0.808f green:0.333f blue:0.067f alpha:1.000f], +[UIColor colorWithRed:0.588f green:0.173f blue:0.043f alpha:1.000f], +[UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], +[UIColor colorWithRed:0.176f green:0.075f blue:0.055f alpha:1.000f], +[UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f], +[UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f], +[UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f], +[UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f], +[UIColor colorWithRed:0.690f green:0.714f blue:0.718f alpha:1.000f], +[UIColor colorWithRed:0.573f green:0.604f blue:0.608f alpha:1.000f], +[UIColor colorWithRed:0.431f green:0.475f blue:0.478f alpha:1.000f], +[UIColor colorWithRed:0.318f green:0.369f blue:0.373f alpha:1.000f], +[UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], +[UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], +[UIColor colorWithRed:0.086f green:0.125f blue:0.125f alpha:1.000f], +[UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.973f blue:0.886f alpha:1.000f], +[UIColor colorWithRed:0.992f green:0.937f blue:0.804f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.914f blue:0.604f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.882f blue:0.431f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.851f blue:0.263f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.804f blue:0.110f alpha:1.000f], +[UIColor colorWithRed:1.000f green:0.737f blue:0.000f alpha:1.000f], +[UIColor colorWithRed:0.867f green:0.600f blue:0.012f alpha:1.000f], +[UIColor colorWithRed:0.729f green:0.459f blue:0.024f alpha:1.000f], +[UIColor colorWithRed:0.580f green:0.298f blue:0.047f alpha:1.000f], +[UIColor colorWithRed:0.329f green:0.165f blue:0.000f alpha:1.000f], +[UIColor colorWithRed:0.176f green:0.102f blue:0.020f alpha:1.000f], +[UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f], +[UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f], +[UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], +[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], +[UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f], +[UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f], +[UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f], +[UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f], +[UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f], +[UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f] + ]; + }); + + return colorArray; +} + +@end`; +/* end snapshot integration ios objective-c ios/color.m should match snapshot */ + +snapshots["integration ios objective-c ios/color.h should match snapshot"] = +` +// +// color.h +// + +// Do not edit directly, this file was auto-generated. + + +#import + +typedef NS_ENUM(NSInteger, StyleDictionaryColorName) { +ColorBackgroundPrimary, +ColorBackgroundSecondary, +ColorBackgroundTertiary, +ColorBackgroundDanger, +ColorBackgroundWarning, +ColorBackgroundSuccess, +ColorBackgroundInfo, +ColorBackgroundDisabled, +ColorBorderPrimary, +ColorBrandPrimary, +ColorBrandSecondary, +ColorCoreGreen0, +ColorCoreGreen100, +ColorCoreGreen200, +ColorCoreGreen300, +ColorCoreGreen400, +ColorCoreGreen500, +ColorCoreGreen600, +ColorCoreGreen700, +ColorCoreGreen800, +ColorCoreGreen900, +ColorCoreGreen1000, +ColorCoreGreen1100, +ColorCoreTeal0, +ColorCoreTeal100, +ColorCoreTeal200, +ColorCoreTeal300, +ColorCoreTeal400, +ColorCoreTeal500, +ColorCoreTeal600, +ColorCoreTeal700, +ColorCoreTeal800, +ColorCoreTeal900, +ColorCoreTeal1000, +ColorCoreTeal1100, +ColorCoreAqua0, +ColorCoreAqua100, +ColorCoreAqua200, +ColorCoreAqua300, +ColorCoreAqua400, +ColorCoreAqua500, +ColorCoreAqua600, +ColorCoreAqua700, +ColorCoreAqua800, +ColorCoreAqua900, +ColorCoreAqua1000, +ColorCoreAqua1100, +ColorCoreBlue0, +ColorCoreBlue100, +ColorCoreBlue200, +ColorCoreBlue300, +ColorCoreBlue400, +ColorCoreBlue500, +ColorCoreBlue600, +ColorCoreBlue700, +ColorCoreBlue800, +ColorCoreBlue900, +ColorCoreBlue1000, +ColorCoreBlue1100, +ColorCorePurple0, +ColorCorePurple100, +ColorCorePurple200, +ColorCorePurple300, +ColorCorePurple400, +ColorCorePurple500, +ColorCorePurple600, +ColorCorePurple700, +ColorCorePurple800, +ColorCorePurple900, +ColorCorePurple1000, +ColorCorePurple1100, +ColorCoreMagenta0, +ColorCoreMagenta100, +ColorCoreMagenta200, +ColorCoreMagenta300, +ColorCoreMagenta400, +ColorCoreMagenta500, +ColorCoreMagenta600, +ColorCoreMagenta700, +ColorCoreMagenta800, +ColorCoreMagenta900, +ColorCoreMagenta1000, +ColorCoreMagenta1100, +ColorCorePink0, +ColorCorePink100, +ColorCorePink200, +ColorCorePink300, +ColorCorePink400, +ColorCorePink500, +ColorCorePink600, +ColorCorePink700, +ColorCorePink800, +ColorCorePink900, +ColorCorePink1000, +ColorCorePink1100, +ColorCoreRed0, +ColorCoreRed100, +ColorCoreRed200, +ColorCoreRed300, +ColorCoreRed400, +ColorCoreRed500, +ColorCoreRed600, +ColorCoreRed700, +ColorCoreRed800, +ColorCoreRed900, +ColorCoreRed1000, +ColorCoreRed1100, +ColorCoreOrange0, +ColorCoreOrange100, +ColorCoreOrange200, +ColorCoreOrange300, +ColorCoreOrange400, +ColorCoreOrange500, +ColorCoreOrange600, +ColorCoreOrange700, +ColorCoreOrange800, +ColorCoreOrange900, +ColorCoreOrange1000, +ColorCoreOrange1100, +ColorCoreNeutral0, +ColorCoreNeutral100, +ColorCoreNeutral200, +ColorCoreNeutral300, +ColorCoreNeutral400, +ColorCoreNeutral500, +ColorCoreNeutral600, +ColorCoreNeutral700, +ColorCoreNeutral800, +ColorCoreNeutral900, +ColorCoreNeutral1000, +ColorCoreNeutral1100, +ColorCoreYellow0, +ColorCoreYellow100, +ColorCoreYellow200, +ColorCoreYellow300, +ColorCoreYellow400, +ColorCoreYellow500, +ColorCoreYellow600, +ColorCoreYellow700, +ColorCoreYellow800, +ColorCoreYellow900, +ColorCoreYellow1000, +ColorCoreYellow1100, +ColorFontPrimary, +ColorFontSecondary, +ColorFontTertiary, +ColorFontInteractive, +ColorFontInteractiveHover, +ColorFontInteractiveActive, +ColorFontInteractiveDisabled, +ColorFontDanger, +ColorFontWarning, +ColorFontSuccess +}; + +@interface StyleDictionaryColor : NSObject ++ (NSArray *)values; ++ (UIColor *)color:(StyleDictionaryColorName)color; +@end`; +/* end snapshot integration ios objective-c ios/color.h should match snapshot */ + +snapshots["integration ios objective-c ios/macros.h should match snapshot"] = +` +// +// macros.h +// + +// Do not edit directly, this file was auto-generated. + + +#import +#import + +#define ColorBackgroundPrimary [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f] +#define ColorBackgroundSecondary [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f] +#define ColorBackgroundTertiary [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f] +#define ColorBackgroundDanger [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f] +#define ColorBackgroundWarning [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f] +#define ColorBackgroundSuccess [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f] +#define ColorBackgroundInfo [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f] +#define ColorBackgroundDisabled [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f] +#define ColorBorderPrimary [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f] +#define ColorBrandPrimary [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] +#define ColorBrandSecondary [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f] +#define ColorCoreGreen0 [UIColor colorWithRed:0.922f green:0.976f blue:0.922f alpha:1.000f] +#define ColorCoreGreen100 [UIColor colorWithRed:0.843f green:0.957f blue:0.843f alpha:1.000f] +#define ColorCoreGreen200 [UIColor colorWithRed:0.761f green:0.949f blue:0.741f alpha:1.000f] +#define ColorCoreGreen300 [UIColor colorWithRed:0.596f green:0.898f blue:0.557f alpha:1.000f] +#define ColorCoreGreen400 [UIColor colorWithRed:0.459f green:0.867f blue:0.400f alpha:1.000f] +#define ColorCoreGreen500 [UIColor colorWithRed:0.349f green:0.796f blue:0.349f alpha:1.000f] +#define ColorCoreGreen600 [UIColor colorWithRed:0.169f green:0.714f blue:0.337f alpha:1.000f] +#define ColorCoreGreen700 [UIColor colorWithRed:0.047f green:0.655f blue:0.314f alpha:1.000f] +#define ColorCoreGreen800 [UIColor colorWithRed:0.000f green:0.545f blue:0.275f alpha:1.000f] +#define ColorCoreGreen900 [UIColor colorWithRed:0.000f green:0.420f blue:0.251f alpha:1.000f] +#define ColorCoreGreen1000 [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f] +#define ColorCoreGreen1100 [UIColor colorWithRed:0.000f green:0.169f blue:0.125f alpha:1.000f] +#define ColorCoreTeal0 [UIColor colorWithRed:0.898f green:0.976f blue:0.961f alpha:1.000f] +#define ColorCoreTeal100 [UIColor colorWithRed:0.804f green:0.969f blue:0.937f alpha:1.000f] +#define ColorCoreTeal200 [UIColor colorWithRed:0.702f green:0.949f blue:0.902f alpha:1.000f] +#define ColorCoreTeal300 [UIColor colorWithRed:0.490f green:0.918f blue:0.835f alpha:1.000f] +#define ColorCoreTeal400 [UIColor colorWithRed:0.141f green:0.878f blue:0.773f alpha:1.000f] +#define ColorCoreTeal500 [UIColor colorWithRed:0.031f green:0.769f blue:0.698f alpha:1.000f] +#define ColorCoreTeal600 [UIColor colorWithRed:0.000f green:0.663f blue:0.612f alpha:1.000f] +#define ColorCoreTeal700 [UIColor colorWithRed:0.043f green:0.588f blue:0.561f alpha:1.000f] +#define ColorCoreTeal800 [UIColor colorWithRed:0.024f green:0.486f blue:0.486f alpha:1.000f] +#define ColorCoreTeal900 [UIColor colorWithRed:0.008f green:0.400f blue:0.380f alpha:1.000f] +#define ColorCoreTeal1000 [UIColor colorWithRed:0.031f green:0.247f blue:0.247f alpha:1.000f] +#define ColorCoreTeal1100 [UIColor colorWithRed:0.000f green:0.145f blue:0.157f alpha:1.000f] +#define ColorCoreAqua0 [UIColor colorWithRed:0.851f green:0.988f blue:0.984f alpha:1.000f] +#define ColorCoreAqua100 [UIColor colorWithRed:0.773f green:0.976f blue:0.976f alpha:1.000f] +#define ColorCoreAqua200 [UIColor colorWithRed:0.647f green:0.949f blue:0.949f alpha:1.000f] +#define ColorCoreAqua300 [UIColor colorWithRed:0.463f green:0.898f blue:0.886f alpha:1.000f] +#define ColorCoreAqua400 [UIColor colorWithRed:0.200f green:0.839f blue:0.886f alpha:1.000f] +#define ColorCoreAqua500 [UIColor colorWithRed:0.090f green:0.722f blue:0.808f alpha:1.000f] +#define ColorCoreAqua600 [UIColor colorWithRed:0.027f green:0.592f blue:0.682f alpha:1.000f] +#define ColorCoreAqua700 [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] +#define ColorCoreAqua800 [UIColor colorWithRed:0.059f green:0.431f blue:0.518f alpha:1.000f] +#define ColorCoreAqua900 [UIColor colorWithRed:0.012f green:0.369f blue:0.451f alpha:1.000f] +#define ColorCoreAqua1000 [UIColor colorWithRed:0.031f green:0.239f blue:0.310f alpha:1.000f] +#define ColorCoreAqua1100 [UIColor colorWithRed:0.000f green:0.157f blue:0.220f alpha:1.000f] +#define ColorCoreBlue0 [UIColor colorWithRed:0.914f green:0.973f blue:1.000f alpha:1.000f] +#define ColorCoreBlue100 [UIColor colorWithRed:0.863f green:0.949f blue:1.000f alpha:1.000f] +#define ColorCoreBlue200 [UIColor colorWithRed:0.780f green:0.894f blue:0.976f alpha:1.000f] +#define ColorCoreBlue300 [UIColor colorWithRed:0.631f green:0.824f blue:0.973f alpha:1.000f] +#define ColorCoreBlue400 [UIColor colorWithRed:0.337f green:0.678f blue:0.961f alpha:1.000f] +#define ColorCoreBlue500 [UIColor colorWithRed:0.220f green:0.588f blue:0.890f alpha:1.000f] +#define ColorCoreBlue600 [UIColor colorWithRed:0.169f green:0.529f blue:0.827f alpha:1.000f] +#define ColorCoreBlue700 [UIColor colorWithRed:0.125f green:0.475f blue:0.765f alpha:1.000f] +#define ColorCoreBlue800 [UIColor colorWithRed:0.067f green:0.427f blue:0.667f alpha:1.000f] +#define ColorCoreBlue900 [UIColor colorWithRed:0.047f green:0.337f blue:0.537f alpha:1.000f] +#define ColorCoreBlue1000 [UIColor colorWithRed:0.039f green:0.224f blue:0.376f alpha:1.000f] +#define ColorCoreBlue1100 [UIColor colorWithRed:0.000f green:0.129f blue:0.220f alpha:1.000f] +#define ColorCorePurple0 [UIColor colorWithRed:0.949f green:0.949f blue:0.976f alpha:1.000f] +#define ColorCorePurple100 [UIColor colorWithRed:0.918f green:0.918f blue:0.976f alpha:1.000f] +#define ColorCorePurple200 [UIColor colorWithRed:0.847f green:0.843f blue:0.976f alpha:1.000f] +#define ColorCorePurple300 [UIColor colorWithRed:0.757f green:0.757f blue:0.969f alpha:1.000f] +#define ColorCorePurple400 [UIColor colorWithRed:0.631f green:0.576f blue:0.949f alpha:1.000f] +#define ColorCorePurple500 [UIColor colorWithRed:0.569f green:0.502f blue:0.957f alpha:1.000f] +#define ColorCorePurple600 [UIColor colorWithRed:0.506f green:0.435f blue:0.918f alpha:1.000f] +#define ColorCorePurple700 [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f] +#define ColorCorePurple800 [UIColor colorWithRed:0.369f green:0.306f blue:0.729f alpha:1.000f] +#define ColorCorePurple900 [UIColor colorWithRed:0.282f green:0.227f blue:0.612f alpha:1.000f] +#define ColorCorePurple1000 [UIColor colorWithRed:0.176f green:0.141f blue:0.420f alpha:1.000f] +#define ColorCorePurple1100 [UIColor colorWithRed:0.114f green:0.114f blue:0.220f alpha:1.000f] +#define ColorCoreMagenta0 [UIColor colorWithRed:0.996f green:0.941f blue:1.000f alpha:1.000f] +#define ColorCoreMagenta100 [UIColor colorWithRed:0.976f green:0.890f blue:0.988f alpha:1.000f] +#define ColorCoreMagenta200 [UIColor colorWithRed:0.957f green:0.769f blue:0.969f alpha:1.000f] +#define ColorCoreMagenta300 [UIColor colorWithRed:0.929f green:0.678f blue:0.949f alpha:1.000f] +#define ColorCoreMagenta400 [UIColor colorWithRed:0.949f green:0.510f blue:0.961f alpha:1.000f] +#define ColorCoreMagenta500 [UIColor colorWithRed:0.859f green:0.380f blue:0.859f alpha:1.000f] +#define ColorCoreMagenta600 [UIColor colorWithRed:0.769f green:0.306f blue:0.725f alpha:1.000f] +#define ColorCoreMagenta700 [UIColor colorWithRed:0.675f green:0.267f blue:0.659f alpha:1.000f] +#define ColorCoreMagenta800 [UIColor colorWithRed:0.561f green:0.220f blue:0.588f alpha:1.000f] +#define ColorCoreMagenta900 [UIColor colorWithRed:0.424f green:0.133f blue:0.467f alpha:1.000f] +#define ColorCoreMagenta1000 [UIColor colorWithRed:0.271f green:0.082f blue:0.318f alpha:1.000f] +#define ColorCoreMagenta1100 [UIColor colorWithRed:0.161f green:0.098f blue:0.176f alpha:1.000f] +#define ColorCorePink0 [UIColor colorWithRed:1.000f green:0.914f blue:0.953f alpha:1.000f] +#define ColorCorePink100 [UIColor colorWithRed:0.988f green:0.859f blue:0.922f alpha:1.000f] +#define ColorCorePink200 [UIColor colorWithRed:1.000f green:0.710f blue:0.835f alpha:1.000f] +#define ColorCorePink300 [UIColor colorWithRed:1.000f green:0.584f blue:0.757f alpha:1.000f] +#define ColorCorePink400 [UIColor colorWithRed:1.000f green:0.463f blue:0.682f alpha:1.000f] +#define ColorCorePink500 [UIColor colorWithRed:0.937f green:0.345f blue:0.545f alpha:1.000f] +#define ColorCorePink600 [UIColor colorWithRed:0.878f green:0.267f blue:0.486f alpha:1.000f] +#define ColorCorePink700 [UIColor colorWithRed:0.808f green:0.212f blue:0.396f alpha:1.000f] +#define ColorCorePink800 [UIColor colorWithRed:0.698f green:0.184f blue:0.357f alpha:1.000f] +#define ColorCorePink900 [UIColor colorWithRed:0.576f green:0.094f blue:0.278f alpha:1.000f] +#define ColorCorePink1000 [UIColor colorWithRed:0.337f green:0.071f blue:0.192f alpha:1.000f] +#define ColorCorePink1100 [UIColor colorWithRed:0.169f green:0.090f blue:0.129f alpha:1.000f] +#define ColorCoreRed0 [UIColor colorWithRed:1.000f green:0.918f blue:0.914f alpha:1.000f] +#define ColorCoreRed100 [UIColor colorWithRed:1.000f green:0.835f blue:0.824f alpha:1.000f] +#define ColorCoreRed200 [UIColor colorWithRed:1.000f green:0.722f blue:0.694f alpha:1.000f] +#define ColorCoreRed300 [UIColor colorWithRed:1.000f green:0.612f blue:0.561f alpha:1.000f] +#define ColorCoreRed400 [UIColor colorWithRed:1.000f green:0.498f blue:0.431f alpha:1.000f] +#define ColorCoreRed500 [UIColor colorWithRed:0.969f green:0.376f blue:0.329f alpha:1.000f] +#define ColorCoreRed600 [UIColor colorWithRed:0.929f green:0.298f blue:0.259f alpha:1.000f] +#define ColorCoreRed700 [UIColor colorWithRed:0.859f green:0.243f blue:0.243f alpha:1.000f] +#define ColorCoreRed800 [UIColor colorWithRed:0.776f green:0.204f blue:0.204f alpha:1.000f] +#define ColorCoreRed900 [UIColor colorWithRed:0.600f green:0.133f blue:0.133f alpha:1.000f] +#define ColorCoreRed1000 [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f] +#define ColorCoreRed1100 [UIColor colorWithRed:0.169f green:0.067f blue:0.067f alpha:1.000f] +#define ColorCoreOrange0 [UIColor colorWithRed:1.000f green:0.929f blue:0.890f alpha:1.000f] +#define ColorCoreOrange100 [UIColor colorWithRed:0.988f green:0.863f blue:0.800f alpha:1.000f] +#define ColorCoreOrange200 [UIColor colorWithRed:1.000f green:0.776f blue:0.643f alpha:1.000f] +#define ColorCoreOrange300 [UIColor colorWithRed:1.000f green:0.694f blue:0.502f alpha:1.000f] +#define ColorCoreOrange400 [UIColor colorWithRed:1.000f green:0.612f blue:0.365f alpha:1.000f] +#define ColorCoreOrange500 [UIColor colorWithRed:0.988f green:0.537f blue:0.263f alpha:1.000f] +#define ColorCoreOrange600 [UIColor colorWithRed:0.961f green:0.490f blue:0.200f alpha:1.000f] +#define ColorCoreOrange700 [UIColor colorWithRed:0.929f green:0.439f blue:0.141f alpha:1.000f] +#define ColorCoreOrange800 [UIColor colorWithRed:0.808f green:0.333f blue:0.067f alpha:1.000f] +#define ColorCoreOrange900 [UIColor colorWithRed:0.588f green:0.173f blue:0.043f alpha:1.000f] +#define ColorCoreOrange1000 [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f] +#define ColorCoreOrange1100 [UIColor colorWithRed:0.176f green:0.075f blue:0.055f alpha:1.000f] +#define ColorCoreNeutral0 [UIColor colorWithRed:1.000f green:1.000f blue:1.000f alpha:1.000f] +#define ColorCoreNeutral100 [UIColor colorWithRed:0.953f green:0.957f blue:0.957f alpha:1.000f] +#define ColorCoreNeutral200 [UIColor colorWithRed:0.871f green:0.882f blue:0.882f alpha:1.000f] +#define ColorCoreNeutral300 [UIColor colorWithRed:0.784f green:0.800f blue:0.800f alpha:1.000f] +#define ColorCoreNeutral400 [UIColor colorWithRed:0.690f green:0.714f blue:0.718f alpha:1.000f] +#define ColorCoreNeutral500 [UIColor colorWithRed:0.573f green:0.604f blue:0.608f alpha:1.000f] +#define ColorCoreNeutral600 [UIColor colorWithRed:0.431f green:0.475f blue:0.478f alpha:1.000f] +#define ColorCoreNeutral700 [UIColor colorWithRed:0.318f green:0.369f blue:0.373f alpha:1.000f] +#define ColorCoreNeutral800 [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f] +#define ColorCoreNeutral900 [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f] +#define ColorCoreNeutral1000 [UIColor colorWithRed:0.086f green:0.125f blue:0.125f alpha:1.000f] +#define ColorCoreNeutral1100 [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f] +#define ColorCoreYellow0 [UIColor colorWithRed:1.000f green:0.973f blue:0.886f alpha:1.000f] +#define ColorCoreYellow100 [UIColor colorWithRed:0.992f green:0.937f blue:0.804f alpha:1.000f] +#define ColorCoreYellow200 [UIColor colorWithRed:1.000f green:0.914f blue:0.604f alpha:1.000f] +#define ColorCoreYellow300 [UIColor colorWithRed:1.000f green:0.882f blue:0.431f alpha:1.000f] +#define ColorCoreYellow400 [UIColor colorWithRed:1.000f green:0.851f blue:0.263f alpha:1.000f] +#define ColorCoreYellow500 [UIColor colorWithRed:1.000f green:0.804f blue:0.110f alpha:1.000f] +#define ColorCoreYellow600 [UIColor colorWithRed:1.000f green:0.737f blue:0.000f alpha:1.000f] +#define ColorCoreYellow700 [UIColor colorWithRed:0.867f green:0.600f blue:0.012f alpha:1.000f] +#define ColorCoreYellow800 [UIColor colorWithRed:0.729f green:0.459f blue:0.024f alpha:1.000f] +#define ColorCoreYellow900 [UIColor colorWithRed:0.580f green:0.298f blue:0.047f alpha:1.000f] +#define ColorCoreYellow1000 [UIColor colorWithRed:0.329f green:0.165f blue:0.000f alpha:1.000f] +#define ColorCoreYellow1100 [UIColor colorWithRed:0.176f green:0.102f blue:0.020f alpha:1.000f] +#define ColorFontPrimary [UIColor colorWithRed:0.016f green:0.016f blue:0.016f alpha:1.000f] +#define ColorFontSecondary [UIColor colorWithRed:0.153f green:0.200f blue:0.200f alpha:1.000f] +#define ColorFontTertiary [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f] +#define ColorFontInteractive [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] +#define ColorFontInteractiveHover [UIColor colorWithRed:0.043f green:0.522f blue:0.600f alpha:1.000f] +#define ColorFontInteractiveActive [UIColor colorWithRed:0.435f green:0.369f blue:0.827f alpha:1.000f] +#define ColorFontInteractiveDisabled [UIColor colorWithRed:0.212f green:0.255f blue:0.255f alpha:1.000f] +#define ColorFontDanger [UIColor colorWithRed:0.427f green:0.075f blue:0.075f alpha:1.000f] +#define ColorFontWarning [UIColor colorWithRed:0.376f green:0.090f blue:0.000f alpha:1.000f] +#define ColorFontSuccess [UIColor colorWithRed:0.031f green:0.259f blue:0.184f alpha:1.000f] +#define SizeBorderRadiusLarge 480.00f +#define SizeFontSmall 12.00f +#define SizeFontMedium 16.00f +#define SizeFontLarge 24.00f +#define SizeFontXl 36.00f +#define SizePaddingSmall 8.00f +#define SizePaddingMedium 16.00f +#define SizePaddingLarge 16.00f +#define SizePaddingXl 16.00f +`; +/* end snapshot integration ios objective-c ios/macros.h should match snapshot */ + +snapshots["integration ios objective-c ios/static.h should match snapshot"] = +` +// static.h +// + +// Do not edit directly, this file was auto-generated. + + +#import + + +extern CGFloat const SizeBorderRadiusLarge; +extern CGFloat const SizeFontSmall; +extern CGFloat const SizeFontMedium; +extern CGFloat const SizeFontLarge; +extern CGFloat const SizeFontXl; +extern CGFloat const SizePaddingSmall; +extern CGFloat const SizePaddingMedium; +extern CGFloat const SizePaddingLarge; +extern CGFloat const SizePaddingXl;`; +/* end snapshot integration ios objective-c ios/static.h should match snapshot */ + +snapshots["integration ios objective-c ios/static.m should match snapshot"] = +` +// +// static.m +// + +// Do not edit directly, this file was auto-generated. + + +#import "StyleDictionaryStatic.h" + + +CGFloat const SizeBorderRadiusLarge = 480.00f; +CGFloat const SizeFontSmall = 12.00f; +CGFloat const SizeFontMedium = 16.00f; +CGFloat const SizeFontLarge = 24.00f; +CGFloat const SizeFontXl = 36.00f; +CGFloat const SizePaddingSmall = 8.00f; +CGFloat const SizePaddingMedium = 16.00f; +CGFloat const SizePaddingLarge = 16.00f; +CGFloat const SizePaddingXl = 16.00f;`; +/* end snapshot integration ios objective-c ios/static.m should match snapshot */ + diff --git a/__integration__/__snapshots__/nameCollisions.test.snap.js b/__integration__/__snapshots__/nameCollisions.test.snap.js new file mode 100644 index 000000000..fe25bec64 --- /dev/null +++ b/__integration__/__snapshots__/nameCollisions.test.snap.js @@ -0,0 +1,22 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration name collisions should warn users of name collisions for flat files"] = +`⚠️ __integration__/build/variables.css +While building variables.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. +Output name red was generated by: +color.red #f00 +color.background.red #f00 +This many-to-one issue is usually caused by some combination of: +* conflicting or similar paths/names in token definitions +* platform transforms/transformGroups affecting names, especially when removing specificity +* overly inclusive file filters`; +/* end snapshot integration name collisions should warn users of name collisions for flat files */ + +snapshots["integration name collisions should warn users of name collisions for flat files, brief version"] = +`⚠️ __integration__/build/variables.css +While building variables.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration name collisions should warn users of name collisions for flat files, brief version */ + diff --git a/__integration__/__snapshots__/objectValues.test.js.snap b/__integration__/__snapshots__/objectValues.test.js.snap deleted file mode 100644 index 63e155095..000000000 --- a/__integration__/__snapshots__/objectValues.test.js.snap +++ /dev/null @@ -1,121 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration object values css/variables border should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --border-primary: 0.125rem solid #ff0000; -} -" -`; - -exports[`integration object values css/variables border with references should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --border-primary: var(--size-border) solid var(--color-red); -} -" -`; - -exports[`integration object values css/variables hex syntax should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --color-red: #ff0000; - --color-green: #40bf40; -} -" -`; - -exports[`integration object values css/variables hex syntax with references should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --color-red: #ff0000; - --color-green: #40bf40; -} -" -`; - -exports[`integration object values css/variables hsl syntax should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --color-red: #ff0000; - --color-green: hsl(120, 50%, 50%); -} -" -`; - -exports[`integration object values css/variables hsl syntax with references should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --color-red: #ff0000; - --color-green: hsl(120, 50%, 50%); -} -" -`; - -exports[`integration object values css/variables shadow should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --shadow-light: #ff0000, #40bf40; - --shadow-dark: #40bf40, #ff0000; -} -" -`; - -exports[`integration object values css/variables shadow should match snapshot with references 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --shadow-light: var(--color-red), var(--color-green); - --shadow-dark: var(--color-green), var(--color-red); -} -" -`; - -exports[`integration object values scss/variables should match snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -$border-primary: 0.125rem solid #ff0000; -" -`; - -exports[`integration object values scss/variables with references should match snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -$border-primary: $size-border solid $color-red; -" -`; diff --git a/__integration__/__snapshots__/objectValues.test.snap.js b/__integration__/__snapshots__/objectValues.test.snap.js new file mode 100644 index 000000000..a09c7d6c1 --- /dev/null +++ b/__integration__/__snapshots__/objectValues.test.snap.js @@ -0,0 +1,233 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["css/variables hsl syntax should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --color-red: #ff0000; + --color-green: hsl(120, 50%, 50%); +} +`; +/* end snapshot css/variables hsl syntax should match snapshot */ + +snapshots["css/variables hsl syntax with references should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --color-red: #ff0000; + --color-green: hsl(120, 50%, 50%); +} +`; +/* end snapshot css/variables hsl syntax with references should match snapshot */ + +snapshots["css/variables hex syntax should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --color-red: #ff0000; + --color-green: #40bf40; +} +`; +/* end snapshot css/variables hex syntax should match snapshot */ + +snapshots["css/variables hex syntax with references should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --color-red: #ff0000; + --color-green: #40bf40; +} +`; +/* end snapshot css/variables hex syntax with references should match snapshot */ + +snapshots["css/variables border should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --border-primary: 0.125rem solid #ff0000; +} +`; +/* end snapshot css/variables border should match snapshot */ + +snapshots["css/variables border with references should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --border-primary: var(--size-border) solid var(--color-red); +} +`; +/* end snapshot css/variables border with references should match snapshot */ + +snapshots["css/variables shadow should match snapshot"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --shadow-light: 0 0 0 #ff0000, 0 0 0 #40bf40; + --shadow-dark: 0 0 0 #40bf40, 0 0 0 #ff0000; +} +`; +/* end snapshot css/variables shadow should match snapshot */ + +snapshots["css/variables shadow should match snapshot with references"] = +`/** + * Do not edit directly + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --shadow-light: 0 0 0 var(--color-red), 0 0 0 var(--color-green); + --shadow-dark: 0 0 0 var(--color-green), 0 0 0 var(--color-red); +} +`; +/* end snapshot css/variables shadow should match snapshot with references */ + +snapshots["scss/variables should match snapshot"] = +` +// Do not edit directly +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +$border-primary: 0.125rem solid #ff0000; +`; +/* end snapshot scss/variables should match snapshot */ + +snapshots["scss/variables with references should match snapshot"] = +` +// Do not edit directly +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +$border-primary: $size-border solid $color-red; +`; +/* end snapshot scss/variables with references should match snapshot */ + +snapshots["integration object values css/variables shadow should match snapshot with references"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --shadow-light: 0 0 0 var(--color-red), 0 0 0 var(--color-green); + --shadow-dark: 0 0 0 var(--color-green), 0 0 0 var(--color-red); +} +`; +/* end snapshot integration object values css/variables shadow should match snapshot with references */ + +snapshots["integration object values css/variables hsl syntax should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --color-red: #ff0000; + --color-green: hsl(120, 50%, 50%); +} +`; +/* end snapshot integration object values css/variables hsl syntax should match snapshot */ + +snapshots["integration object values css/variables hsl syntax with references should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --color-red: #ff0000; + --color-green: hsl(120, 50%, 50%); +} +`; +/* end snapshot integration object values css/variables hsl syntax with references should match snapshot */ + +snapshots["integration object values css/variables hex syntax should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --color-red: #ff0000; + --color-green: #40bf40; +} +`; +/* end snapshot integration object values css/variables hex syntax should match snapshot */ + +snapshots["integration object values css/variables hex syntax with references should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --color-red: #ff0000; + --color-green: #40bf40; +} +`; +/* end snapshot integration object values css/variables hex syntax with references should match snapshot */ + +snapshots["integration object values css/variables border should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --border-primary: 0.125rem solid #ff0000; +} +`; +/* end snapshot integration object values css/variables border should match snapshot */ + +snapshots["integration object values css/variables border with references should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --border-primary: var(--size-border) solid var(--color-red); +} +`; +/* end snapshot integration object values css/variables border with references should match snapshot */ + +snapshots["integration object values css/variables shadow should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --shadow-light: 0 0 0 #ff0000, 0 0 0 #40bf40; + --shadow-dark: 0 0 0 #40bf40, 0 0 0 #ff0000; +} +`; +/* end snapshot integration object values css/variables shadow should match snapshot */ + +snapshots["integration object values scss/variables should match snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +$border-primary: 0.125rem solid #ff0000; +`; +/* end snapshot integration object values scss/variables should match snapshot */ + +snapshots["integration object values scss/variables with references should match snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +$border-primary: $size-border solid $color-red; +`; +/* end snapshot integration object values scss/variables with references should match snapshot */ + diff --git a/__integration__/__snapshots__/outputReferences.test.snap.js b/__integration__/__snapshots__/outputReferences.test.snap.js new file mode 100644 index 000000000..61c38b74f --- /dev/null +++ b/__integration__/__snapshots__/outputReferences.test.snap.js @@ -0,0 +1,42 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration output references should warn the user if filters out references briefly"] = +`⚠️ __integration__/build/filteredVariables.css +While building filteredVariables.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration output references should warn the user if filters out references briefly */ + +snapshots["integration output references should warn the user if filters out references with a detailed message when using verbose logging"] = +`⚠️ __integration__/build/filteredVariables.css +While building filteredVariables.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. +Here are the references that are used but not defined in the file: +color.core.neutral.100 +color.core.neutral.0 +color.core.neutral.200 +color.core.red.0 +color.core.orange.0 +color.core.green.0 +color.core.blue.0 +This is caused when combining a filter and \`outputReferences\`.`; +/* end snapshot integration output references should warn the user if filters out references with a detailed message when using verbose logging */ + +snapshots["integration output references should not warn the user if filters out references is prevented with outputReferencesFilter"] = +` +css +✔︎ __integration__/build/filteredVariables.css`; +/* end snapshot integration output references should not warn the user if filters out references is prevented with outputReferencesFilter */ + +snapshots["integration output references should allow using outputReferencesTransformed to not output refs when value has been transitively transformed"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --base: rgb(0,0,0); + --referred: rgba(0,0,0,0.12); +} +`; +/* end snapshot integration output references should allow using outputReferencesTransformed to not output refs when value has been transitively transformed */ + diff --git a/__integration__/__snapshots__/scss.test.js.snap b/__integration__/__snapshots__/scss.test.snap.js similarity index 97% rename from __integration__/__snapshots__/scss.test.js.snap rename to __integration__/__snapshots__/scss.test.snap.js index 2fab321f8..f6f6234c5 100644 --- a/__integration__/__snapshots__/scss.test.js.snap +++ b/__integration__/__snapshots__/scss.test.snap.js @@ -1,11 +1,178 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; -exports[`integration scss scss/map-deep should match snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ +snapshots["integration scss scss/variables should match snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +$color-background-primary: #ffffff !default; +$color-background-secondary: #f3f4f4; +$color-background-tertiary: #dee1e1; +$color-background-danger: #ffeae9; +$color-background-warning: #ffede3; +$color-background-success: #ebf9eb; +$color-background-info: #e9f8ff; +$color-background-disabled: #dee1e1; +$color-border-primary: #c8cccc; +$color-brand-primary: #0b8599; +$color-brand-secondary: #6f5ed3; +$color-core-green-0: #ebf9eb; +$color-core-green-100: #d7f4d7; +$color-core-green-200: #c2f2bd; +$color-core-green-300: #98e58e; +$color-core-green-400: #75dd66; +$color-core-green-500: #59cb59; +$color-core-green-600: #2bb656; +$color-core-green-700: #0ca750; +$color-core-green-800: #008b46; +$color-core-green-900: #006b40; +$color-core-green-1000: #08422f; +$color-core-green-1100: #002b20; +$color-core-teal-0: #e5f9f5; +$color-core-teal-100: #cdf7ef; +$color-core-teal-200: #b3f2e6; +$color-core-teal-300: #7dead5; +$color-core-teal-400: #24e0c5; +$color-core-teal-500: #08c4b2; +$color-core-teal-600: #00a99c; +$color-core-teal-700: #0b968f; +$color-core-teal-800: #067c7c; +$color-core-teal-900: #026661; +$color-core-teal-1000: #083f3f; +$color-core-teal-1100: #002528; +$color-core-aqua-0: #d9fcfb; +$color-core-aqua-100: #c5f9f9; +$color-core-aqua-200: #a5f2f2; +$color-core-aqua-300: #76e5e2; +$color-core-aqua-400: #33d6e2; +$color-core-aqua-500: #17b8ce; +$color-core-aqua-600: #0797ae; +$color-core-aqua-700: #0b8599; +$color-core-aqua-800: #0f6e84; +$color-core-aqua-900: #035e73; +$color-core-aqua-1000: #083d4f; +$color-core-aqua-1100: #002838; +$color-core-blue-0: #e9f8ff; +$color-core-blue-100: #dcf2ff; +$color-core-blue-200: #c7e4f9; +$color-core-blue-300: #a1d2f8; +$color-core-blue-400: #56adf5; +$color-core-blue-500: #3896e3; +$color-core-blue-600: #2b87d3; +$color-core-blue-700: #2079c3; +$color-core-blue-800: #116daa; +$color-core-blue-900: #0c5689; +$color-core-blue-1000: #0a3960; +$color-core-blue-1100: #002138; +$color-core-purple-0: #f2f2f9; +$color-core-purple-100: #eaeaf9; +$color-core-purple-200: #d8d7f9; +$color-core-purple-300: #c1c1f7; +$color-core-purple-400: #a193f2; +$color-core-purple-500: #9180f4; +$color-core-purple-600: #816fea; +$color-core-purple-700: #6f5ed3; +$color-core-purple-800: #5e4eba; +$color-core-purple-900: #483a9c; +$color-core-purple-1000: #2d246b; +$color-core-purple-1100: #1d1d38; +$color-core-magenta-0: #fef0ff; +$color-core-magenta-100: #f9e3fc; +$color-core-magenta-200: #f4c4f7; +$color-core-magenta-300: #edadf2; +$color-core-magenta-400: #f282f5; +$color-core-magenta-500: #db61db; +$color-core-magenta-600: #c44eb9; +$color-core-magenta-700: #ac44a8; +$color-core-magenta-800: #8f3896; +$color-core-magenta-900: #6c2277; +$color-core-magenta-1000: #451551; +$color-core-magenta-1100: #29192d; +$color-core-pink-0: #ffe9f3; +$color-core-pink-100: #fcdbeb; +$color-core-pink-200: #ffb5d5; +$color-core-pink-300: #ff95c1; +$color-core-pink-400: #ff76ae; +$color-core-pink-500: #ef588b; +$color-core-pink-600: #e0447c; +$color-core-pink-700: #ce3665; +$color-core-pink-800: #b22f5b; +$color-core-pink-900: #931847; +$color-core-pink-1000: #561231; +$color-core-pink-1100: #2b1721; +$color-core-red-0: #ffeae9; +$color-core-red-100: #ffd5d2; +$color-core-red-200: #ffb8b1; +$color-core-red-300: #ff9c8f; +$color-core-red-400: #ff7f6e; +$color-core-red-500: #f76054; +$color-core-red-600: #ed4c42; +$color-core-red-700: #db3e3e; +$color-core-red-800: #c63434; +$color-core-red-900: #992222; +$color-core-red-1000: #6d1313; +$color-core-red-1100: #2b1111; +$color-core-orange-0: #ffede3; +$color-core-orange-100: #fcdccc; +$color-core-orange-200: #ffc6a4; +$color-core-orange-300: #ffb180; +$color-core-orange-400: #ff9c5d; +$color-core-orange-500: #fc8943; +$color-core-orange-600: #f57d33; +$color-core-orange-700: #ed7024; +$color-core-orange-800: #ce5511; +$color-core-orange-900: #962c0b; +$color-core-orange-1000: #601700; +$color-core-orange-1100: #2d130e; +$color-core-neutral-0: #ffffff; +$color-core-neutral-100: #f3f4f4; +$color-core-neutral-200: #dee1e1; +$color-core-neutral-300: #c8cccc; +$color-core-neutral-400: #b0b6b7; +$color-core-neutral-500: #929a9b; +$color-core-neutral-600: #6e797a; +$color-core-neutral-700: #515e5f; +$color-core-neutral-800: #364141; +$color-core-neutral-900: #273333; +$color-core-neutral-1000: #162020; +$color-core-neutral-1100: #040404; +$color-core-yellow-0: #fff8e2; +$color-core-yellow-100: #fdefcd; +$color-core-yellow-200: #ffe99a; +$color-core-yellow-300: #ffe16e; +$color-core-yellow-400: #ffd943; +$color-core-yellow-500: #ffcd1c; +$color-core-yellow-600: #ffbc00; +$color-core-yellow-700: #dd9903; +$color-core-yellow-800: #ba7506; +$color-core-yellow-900: #944c0c; +$color-core-yellow-1000: #542a00; +$color-core-yellow-1100: #2d1a05; +$color-font-primary: #040404; +$color-font-secondary: #273333; +$color-font-tertiary: #364141; +$color-font-interactive: #0b8599; +$color-font-interactive-hover: #0b8599; +$color-font-interactive-active: #6f5ed3; +$color-font-interactive-disabled: #364141; +$color-font-danger: #6d1313; +$color-font-warning: #601700; +$color-font-success: #08422f; +$size-border-radius-large: 30rem; +$size-font-small: 0.75rem; +$size-font-medium: 1rem; +$size-font-large: 1.5rem; +$size-font-xl: 2.25rem; +$size-padding-small: 0.5rem; +$size-padding-medium: 1rem; +$size-padding-large: 1rem; +$size-padding-xl: 1rem; +`; +/* end snapshot integration scss scss/variables should match snapshot */ + +snapshots["integration scss scss/variables with themeable should match snapshot"] = +` +// Do not edit directly, this file was auto-generated. $color-background-primary: #ffffff !default; $color-background-secondary: #f3f4f4 !default; @@ -169,784 +336,533 @@ $size-padding-small: 0.5rem !default; $size-padding-medium: 1rem !default; $size-padding-large: 1rem !default; $size-padding-xl: 1rem !default; +`; +/* end snapshot integration scss scss/variables with themeable should match snapshot */ -$design-system-tokens: ( - 'color': ( - 'background': ( - 'primary': $color-background-primary, - 'secondary': $color-background-secondary, - 'tertiary': $color-background-tertiary, - 'danger': $color-background-danger, - 'warning': $color-background-warning, - 'success': $color-background-success, - 'info': $color-background-info, - 'disabled': $color-background-disabled - ), - 'border': ( - 'primary': $color-border-primary, - 'secondary': ( - - ), - 'tertiary': ( +snapshots["integration scss scss/variables with outputReferences should match snapshot"] = +` +// Do not edit directly, this file was auto-generated. - ) - ), - 'brand': ( - 'primary': $color-brand-primary, - 'secondary': $color-brand-secondary - ), - 'core': ( - 'green': ( - '0': $color-core-green-0, - '100': $color-core-green-100, - '200': $color-core-green-200, - '300': $color-core-green-300, - '400': $color-core-green-400, - '500': $color-core-green-500, - '600': $color-core-green-600, - '700': $color-core-green-700, - '800': $color-core-green-800, - '900': $color-core-green-900, - '1000': $color-core-green-1000, - '1100': $color-core-green-1100 - ), - 'teal': ( - '0': $color-core-teal-0, - '100': $color-core-teal-100, - '200': $color-core-teal-200, - '300': $color-core-teal-300, - '400': $color-core-teal-400, - '500': $color-core-teal-500, - '600': $color-core-teal-600, - '700': $color-core-teal-700, - '800': $color-core-teal-800, - '900': $color-core-teal-900, - '1000': $color-core-teal-1000, - '1100': $color-core-teal-1100 - ), - 'aqua': ( - '0': $color-core-aqua-0, - '100': $color-core-aqua-100, - '200': $color-core-aqua-200, - '300': $color-core-aqua-300, - '400': $color-core-aqua-400, - '500': $color-core-aqua-500, - '600': $color-core-aqua-600, - '700': $color-core-aqua-700, - '800': $color-core-aqua-800, - '900': $color-core-aqua-900, - '1000': $color-core-aqua-1000, - '1100': $color-core-aqua-1100 - ), - 'blue': ( - '0': $color-core-blue-0, - '100': $color-core-blue-100, - '200': $color-core-blue-200, - '300': $color-core-blue-300, - '400': $color-core-blue-400, - '500': $color-core-blue-500, - '600': $color-core-blue-600, - '700': $color-core-blue-700, - '800': $color-core-blue-800, - '900': $color-core-blue-900, - '1000': $color-core-blue-1000, - '1100': $color-core-blue-1100 - ), - 'purple': ( - '0': $color-core-purple-0, - '100': $color-core-purple-100, - '200': $color-core-purple-200, - '300': $color-core-purple-300, - '400': $color-core-purple-400, - '500': $color-core-purple-500, - '600': $color-core-purple-600, - '700': $color-core-purple-700, - '800': $color-core-purple-800, - '900': $color-core-purple-900, - '1000': $color-core-purple-1000, - '1100': $color-core-purple-1100 - ), - 'magenta': ( - '0': $color-core-magenta-0, - '100': $color-core-magenta-100, - '200': $color-core-magenta-200, - '300': $color-core-magenta-300, - '400': $color-core-magenta-400, - '500': $color-core-magenta-500, - '600': $color-core-magenta-600, - '700': $color-core-magenta-700, - '800': $color-core-magenta-800, - '900': $color-core-magenta-900, - '1000': $color-core-magenta-1000, - '1100': $color-core-magenta-1100 - ), - 'pink': ( - '0': $color-core-pink-0, - '100': $color-core-pink-100, - '200': $color-core-pink-200, - '300': $color-core-pink-300, - '400': $color-core-pink-400, - '500': $color-core-pink-500, - '600': $color-core-pink-600, - '700': $color-core-pink-700, - '800': $color-core-pink-800, - '900': $color-core-pink-900, - '1000': $color-core-pink-1000, - '1100': $color-core-pink-1100 - ), - 'red': ( - '0': $color-core-red-0, - '100': $color-core-red-100, - '200': $color-core-red-200, - '300': $color-core-red-300, - '400': $color-core-red-400, - '500': $color-core-red-500, - '600': $color-core-red-600, - '700': $color-core-red-700, - '800': $color-core-red-800, - '900': $color-core-red-900, - '1000': $color-core-red-1000, - '1100': $color-core-red-1100 - ), - 'orange': ( - '0': $color-core-orange-0, - '100': $color-core-orange-100, - '200': $color-core-orange-200, - '300': $color-core-orange-300, - '400': $color-core-orange-400, - '500': $color-core-orange-500, - '600': $color-core-orange-600, - '700': $color-core-orange-700, - '800': $color-core-orange-800, - '900': $color-core-orange-900, - '1000': $color-core-orange-1000, - '1100': $color-core-orange-1100 - ), - 'neutral': ( - '0': $color-core-neutral-0, - '100': $color-core-neutral-100, - '200': $color-core-neutral-200, - '300': $color-core-neutral-300, - '400': $color-core-neutral-400, - '500': $color-core-neutral-500, - '600': $color-core-neutral-600, - '700': $color-core-neutral-700, - '800': $color-core-neutral-800, - '900': $color-core-neutral-900, - '1000': $color-core-neutral-1000, - '1100': $color-core-neutral-1100 - ), - 'yellow': ( - '0': $color-core-yellow-0, - '100': $color-core-yellow-100, - '200': $color-core-yellow-200, - '300': $color-core-yellow-300, - '400': $color-core-yellow-400, - '500': $color-core-yellow-500, - '600': $color-core-yellow-600, - '700': $color-core-yellow-700, - '800': $color-core-yellow-800, - '900': $color-core-yellow-900, - '1000': $color-core-yellow-1000, - '1100': $color-core-yellow-1100 - ) - ), - 'font': ( - 'primary': $color-font-primary, - 'secondary': $color-font-secondary, - 'tertiary': $color-font-tertiary, - 'interactive': ( - '_': $color-font-interactive, - 'hover': $color-font-interactive-hover, - 'active': $color-font-interactive-active, - 'disabled': $color-font-interactive-disabled - ), - 'danger': $color-font-danger, - 'warning': $color-font-warning, - 'success': $color-font-success - ) - ), - 'size': ( - 'border': ( - 'radius': ( - 'large': $size-border-radius-large - ) - ), - 'font': ( - 'small': $size-font-small, - 'medium': $size-font-medium, - 'large': $size-font-large, - 'xl': $size-font-xl - ), - 'padding': ( - 'small': $size-padding-small, - 'medium': $size-padding-medium, - 'large': $size-padding-large, - 'xl': $size-padding-xl - ) - ) -); -" -`; - -exports[`integration scss scss/map-deep with outputReferences should match snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$size-padding-xl: 1rem !default; -$size-padding-large: 1rem !default; -$size-padding-medium: 1rem !default; -$size-padding-small: 0.5rem !default; -$size-font-xl: 2.25rem !default; -$size-font-large: 1.5rem !default; -$size-font-medium: 1rem !default; -$size-font-small: 0.75rem !default; -$size-border-radius-large: 30rem !default; -$color-core-yellow-1100: #2d1a05 !default; -$color-core-yellow-1000: #542a00 !default; -$color-core-yellow-900: #944c0c !default; -$color-core-yellow-800: #ba7506 !default; -$color-core-yellow-700: #dd9903 !default; -$color-core-yellow-600: #ffbc00 !default; -$color-core-yellow-500: #ffcd1c !default; -$color-core-yellow-400: #ffd943 !default; -$color-core-yellow-300: #ffe16e !default; -$color-core-yellow-200: #ffe99a !default; -$color-core-yellow-100: #fdefcd !default; -$color-core-yellow-0: #fff8e2 !default; -$color-core-neutral-1100: #040404 !default; -$color-core-neutral-1000: #162020 !default; -$color-core-neutral-900: #273333 !default; -$color-core-neutral-800: #364141 !default; -$color-core-neutral-700: #515e5f !default; -$color-core-neutral-600: #6e797a !default; -$color-core-neutral-500: #929a9b !default; -$color-core-neutral-400: #b0b6b7 !default; -$color-core-neutral-300: #c8cccc !default; -$color-core-neutral-200: #dee1e1 !default; -$color-core-neutral-100: #f3f4f4 !default; -$color-core-neutral-0: #ffffff !default; -$color-core-orange-1100: #2d130e !default; -$color-core-orange-1000: #601700 !default; -$color-core-orange-900: #962c0b !default; -$color-core-orange-800: #ce5511 !default; -$color-core-orange-700: #ed7024 !default; -$color-core-orange-600: #f57d33 !default; -$color-core-orange-500: #fc8943 !default; -$color-core-orange-400: #ff9c5d !default; -$color-core-orange-300: #ffb180 !default; -$color-core-orange-200: #ffc6a4 !default; -$color-core-orange-100: #fcdccc !default; -$color-core-orange-0: #ffede3 !default; -$color-core-red-1100: #2b1111 !default; -$color-core-red-1000: #6d1313 !default; -$color-core-red-900: #992222 !default; -$color-core-red-800: #c63434 !default; -$color-core-red-700: #db3e3e !default; -$color-core-red-600: #ed4c42 !default; -$color-core-red-500: #f76054 !default; -$color-core-red-400: #ff7f6e !default; -$color-core-red-300: #ff9c8f !default; -$color-core-red-200: #ffb8b1 !default; -$color-core-red-100: #ffd5d2 !default; -$color-core-red-0: #ffeae9 !default; -$color-core-pink-1100: #2b1721 !default; -$color-core-pink-1000: #561231 !default; -$color-core-pink-900: #931847 !default; -$color-core-pink-800: #b22f5b !default; -$color-core-pink-700: #ce3665 !default; -$color-core-pink-600: #e0447c !default; -$color-core-pink-500: #ef588b !default; -$color-core-pink-400: #ff76ae !default; -$color-core-pink-300: #ff95c1 !default; -$color-core-pink-200: #ffb5d5 !default; -$color-core-pink-100: #fcdbeb !default; -$color-core-pink-0: #ffe9f3 !default; -$color-core-magenta-1100: #29192d !default; -$color-core-magenta-1000: #451551 !default; -$color-core-magenta-900: #6c2277 !default; -$color-core-magenta-800: #8f3896 !default; -$color-core-magenta-700: #ac44a8 !default; -$color-core-magenta-600: #c44eb9 !default; -$color-core-magenta-500: #db61db !default; -$color-core-magenta-400: #f282f5 !default; -$color-core-magenta-300: #edadf2 !default; -$color-core-magenta-200: #f4c4f7 !default; -$color-core-magenta-100: #f9e3fc !default; -$color-core-magenta-0: #fef0ff !default; -$color-core-purple-1100: #1d1d38 !default; -$color-core-purple-1000: #2d246b !default; -$color-core-purple-900: #483a9c !default; -$color-core-purple-800: #5e4eba !default; -$color-core-purple-700: #6f5ed3 !default; -$color-core-purple-600: #816fea !default; -$color-core-purple-500: #9180f4 !default; -$color-core-purple-400: #a193f2 !default; -$color-core-purple-300: #c1c1f7 !default; -$color-core-purple-200: #d8d7f9 !default; -$color-core-purple-100: #eaeaf9 !default; -$color-core-purple-0: #f2f2f9 !default; -$color-core-blue-1100: #002138 !default; -$color-core-blue-1000: #0a3960 !default; -$color-core-blue-900: #0c5689 !default; -$color-core-blue-800: #116daa !default; -$color-core-blue-700: #2079c3 !default; -$color-core-blue-600: #2b87d3 !default; -$color-core-blue-500: #3896e3 !default; -$color-core-blue-400: #56adf5 !default; -$color-core-blue-300: #a1d2f8 !default; -$color-core-blue-200: #c7e4f9 !default; -$color-core-blue-100: #dcf2ff !default; -$color-core-blue-0: #e9f8ff !default; -$color-core-aqua-1100: #002838 !default; -$color-core-aqua-1000: #083d4f !default; -$color-core-aqua-900: #035e73 !default; -$color-core-aqua-800: #0f6e84 !default; -$color-core-aqua-700: #0b8599 !default; -$color-core-aqua-600: #0797ae !default; -$color-core-aqua-500: #17b8ce !default; -$color-core-aqua-400: #33d6e2 !default; -$color-core-aqua-300: #76e5e2 !default; -$color-core-aqua-200: #a5f2f2 !default; -$color-core-aqua-100: #c5f9f9 !default; -$color-core-aqua-0: #d9fcfb !default; -$color-core-teal-1100: #002528 !default; -$color-core-teal-1000: #083f3f !default; -$color-core-teal-900: #026661 !default; -$color-core-teal-800: #067c7c !default; -$color-core-teal-700: #0b968f !default; -$color-core-teal-600: #00a99c !default; -$color-core-teal-500: #08c4b2 !default; -$color-core-teal-400: #24e0c5 !default; -$color-core-teal-300: #7dead5 !default; -$color-core-teal-200: #b3f2e6 !default; -$color-core-teal-100: #cdf7ef !default; -$color-core-teal-0: #e5f9f5 !default; -$color-core-green-1100: #002b20 !default; -$color-core-green-1000: #08422f !default; -$color-core-green-900: #006b40 !default; -$color-core-green-800: #008b46 !default; -$color-core-green-700: #0ca750 !default; -$color-core-green-600: #2bb656 !default; -$color-core-green-500: #59cb59 !default; -$color-core-green-400: #75dd66 !default; -$color-core-green-300: #98e58e !default; -$color-core-green-200: #c2f2bd !default; -$color-core-green-100: #d7f4d7 !default; -$color-core-green-0: #ebf9eb !default; -$color-font-success: $color-core-green-1000 !default; -$color-font-warning: $color-core-orange-1000 !default; -$color-font-danger: $color-core-red-1000 !default; -$color-font-tertiary: $color-core-neutral-800 !default; -$color-font-secondary: $color-core-neutral-900 !default; -$color-font-primary: $color-core-neutral-1100 !default; -$color-brand-secondary: $color-core-purple-700 !default; -$color-brand-primary: $color-core-aqua-700 !default; -$color-border-primary: $color-core-neutral-300 !default; -$color-background-info: $color-core-blue-0 !default; -$color-background-success: $color-core-green-0 !default; -$color-background-warning: $color-core-orange-0 !default; -$color-background-danger: $color-core-red-0 !default; -$color-background-tertiary: $color-core-neutral-200 !default; -$color-background-secondary: $color-core-neutral-100 !default; -$color-background-primary: $color-core-neutral-0 !default; -$color-font-interactive-disabled: $color-font-tertiary !default; -$color-font-interactive-active: $color-brand-secondary !default; -$color-font-interactive-hover: $color-brand-primary !default; -$color-font-interactive: $color-brand-primary !default; -$color-background-disabled: $color-background-tertiary !default; - -$design-system-tokens: ( - 'color': ( - 'background': ( - 'primary': $color-background-primary, - 'secondary': $color-background-secondary, - 'tertiary': $color-background-tertiary, - 'danger': $color-background-danger, - 'warning': $color-background-warning, - 'success': $color-background-success, - 'info': $color-background-info, - 'disabled': $color-background-disabled - ), - 'border': ( - 'primary': $color-border-primary, - 'secondary': ( - - ), - 'tertiary': ( - - ) - ), - 'brand': ( - 'primary': $color-brand-primary, - 'secondary': $color-brand-secondary - ), - 'core': ( - 'green': ( - '0': $color-core-green-0, - '100': $color-core-green-100, - '200': $color-core-green-200, - '300': $color-core-green-300, - '400': $color-core-green-400, - '500': $color-core-green-500, - '600': $color-core-green-600, - '700': $color-core-green-700, - '800': $color-core-green-800, - '900': $color-core-green-900, - '1000': $color-core-green-1000, - '1100': $color-core-green-1100 - ), - 'teal': ( - '0': $color-core-teal-0, - '100': $color-core-teal-100, - '200': $color-core-teal-200, - '300': $color-core-teal-300, - '400': $color-core-teal-400, - '500': $color-core-teal-500, - '600': $color-core-teal-600, - '700': $color-core-teal-700, - '800': $color-core-teal-800, - '900': $color-core-teal-900, - '1000': $color-core-teal-1000, - '1100': $color-core-teal-1100 - ), - 'aqua': ( - '0': $color-core-aqua-0, - '100': $color-core-aqua-100, - '200': $color-core-aqua-200, - '300': $color-core-aqua-300, - '400': $color-core-aqua-400, - '500': $color-core-aqua-500, - '600': $color-core-aqua-600, - '700': $color-core-aqua-700, - '800': $color-core-aqua-800, - '900': $color-core-aqua-900, - '1000': $color-core-aqua-1000, - '1100': $color-core-aqua-1100 - ), - 'blue': ( - '0': $color-core-blue-0, - '100': $color-core-blue-100, - '200': $color-core-blue-200, - '300': $color-core-blue-300, - '400': $color-core-blue-400, - '500': $color-core-blue-500, - '600': $color-core-blue-600, - '700': $color-core-blue-700, - '800': $color-core-blue-800, - '900': $color-core-blue-900, - '1000': $color-core-blue-1000, - '1100': $color-core-blue-1100 - ), - 'purple': ( - '0': $color-core-purple-0, - '100': $color-core-purple-100, - '200': $color-core-purple-200, - '300': $color-core-purple-300, - '400': $color-core-purple-400, - '500': $color-core-purple-500, - '600': $color-core-purple-600, - '700': $color-core-purple-700, - '800': $color-core-purple-800, - '900': $color-core-purple-900, - '1000': $color-core-purple-1000, - '1100': $color-core-purple-1100 - ), - 'magenta': ( - '0': $color-core-magenta-0, - '100': $color-core-magenta-100, - '200': $color-core-magenta-200, - '300': $color-core-magenta-300, - '400': $color-core-magenta-400, - '500': $color-core-magenta-500, - '600': $color-core-magenta-600, - '700': $color-core-magenta-700, - '800': $color-core-magenta-800, - '900': $color-core-magenta-900, - '1000': $color-core-magenta-1000, - '1100': $color-core-magenta-1100 - ), - 'pink': ( - '0': $color-core-pink-0, - '100': $color-core-pink-100, - '200': $color-core-pink-200, - '300': $color-core-pink-300, - '400': $color-core-pink-400, - '500': $color-core-pink-500, - '600': $color-core-pink-600, - '700': $color-core-pink-700, - '800': $color-core-pink-800, - '900': $color-core-pink-900, - '1000': $color-core-pink-1000, - '1100': $color-core-pink-1100 - ), - 'red': ( - '0': $color-core-red-0, - '100': $color-core-red-100, - '200': $color-core-red-200, - '300': $color-core-red-300, - '400': $color-core-red-400, - '500': $color-core-red-500, - '600': $color-core-red-600, - '700': $color-core-red-700, - '800': $color-core-red-800, - '900': $color-core-red-900, - '1000': $color-core-red-1000, - '1100': $color-core-red-1100 - ), - 'orange': ( - '0': $color-core-orange-0, - '100': $color-core-orange-100, - '200': $color-core-orange-200, - '300': $color-core-orange-300, - '400': $color-core-orange-400, - '500': $color-core-orange-500, - '600': $color-core-orange-600, - '700': $color-core-orange-700, - '800': $color-core-orange-800, - '900': $color-core-orange-900, - '1000': $color-core-orange-1000, - '1100': $color-core-orange-1100 - ), - 'neutral': ( - '0': $color-core-neutral-0, - '100': $color-core-neutral-100, - '200': $color-core-neutral-200, - '300': $color-core-neutral-300, - '400': $color-core-neutral-400, - '500': $color-core-neutral-500, - '600': $color-core-neutral-600, - '700': $color-core-neutral-700, - '800': $color-core-neutral-800, - '900': $color-core-neutral-900, - '1000': $color-core-neutral-1000, - '1100': $color-core-neutral-1100 - ), - 'yellow': ( - '0': $color-core-yellow-0, - '100': $color-core-yellow-100, - '200': $color-core-yellow-200, - '300': $color-core-yellow-300, - '400': $color-core-yellow-400, - '500': $color-core-yellow-500, - '600': $color-core-yellow-600, - '700': $color-core-yellow-700, - '800': $color-core-yellow-800, - '900': $color-core-yellow-900, - '1000': $color-core-yellow-1000, - '1100': $color-core-yellow-1100 - ) - ), - 'font': ( - 'primary': $color-font-primary, - 'secondary': $color-font-secondary, - 'tertiary': $color-font-tertiary, - 'interactive': ( - '_': $color-font-interactive, - 'hover': $color-font-interactive-hover, - 'active': $color-font-interactive-active, - 'disabled': $color-font-interactive-disabled - ), - 'danger': $color-font-danger, - 'warning': $color-font-warning, - 'success': $color-font-success - ) - ), - 'size': ( - 'border': ( - 'radius': ( - 'large': $size-border-radius-large - ) - ), - 'font': ( - 'small': $size-font-small, - 'medium': $size-font-medium, - 'large': $size-font-large, - 'xl': $size-font-xl - ), - 'padding': ( - 'small': $size-padding-small, - 'medium': $size-padding-medium, - 'large': $size-padding-large, - 'xl': $size-padding-xl - ) - ) -); -" +$size-padding-xl: 1rem; +$size-padding-large: 1rem; +$size-padding-medium: 1rem; +$size-padding-small: 0.5rem; +$size-font-xl: 2.25rem; +$size-font-large: 1.5rem; +$size-font-medium: 1rem; +$size-font-small: 0.75rem; +$size-border-radius-large: 30rem; +$color-core-yellow-1100: #2d1a05; +$color-core-yellow-1000: #542a00; +$color-core-yellow-900: #944c0c; +$color-core-yellow-800: #ba7506; +$color-core-yellow-700: #dd9903; +$color-core-yellow-600: #ffbc00; +$color-core-yellow-500: #ffcd1c; +$color-core-yellow-400: #ffd943; +$color-core-yellow-300: #ffe16e; +$color-core-yellow-200: #ffe99a; +$color-core-yellow-100: #fdefcd; +$color-core-yellow-0: #fff8e2; +$color-core-neutral-1100: #040404; +$color-core-neutral-1000: #162020; +$color-core-neutral-900: #273333; +$color-core-neutral-800: #364141; +$color-core-neutral-700: #515e5f; +$color-core-neutral-600: #6e797a; +$color-core-neutral-500: #929a9b; +$color-core-neutral-400: #b0b6b7; +$color-core-neutral-300: #c8cccc; +$color-core-neutral-200: #dee1e1; +$color-core-neutral-100: #f3f4f4; +$color-core-neutral-0: #ffffff; +$color-core-orange-1100: #2d130e; +$color-core-orange-1000: #601700; +$color-core-orange-900: #962c0b; +$color-core-orange-800: #ce5511; +$color-core-orange-700: #ed7024; +$color-core-orange-600: #f57d33; +$color-core-orange-500: #fc8943; +$color-core-orange-400: #ff9c5d; +$color-core-orange-300: #ffb180; +$color-core-orange-200: #ffc6a4; +$color-core-orange-100: #fcdccc; +$color-core-orange-0: #ffede3; +$color-core-red-1100: #2b1111; +$color-core-red-1000: #6d1313; +$color-core-red-900: #992222; +$color-core-red-800: #c63434; +$color-core-red-700: #db3e3e; +$color-core-red-600: #ed4c42; +$color-core-red-500: #f76054; +$color-core-red-400: #ff7f6e; +$color-core-red-300: #ff9c8f; +$color-core-red-200: #ffb8b1; +$color-core-red-100: #ffd5d2; +$color-core-red-0: #ffeae9; +$color-core-pink-1100: #2b1721; +$color-core-pink-1000: #561231; +$color-core-pink-900: #931847; +$color-core-pink-800: #b22f5b; +$color-core-pink-700: #ce3665; +$color-core-pink-600: #e0447c; +$color-core-pink-500: #ef588b; +$color-core-pink-400: #ff76ae; +$color-core-pink-300: #ff95c1; +$color-core-pink-200: #ffb5d5; +$color-core-pink-100: #fcdbeb; +$color-core-pink-0: #ffe9f3; +$color-core-magenta-1100: #29192d; +$color-core-magenta-1000: #451551; +$color-core-magenta-900: #6c2277; +$color-core-magenta-800: #8f3896; +$color-core-magenta-700: #ac44a8; +$color-core-magenta-600: #c44eb9; +$color-core-magenta-500: #db61db; +$color-core-magenta-400: #f282f5; +$color-core-magenta-300: #edadf2; +$color-core-magenta-200: #f4c4f7; +$color-core-magenta-100: #f9e3fc; +$color-core-magenta-0: #fef0ff; +$color-core-purple-1100: #1d1d38; +$color-core-purple-1000: #2d246b; +$color-core-purple-900: #483a9c; +$color-core-purple-800: #5e4eba; +$color-core-purple-700: #6f5ed3; +$color-core-purple-600: #816fea; +$color-core-purple-500: #9180f4; +$color-core-purple-400: #a193f2; +$color-core-purple-300: #c1c1f7; +$color-core-purple-200: #d8d7f9; +$color-core-purple-100: #eaeaf9; +$color-core-purple-0: #f2f2f9; +$color-core-blue-1100: #002138; +$color-core-blue-1000: #0a3960; +$color-core-blue-900: #0c5689; +$color-core-blue-800: #116daa; +$color-core-blue-700: #2079c3; +$color-core-blue-600: #2b87d3; +$color-core-blue-500: #3896e3; +$color-core-blue-400: #56adf5; +$color-core-blue-300: #a1d2f8; +$color-core-blue-200: #c7e4f9; +$color-core-blue-100: #dcf2ff; +$color-core-blue-0: #e9f8ff; +$color-core-aqua-1100: #002838; +$color-core-aqua-1000: #083d4f; +$color-core-aqua-900: #035e73; +$color-core-aqua-800: #0f6e84; +$color-core-aqua-700: #0b8599; +$color-core-aqua-600: #0797ae; +$color-core-aqua-500: #17b8ce; +$color-core-aqua-400: #33d6e2; +$color-core-aqua-300: #76e5e2; +$color-core-aqua-200: #a5f2f2; +$color-core-aqua-100: #c5f9f9; +$color-core-aqua-0: #d9fcfb; +$color-core-teal-1100: #002528; +$color-core-teal-1000: #083f3f; +$color-core-teal-900: #026661; +$color-core-teal-800: #067c7c; +$color-core-teal-700: #0b968f; +$color-core-teal-600: #00a99c; +$color-core-teal-500: #08c4b2; +$color-core-teal-400: #24e0c5; +$color-core-teal-300: #7dead5; +$color-core-teal-200: #b3f2e6; +$color-core-teal-100: #cdf7ef; +$color-core-teal-0: #e5f9f5; +$color-core-green-1100: #002b20; +$color-core-green-1000: #08422f; +$color-core-green-900: #006b40; +$color-core-green-800: #008b46; +$color-core-green-700: #0ca750; +$color-core-green-600: #2bb656; +$color-core-green-500: #59cb59; +$color-core-green-400: #75dd66; +$color-core-green-300: #98e58e; +$color-core-green-200: #c2f2bd; +$color-core-green-100: #d7f4d7; +$color-core-green-0: #ebf9eb; +$color-font-success: $color-core-green-1000; +$color-font-warning: $color-core-orange-1000; +$color-font-danger: $color-core-red-1000; +$color-font-tertiary: $color-core-neutral-800; +$color-font-secondary: $color-core-neutral-900; +$color-font-primary: $color-core-neutral-1100; +$color-brand-secondary: $color-core-purple-700; +$color-brand-primary: $color-core-aqua-700; +$color-border-primary: $color-core-neutral-300; +$color-background-info: $color-core-blue-0; +$color-background-success: $color-core-green-0; +$color-background-warning: $color-core-orange-0; +$color-background-danger: $color-core-red-0; +$color-background-tertiary: $color-core-neutral-200; +$color-background-secondary: $color-core-neutral-100; +$color-background-primary: $color-core-neutral-0 !default; +$color-font-interactive-disabled: $color-font-tertiary; +$color-font-interactive-active: $color-brand-secondary; +$color-font-interactive-hover: $color-brand-primary; +$color-font-interactive: $color-brand-primary; +$color-background-disabled: $color-background-tertiary; +`; +/* end snapshot integration scss scss/variables with outputReferences should match snapshot */ + +snapshots["integration scss scss/variables with filter and output references should match snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +$color-background-info: $color-core-blue-0; +$color-background-success: $color-core-green-0; +$color-background-warning: $color-core-orange-0; +$color-background-danger: $color-core-red-0; +$color-background-tertiary: $color-core-neutral-200; +$color-background-secondary: $color-core-neutral-100; +$color-background-primary: $color-core-neutral-0 !default; +$color-background-disabled: $color-background-tertiary; `; +/* end snapshot integration scss scss/variables with filter and output references should match snapshot */ -exports[`integration scss scss/map-deep without themeable should match snapshot 1`] = ` -" +snapshots["integration scss scss/map-flat should match snapshot"] = +` /** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT + * Do not edit directly, this file was auto-generated. */ -$color-background-primary: #ffffff !default; -$color-background-secondary: #f3f4f4; -$color-background-tertiary: #dee1e1; -$color-background-danger: #ffeae9; -$color-background-warning: #ffede3; -$color-background-success: #ebf9eb; -$color-background-info: #e9f8ff; -$color-background-disabled: #dee1e1; -$color-border-primary: #c8cccc; -$color-brand-primary: #0b8599; -$color-brand-secondary: #6f5ed3; -$color-core-green-0: #ebf9eb; -$color-core-green-100: #d7f4d7; -$color-core-green-200: #c2f2bd; -$color-core-green-300: #98e58e; -$color-core-green-400: #75dd66; -$color-core-green-500: #59cb59; -$color-core-green-600: #2bb656; -$color-core-green-700: #0ca750; -$color-core-green-800: #008b46; -$color-core-green-900: #006b40; -$color-core-green-1000: #08422f; -$color-core-green-1100: #002b20; -$color-core-teal-0: #e5f9f5; -$color-core-teal-100: #cdf7ef; -$color-core-teal-200: #b3f2e6; -$color-core-teal-300: #7dead5; -$color-core-teal-400: #24e0c5; -$color-core-teal-500: #08c4b2; -$color-core-teal-600: #00a99c; -$color-core-teal-700: #0b968f; -$color-core-teal-800: #067c7c; -$color-core-teal-900: #026661; -$color-core-teal-1000: #083f3f; -$color-core-teal-1100: #002528; -$color-core-aqua-0: #d9fcfb; -$color-core-aqua-100: #c5f9f9; -$color-core-aqua-200: #a5f2f2; -$color-core-aqua-300: #76e5e2; -$color-core-aqua-400: #33d6e2; -$color-core-aqua-500: #17b8ce; -$color-core-aqua-600: #0797ae; -$color-core-aqua-700: #0b8599; -$color-core-aqua-800: #0f6e84; -$color-core-aqua-900: #035e73; -$color-core-aqua-1000: #083d4f; -$color-core-aqua-1100: #002838; -$color-core-blue-0: #e9f8ff; -$color-core-blue-100: #dcf2ff; -$color-core-blue-200: #c7e4f9; -$color-core-blue-300: #a1d2f8; -$color-core-blue-400: #56adf5; -$color-core-blue-500: #3896e3; -$color-core-blue-600: #2b87d3; -$color-core-blue-700: #2079c3; -$color-core-blue-800: #116daa; -$color-core-blue-900: #0c5689; -$color-core-blue-1000: #0a3960; -$color-core-blue-1100: #002138; -$color-core-purple-0: #f2f2f9; -$color-core-purple-100: #eaeaf9; -$color-core-purple-200: #d8d7f9; -$color-core-purple-300: #c1c1f7; -$color-core-purple-400: #a193f2; -$color-core-purple-500: #9180f4; -$color-core-purple-600: #816fea; -$color-core-purple-700: #6f5ed3; -$color-core-purple-800: #5e4eba; -$color-core-purple-900: #483a9c; -$color-core-purple-1000: #2d246b; -$color-core-purple-1100: #1d1d38; -$color-core-magenta-0: #fef0ff; -$color-core-magenta-100: #f9e3fc; -$color-core-magenta-200: #f4c4f7; -$color-core-magenta-300: #edadf2; -$color-core-magenta-400: #f282f5; -$color-core-magenta-500: #db61db; -$color-core-magenta-600: #c44eb9; -$color-core-magenta-700: #ac44a8; -$color-core-magenta-800: #8f3896; -$color-core-magenta-900: #6c2277; -$color-core-magenta-1000: #451551; -$color-core-magenta-1100: #29192d; -$color-core-pink-0: #ffe9f3; -$color-core-pink-100: #fcdbeb; -$color-core-pink-200: #ffb5d5; -$color-core-pink-300: #ff95c1; -$color-core-pink-400: #ff76ae; -$color-core-pink-500: #ef588b; -$color-core-pink-600: #e0447c; -$color-core-pink-700: #ce3665; -$color-core-pink-800: #b22f5b; -$color-core-pink-900: #931847; -$color-core-pink-1000: #561231; -$color-core-pink-1100: #2b1721; -$color-core-red-0: #ffeae9; -$color-core-red-100: #ffd5d2; -$color-core-red-200: #ffb8b1; -$color-core-red-300: #ff9c8f; -$color-core-red-400: #ff7f6e; -$color-core-red-500: #f76054; -$color-core-red-600: #ed4c42; -$color-core-red-700: #db3e3e; -$color-core-red-800: #c63434; -$color-core-red-900: #992222; -$color-core-red-1000: #6d1313; -$color-core-red-1100: #2b1111; -$color-core-orange-0: #ffede3; -$color-core-orange-100: #fcdccc; -$color-core-orange-200: #ffc6a4; -$color-core-orange-300: #ffb180; -$color-core-orange-400: #ff9c5d; -$color-core-orange-500: #fc8943; -$color-core-orange-600: #f57d33; -$color-core-orange-700: #ed7024; -$color-core-orange-800: #ce5511; -$color-core-orange-900: #962c0b; -$color-core-orange-1000: #601700; -$color-core-orange-1100: #2d130e; -$color-core-neutral-0: #ffffff; -$color-core-neutral-100: #f3f4f4; -$color-core-neutral-200: #dee1e1; -$color-core-neutral-300: #c8cccc; -$color-core-neutral-400: #b0b6b7; -$color-core-neutral-500: #929a9b; -$color-core-neutral-600: #6e797a; -$color-core-neutral-700: #515e5f; -$color-core-neutral-800: #364141; -$color-core-neutral-900: #273333; -$color-core-neutral-1000: #162020; -$color-core-neutral-1100: #040404; -$color-core-yellow-0: #fff8e2; -$color-core-yellow-100: #fdefcd; -$color-core-yellow-200: #ffe99a; -$color-core-yellow-300: #ffe16e; -$color-core-yellow-400: #ffd943; -$color-core-yellow-500: #ffcd1c; -$color-core-yellow-600: #ffbc00; -$color-core-yellow-700: #dd9903; -$color-core-yellow-800: #ba7506; -$color-core-yellow-900: #944c0c; -$color-core-yellow-1000: #542a00; -$color-core-yellow-1100: #2d1a05; -$color-font-primary: #040404; -$color-font-secondary: #273333; -$color-font-tertiary: #364141; -$color-font-interactive: #0b8599; -$color-font-interactive-hover: #0b8599; -$color-font-interactive-active: #6f5ed3; -$color-font-interactive-disabled: #364141; -$color-font-danger: #6d1313; -$color-font-warning: #601700; -$color-font-success: #08422f; -$size-border-radius-large: 30rem; -$size-font-small: 0.75rem; -$size-font-medium: 1rem; -$size-font-large: 1.5rem; -$size-font-xl: 2.25rem; -$size-padding-small: 0.5rem; -$size-padding-medium: 1rem; -$size-padding-large: 1rem; -$size-padding-xl: 1rem; +$design-system-tokens: ( + 'color-background-primary': #ffffff, + 'color-background-secondary': #f3f4f4, + 'color-background-tertiary': #dee1e1, + 'color-background-danger': #ffeae9, + 'color-background-warning': #ffede3, + 'color-background-success': #ebf9eb, + 'color-background-info': #e9f8ff, + 'color-background-disabled': #dee1e1, + 'color-border-primary': #c8cccc, + 'color-brand-primary': #0b8599, + 'color-brand-secondary': #6f5ed3, + 'color-core-green-0': #ebf9eb, + 'color-core-green-100': #d7f4d7, + 'color-core-green-200': #c2f2bd, + 'color-core-green-300': #98e58e, + 'color-core-green-400': #75dd66, + 'color-core-green-500': #59cb59, + 'color-core-green-600': #2bb656, + 'color-core-green-700': #0ca750, + 'color-core-green-800': #008b46, + 'color-core-green-900': #006b40, + 'color-core-green-1000': #08422f, + 'color-core-green-1100': #002b20, + 'color-core-teal-0': #e5f9f5, + 'color-core-teal-100': #cdf7ef, + 'color-core-teal-200': #b3f2e6, + 'color-core-teal-300': #7dead5, + 'color-core-teal-400': #24e0c5, + 'color-core-teal-500': #08c4b2, + 'color-core-teal-600': #00a99c, + 'color-core-teal-700': #0b968f, + 'color-core-teal-800': #067c7c, + 'color-core-teal-900': #026661, + 'color-core-teal-1000': #083f3f, + 'color-core-teal-1100': #002528, + 'color-core-aqua-0': #d9fcfb, + 'color-core-aqua-100': #c5f9f9, + 'color-core-aqua-200': #a5f2f2, + 'color-core-aqua-300': #76e5e2, + 'color-core-aqua-400': #33d6e2, + 'color-core-aqua-500': #17b8ce, + 'color-core-aqua-600': #0797ae, + 'color-core-aqua-700': #0b8599, + 'color-core-aqua-800': #0f6e84, + 'color-core-aqua-900': #035e73, + 'color-core-aqua-1000': #083d4f, + 'color-core-aqua-1100': #002838, + 'color-core-blue-0': #e9f8ff, + 'color-core-blue-100': #dcf2ff, + 'color-core-blue-200': #c7e4f9, + 'color-core-blue-300': #a1d2f8, + 'color-core-blue-400': #56adf5, + 'color-core-blue-500': #3896e3, + 'color-core-blue-600': #2b87d3, + 'color-core-blue-700': #2079c3, + 'color-core-blue-800': #116daa, + 'color-core-blue-900': #0c5689, + 'color-core-blue-1000': #0a3960, + 'color-core-blue-1100': #002138, + 'color-core-purple-0': #f2f2f9, + 'color-core-purple-100': #eaeaf9, + 'color-core-purple-200': #d8d7f9, + 'color-core-purple-300': #c1c1f7, + 'color-core-purple-400': #a193f2, + 'color-core-purple-500': #9180f4, + 'color-core-purple-600': #816fea, + 'color-core-purple-700': #6f5ed3, + 'color-core-purple-800': #5e4eba, + 'color-core-purple-900': #483a9c, + 'color-core-purple-1000': #2d246b, + 'color-core-purple-1100': #1d1d38, + 'color-core-magenta-0': #fef0ff, + 'color-core-magenta-100': #f9e3fc, + 'color-core-magenta-200': #f4c4f7, + 'color-core-magenta-300': #edadf2, + 'color-core-magenta-400': #f282f5, + 'color-core-magenta-500': #db61db, + 'color-core-magenta-600': #c44eb9, + 'color-core-magenta-700': #ac44a8, + 'color-core-magenta-800': #8f3896, + 'color-core-magenta-900': #6c2277, + 'color-core-magenta-1000': #451551, + 'color-core-magenta-1100': #29192d, + 'color-core-pink-0': #ffe9f3, + 'color-core-pink-100': #fcdbeb, + 'color-core-pink-200': #ffb5d5, + 'color-core-pink-300': #ff95c1, + 'color-core-pink-400': #ff76ae, + 'color-core-pink-500': #ef588b, + 'color-core-pink-600': #e0447c, + 'color-core-pink-700': #ce3665, + 'color-core-pink-800': #b22f5b, + 'color-core-pink-900': #931847, + 'color-core-pink-1000': #561231, + 'color-core-pink-1100': #2b1721, + 'color-core-red-0': #ffeae9, + 'color-core-red-100': #ffd5d2, + 'color-core-red-200': #ffb8b1, + 'color-core-red-300': #ff9c8f, + 'color-core-red-400': #ff7f6e, + 'color-core-red-500': #f76054, + 'color-core-red-600': #ed4c42, + 'color-core-red-700': #db3e3e, + 'color-core-red-800': #c63434, + 'color-core-red-900': #992222, + 'color-core-red-1000': #6d1313, + 'color-core-red-1100': #2b1111, + 'color-core-orange-0': #ffede3, + 'color-core-orange-100': #fcdccc, + 'color-core-orange-200': #ffc6a4, + 'color-core-orange-300': #ffb180, + 'color-core-orange-400': #ff9c5d, + 'color-core-orange-500': #fc8943, + 'color-core-orange-600': #f57d33, + 'color-core-orange-700': #ed7024, + 'color-core-orange-800': #ce5511, + 'color-core-orange-900': #962c0b, + 'color-core-orange-1000': #601700, + 'color-core-orange-1100': #2d130e, + 'color-core-neutral-0': #ffffff, + 'color-core-neutral-100': #f3f4f4, + 'color-core-neutral-200': #dee1e1, + 'color-core-neutral-300': #c8cccc, + 'color-core-neutral-400': #b0b6b7, + 'color-core-neutral-500': #929a9b, + 'color-core-neutral-600': #6e797a, + 'color-core-neutral-700': #515e5f, + 'color-core-neutral-800': #364141, + 'color-core-neutral-900': #273333, + 'color-core-neutral-1000': #162020, + 'color-core-neutral-1100': #040404, + 'color-core-yellow-0': #fff8e2, + 'color-core-yellow-100': #fdefcd, + 'color-core-yellow-200': #ffe99a, + 'color-core-yellow-300': #ffe16e, + 'color-core-yellow-400': #ffd943, + 'color-core-yellow-500': #ffcd1c, + 'color-core-yellow-600': #ffbc00, + 'color-core-yellow-700': #dd9903, + 'color-core-yellow-800': #ba7506, + 'color-core-yellow-900': #944c0c, + 'color-core-yellow-1000': #542a00, + 'color-core-yellow-1100': #2d1a05, + 'color-font-primary': #040404, + 'color-font-secondary': #273333, + 'color-font-tertiary': #364141, + 'color-font-interactive': #0b8599, + 'color-font-interactive-hover': #0b8599, + 'color-font-interactive-active': #6f5ed3, + 'color-font-interactive-disabled': #364141, + 'color-font-danger': #6d1313, + 'color-font-warning': #601700, + 'color-font-success': #08422f, + 'size-border-radius-large': 30rem, + 'size-font-small': 0.75rem, + 'size-font-medium': 1rem, + 'size-font-large': 1.5rem, + 'size-font-xl': 2.25rem, + 'size-padding-small': 0.5rem, + 'size-padding-medium': 1rem, + 'size-padding-large': 1rem, + 'size-padding-xl': 1rem +);`; +/* end snapshot integration scss scss/map-flat should match snapshot */ + +snapshots["integration scss scss/map-deep should match snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ + +$color-background-primary: #ffffff !default; +$color-background-secondary: #f3f4f4 !default; +$color-background-tertiary: #dee1e1 !default; +$color-background-danger: #ffeae9 !default; +$color-background-warning: #ffede3 !default; +$color-background-success: #ebf9eb !default; +$color-background-info: #e9f8ff !default; +$color-background-disabled: #dee1e1 !default; +$color-border-primary: #c8cccc !default; +$color-brand-primary: #0b8599 !default; +$color-brand-secondary: #6f5ed3 !default; +$color-core-green-0: #ebf9eb !default; +$color-core-green-100: #d7f4d7 !default; +$color-core-green-200: #c2f2bd !default; +$color-core-green-300: #98e58e !default; +$color-core-green-400: #75dd66 !default; +$color-core-green-500: #59cb59 !default; +$color-core-green-600: #2bb656 !default; +$color-core-green-700: #0ca750 !default; +$color-core-green-800: #008b46 !default; +$color-core-green-900: #006b40 !default; +$color-core-green-1000: #08422f !default; +$color-core-green-1100: #002b20 !default; +$color-core-teal-0: #e5f9f5 !default; +$color-core-teal-100: #cdf7ef !default; +$color-core-teal-200: #b3f2e6 !default; +$color-core-teal-300: #7dead5 !default; +$color-core-teal-400: #24e0c5 !default; +$color-core-teal-500: #08c4b2 !default; +$color-core-teal-600: #00a99c !default; +$color-core-teal-700: #0b968f !default; +$color-core-teal-800: #067c7c !default; +$color-core-teal-900: #026661 !default; +$color-core-teal-1000: #083f3f !default; +$color-core-teal-1100: #002528 !default; +$color-core-aqua-0: #d9fcfb !default; +$color-core-aqua-100: #c5f9f9 !default; +$color-core-aqua-200: #a5f2f2 !default; +$color-core-aqua-300: #76e5e2 !default; +$color-core-aqua-400: #33d6e2 !default; +$color-core-aqua-500: #17b8ce !default; +$color-core-aqua-600: #0797ae !default; +$color-core-aqua-700: #0b8599 !default; +$color-core-aqua-800: #0f6e84 !default; +$color-core-aqua-900: #035e73 !default; +$color-core-aqua-1000: #083d4f !default; +$color-core-aqua-1100: #002838 !default; +$color-core-blue-0: #e9f8ff !default; +$color-core-blue-100: #dcf2ff !default; +$color-core-blue-200: #c7e4f9 !default; +$color-core-blue-300: #a1d2f8 !default; +$color-core-blue-400: #56adf5 !default; +$color-core-blue-500: #3896e3 !default; +$color-core-blue-600: #2b87d3 !default; +$color-core-blue-700: #2079c3 !default; +$color-core-blue-800: #116daa !default; +$color-core-blue-900: #0c5689 !default; +$color-core-blue-1000: #0a3960 !default; +$color-core-blue-1100: #002138 !default; +$color-core-purple-0: #f2f2f9 !default; +$color-core-purple-100: #eaeaf9 !default; +$color-core-purple-200: #d8d7f9 !default; +$color-core-purple-300: #c1c1f7 !default; +$color-core-purple-400: #a193f2 !default; +$color-core-purple-500: #9180f4 !default; +$color-core-purple-600: #816fea !default; +$color-core-purple-700: #6f5ed3 !default; +$color-core-purple-800: #5e4eba !default; +$color-core-purple-900: #483a9c !default; +$color-core-purple-1000: #2d246b !default; +$color-core-purple-1100: #1d1d38 !default; +$color-core-magenta-0: #fef0ff !default; +$color-core-magenta-100: #f9e3fc !default; +$color-core-magenta-200: #f4c4f7 !default; +$color-core-magenta-300: #edadf2 !default; +$color-core-magenta-400: #f282f5 !default; +$color-core-magenta-500: #db61db !default; +$color-core-magenta-600: #c44eb9 !default; +$color-core-magenta-700: #ac44a8 !default; +$color-core-magenta-800: #8f3896 !default; +$color-core-magenta-900: #6c2277 !default; +$color-core-magenta-1000: #451551 !default; +$color-core-magenta-1100: #29192d !default; +$color-core-pink-0: #ffe9f3 !default; +$color-core-pink-100: #fcdbeb !default; +$color-core-pink-200: #ffb5d5 !default; +$color-core-pink-300: #ff95c1 !default; +$color-core-pink-400: #ff76ae !default; +$color-core-pink-500: #ef588b !default; +$color-core-pink-600: #e0447c !default; +$color-core-pink-700: #ce3665 !default; +$color-core-pink-800: #b22f5b !default; +$color-core-pink-900: #931847 !default; +$color-core-pink-1000: #561231 !default; +$color-core-pink-1100: #2b1721 !default; +$color-core-red-0: #ffeae9 !default; +$color-core-red-100: #ffd5d2 !default; +$color-core-red-200: #ffb8b1 !default; +$color-core-red-300: #ff9c8f !default; +$color-core-red-400: #ff7f6e !default; +$color-core-red-500: #f76054 !default; +$color-core-red-600: #ed4c42 !default; +$color-core-red-700: #db3e3e !default; +$color-core-red-800: #c63434 !default; +$color-core-red-900: #992222 !default; +$color-core-red-1000: #6d1313 !default; +$color-core-red-1100: #2b1111 !default; +$color-core-orange-0: #ffede3 !default; +$color-core-orange-100: #fcdccc !default; +$color-core-orange-200: #ffc6a4 !default; +$color-core-orange-300: #ffb180 !default; +$color-core-orange-400: #ff9c5d !default; +$color-core-orange-500: #fc8943 !default; +$color-core-orange-600: #f57d33 !default; +$color-core-orange-700: #ed7024 !default; +$color-core-orange-800: #ce5511 !default; +$color-core-orange-900: #962c0b !default; +$color-core-orange-1000: #601700 !default; +$color-core-orange-1100: #2d130e !default; +$color-core-neutral-0: #ffffff !default; +$color-core-neutral-100: #f3f4f4 !default; +$color-core-neutral-200: #dee1e1 !default; +$color-core-neutral-300: #c8cccc !default; +$color-core-neutral-400: #b0b6b7 !default; +$color-core-neutral-500: #929a9b !default; +$color-core-neutral-600: #6e797a !default; +$color-core-neutral-700: #515e5f !default; +$color-core-neutral-800: #364141 !default; +$color-core-neutral-900: #273333 !default; +$color-core-neutral-1000: #162020 !default; +$color-core-neutral-1100: #040404 !default; +$color-core-yellow-0: #fff8e2 !default; +$color-core-yellow-100: #fdefcd !default; +$color-core-yellow-200: #ffe99a !default; +$color-core-yellow-300: #ffe16e !default; +$color-core-yellow-400: #ffd943 !default; +$color-core-yellow-500: #ffcd1c !default; +$color-core-yellow-600: #ffbc00 !default; +$color-core-yellow-700: #dd9903 !default; +$color-core-yellow-800: #ba7506 !default; +$color-core-yellow-900: #944c0c !default; +$color-core-yellow-1000: #542a00 !default; +$color-core-yellow-1100: #2d1a05 !default; +$color-font-primary: #040404 !default; +$color-font-secondary: #273333 !default; +$color-font-tertiary: #364141 !default; +$color-font-interactive: #0b8599 !default; +$color-font-interactive-hover: #0b8599 !default; +$color-font-interactive-active: #6f5ed3 !default; +$color-font-interactive-disabled: #364141 !default; +$color-font-danger: #6d1313 !default; +$color-font-warning: #601700 !default; +$color-font-success: #08422f !default; +$size-border-radius-large: 30rem !default; +$size-font-small: 0.75rem !default; +$size-font-medium: 1rem !default; +$size-font-large: 1.5rem !default; +$size-font-xl: 2.25rem !default; +$size-padding-small: 0.5rem !default; +$size-padding-medium: 1rem !default; +$size-padding-large: 1rem !default; +$size-padding-xl: 1rem !default; $design-system-tokens: ( 'color': ( @@ -1138,731 +1054,808 @@ $design-system-tokens: ( 'hover': $color-font-interactive-hover, 'active': $color-font-interactive-active, 'disabled': $color-font-interactive-disabled - ), - 'danger': $color-font-danger, - 'warning': $color-font-warning, - 'success': $color-font-success - ) - ), - 'size': ( - 'border': ( - 'radius': ( - 'large': $size-border-radius-large - ) - ), - 'font': ( - 'small': $size-font-small, - 'medium': $size-font-medium, - 'large': $size-font-large, - 'xl': $size-font-xl - ), - 'padding': ( - 'small': $size-padding-small, - 'medium': $size-padding-medium, - 'large': $size-padding-large, - 'xl': $size-padding-xl - ) - ) -); -" -`; - -exports[`integration scss scss/map-flat should match snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$design-system-tokens: ( - 'color-background-primary': #ffffff, - 'color-background-secondary': #f3f4f4, - 'color-background-tertiary': #dee1e1, - 'color-background-danger': #ffeae9, - 'color-background-warning': #ffede3, - 'color-background-success': #ebf9eb, - 'color-background-info': #e9f8ff, - 'color-background-disabled': #dee1e1, - 'color-border-primary': #c8cccc, - 'color-brand-primary': #0b8599, - 'color-brand-secondary': #6f5ed3, - 'color-core-green-0': #ebf9eb, - 'color-core-green-100': #d7f4d7, - 'color-core-green-200': #c2f2bd, - 'color-core-green-300': #98e58e, - 'color-core-green-400': #75dd66, - 'color-core-green-500': #59cb59, - 'color-core-green-600': #2bb656, - 'color-core-green-700': #0ca750, - 'color-core-green-800': #008b46, - 'color-core-green-900': #006b40, - 'color-core-green-1000': #08422f, - 'color-core-green-1100': #002b20, - 'color-core-teal-0': #e5f9f5, - 'color-core-teal-100': #cdf7ef, - 'color-core-teal-200': #b3f2e6, - 'color-core-teal-300': #7dead5, - 'color-core-teal-400': #24e0c5, - 'color-core-teal-500': #08c4b2, - 'color-core-teal-600': #00a99c, - 'color-core-teal-700': #0b968f, - 'color-core-teal-800': #067c7c, - 'color-core-teal-900': #026661, - 'color-core-teal-1000': #083f3f, - 'color-core-teal-1100': #002528, - 'color-core-aqua-0': #d9fcfb, - 'color-core-aqua-100': #c5f9f9, - 'color-core-aqua-200': #a5f2f2, - 'color-core-aqua-300': #76e5e2, - 'color-core-aqua-400': #33d6e2, - 'color-core-aqua-500': #17b8ce, - 'color-core-aqua-600': #0797ae, - 'color-core-aqua-700': #0b8599, - 'color-core-aqua-800': #0f6e84, - 'color-core-aqua-900': #035e73, - 'color-core-aqua-1000': #083d4f, - 'color-core-aqua-1100': #002838, - 'color-core-blue-0': #e9f8ff, - 'color-core-blue-100': #dcf2ff, - 'color-core-blue-200': #c7e4f9, - 'color-core-blue-300': #a1d2f8, - 'color-core-blue-400': #56adf5, - 'color-core-blue-500': #3896e3, - 'color-core-blue-600': #2b87d3, - 'color-core-blue-700': #2079c3, - 'color-core-blue-800': #116daa, - 'color-core-blue-900': #0c5689, - 'color-core-blue-1000': #0a3960, - 'color-core-blue-1100': #002138, - 'color-core-purple-0': #f2f2f9, - 'color-core-purple-100': #eaeaf9, - 'color-core-purple-200': #d8d7f9, - 'color-core-purple-300': #c1c1f7, - 'color-core-purple-400': #a193f2, - 'color-core-purple-500': #9180f4, - 'color-core-purple-600': #816fea, - 'color-core-purple-700': #6f5ed3, - 'color-core-purple-800': #5e4eba, - 'color-core-purple-900': #483a9c, - 'color-core-purple-1000': #2d246b, - 'color-core-purple-1100': #1d1d38, - 'color-core-magenta-0': #fef0ff, - 'color-core-magenta-100': #f9e3fc, - 'color-core-magenta-200': #f4c4f7, - 'color-core-magenta-300': #edadf2, - 'color-core-magenta-400': #f282f5, - 'color-core-magenta-500': #db61db, - 'color-core-magenta-600': #c44eb9, - 'color-core-magenta-700': #ac44a8, - 'color-core-magenta-800': #8f3896, - 'color-core-magenta-900': #6c2277, - 'color-core-magenta-1000': #451551, - 'color-core-magenta-1100': #29192d, - 'color-core-pink-0': #ffe9f3, - 'color-core-pink-100': #fcdbeb, - 'color-core-pink-200': #ffb5d5, - 'color-core-pink-300': #ff95c1, - 'color-core-pink-400': #ff76ae, - 'color-core-pink-500': #ef588b, - 'color-core-pink-600': #e0447c, - 'color-core-pink-700': #ce3665, - 'color-core-pink-800': #b22f5b, - 'color-core-pink-900': #931847, - 'color-core-pink-1000': #561231, - 'color-core-pink-1100': #2b1721, - 'color-core-red-0': #ffeae9, - 'color-core-red-100': #ffd5d2, - 'color-core-red-200': #ffb8b1, - 'color-core-red-300': #ff9c8f, - 'color-core-red-400': #ff7f6e, - 'color-core-red-500': #f76054, - 'color-core-red-600': #ed4c42, - 'color-core-red-700': #db3e3e, - 'color-core-red-800': #c63434, - 'color-core-red-900': #992222, - 'color-core-red-1000': #6d1313, - 'color-core-red-1100': #2b1111, - 'color-core-orange-0': #ffede3, - 'color-core-orange-100': #fcdccc, - 'color-core-orange-200': #ffc6a4, - 'color-core-orange-300': #ffb180, - 'color-core-orange-400': #ff9c5d, - 'color-core-orange-500': #fc8943, - 'color-core-orange-600': #f57d33, - 'color-core-orange-700': #ed7024, - 'color-core-orange-800': #ce5511, - 'color-core-orange-900': #962c0b, - 'color-core-orange-1000': #601700, - 'color-core-orange-1100': #2d130e, - 'color-core-neutral-0': #ffffff, - 'color-core-neutral-100': #f3f4f4, - 'color-core-neutral-200': #dee1e1, - 'color-core-neutral-300': #c8cccc, - 'color-core-neutral-400': #b0b6b7, - 'color-core-neutral-500': #929a9b, - 'color-core-neutral-600': #6e797a, - 'color-core-neutral-700': #515e5f, - 'color-core-neutral-800': #364141, - 'color-core-neutral-900': #273333, - 'color-core-neutral-1000': #162020, - 'color-core-neutral-1100': #040404, - 'color-core-yellow-0': #fff8e2, - 'color-core-yellow-100': #fdefcd, - 'color-core-yellow-200': #ffe99a, - 'color-core-yellow-300': #ffe16e, - 'color-core-yellow-400': #ffd943, - 'color-core-yellow-500': #ffcd1c, - 'color-core-yellow-600': #ffbc00, - 'color-core-yellow-700': #dd9903, - 'color-core-yellow-800': #ba7506, - 'color-core-yellow-900': #944c0c, - 'color-core-yellow-1000': #542a00, - 'color-core-yellow-1100': #2d1a05, - 'color-font-primary': #040404, - 'color-font-secondary': #273333, - 'color-font-tertiary': #364141, - 'color-font-interactive': #0b8599, - 'color-font-interactive-hover': #0b8599, - 'color-font-interactive-active': #6f5ed3, - 'color-font-interactive-disabled': #364141, - 'color-font-danger': #6d1313, - 'color-font-warning': #601700, - 'color-font-success': #08422f, - 'size-border-radius-large': 30rem, - 'size-font-small': 0.75rem, - 'size-font-medium': 1rem, - 'size-font-large': 1.5rem, - 'size-font-xl': 2.25rem, - 'size-padding-small': 0.5rem, - 'size-padding-medium': 1rem, - 'size-padding-large': 1rem, - 'size-padding-xl': 1rem + ), + 'danger': $color-font-danger, + 'warning': $color-font-warning, + 'success': $color-font-success + ) + ), + 'size': ( + 'border': ( + 'radius': ( + 'large': $size-border-radius-large + ) + ), + 'font': ( + 'small': $size-font-small, + 'medium': $size-font-medium, + 'large': $size-font-large, + 'xl': $size-font-xl + ), + 'padding': ( + 'small': $size-padding-small, + 'medium': $size-padding-medium, + 'large': $size-padding-large, + 'xl': $size-padding-xl + ) + ) ); -" `; +/* end snapshot integration scss scss/map-deep should match snapshot */ -exports[`integration scss scss/variables should match snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +snapshots["integration scss scss/map-deep with outputReferences should match snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ -$color-background-primary: #ffffff !default; -$color-background-secondary: #f3f4f4; -$color-background-tertiary: #dee1e1; -$color-background-danger: #ffeae9; -$color-background-warning: #ffede3; -$color-background-success: #ebf9eb; -$color-background-info: #e9f8ff; -$color-background-disabled: #dee1e1; -$color-border-primary: #c8cccc; -$color-brand-primary: #0b8599; -$color-brand-secondary: #6f5ed3; -$color-core-green-0: #ebf9eb; -$color-core-green-100: #d7f4d7; -$color-core-green-200: #c2f2bd; -$color-core-green-300: #98e58e; -$color-core-green-400: #75dd66; -$color-core-green-500: #59cb59; -$color-core-green-600: #2bb656; -$color-core-green-700: #0ca750; -$color-core-green-800: #008b46; -$color-core-green-900: #006b40; -$color-core-green-1000: #08422f; -$color-core-green-1100: #002b20; -$color-core-teal-0: #e5f9f5; -$color-core-teal-100: #cdf7ef; -$color-core-teal-200: #b3f2e6; -$color-core-teal-300: #7dead5; -$color-core-teal-400: #24e0c5; -$color-core-teal-500: #08c4b2; -$color-core-teal-600: #00a99c; -$color-core-teal-700: #0b968f; -$color-core-teal-800: #067c7c; -$color-core-teal-900: #026661; -$color-core-teal-1000: #083f3f; -$color-core-teal-1100: #002528; -$color-core-aqua-0: #d9fcfb; -$color-core-aqua-100: #c5f9f9; -$color-core-aqua-200: #a5f2f2; -$color-core-aqua-300: #76e5e2; -$color-core-aqua-400: #33d6e2; -$color-core-aqua-500: #17b8ce; -$color-core-aqua-600: #0797ae; -$color-core-aqua-700: #0b8599; -$color-core-aqua-800: #0f6e84; -$color-core-aqua-900: #035e73; -$color-core-aqua-1000: #083d4f; -$color-core-aqua-1100: #002838; -$color-core-blue-0: #e9f8ff; -$color-core-blue-100: #dcf2ff; -$color-core-blue-200: #c7e4f9; -$color-core-blue-300: #a1d2f8; -$color-core-blue-400: #56adf5; -$color-core-blue-500: #3896e3; -$color-core-blue-600: #2b87d3; -$color-core-blue-700: #2079c3; -$color-core-blue-800: #116daa; -$color-core-blue-900: #0c5689; -$color-core-blue-1000: #0a3960; -$color-core-blue-1100: #002138; -$color-core-purple-0: #f2f2f9; -$color-core-purple-100: #eaeaf9; -$color-core-purple-200: #d8d7f9; -$color-core-purple-300: #c1c1f7; -$color-core-purple-400: #a193f2; -$color-core-purple-500: #9180f4; -$color-core-purple-600: #816fea; -$color-core-purple-700: #6f5ed3; -$color-core-purple-800: #5e4eba; -$color-core-purple-900: #483a9c; -$color-core-purple-1000: #2d246b; -$color-core-purple-1100: #1d1d38; -$color-core-magenta-0: #fef0ff; -$color-core-magenta-100: #f9e3fc; -$color-core-magenta-200: #f4c4f7; -$color-core-magenta-300: #edadf2; -$color-core-magenta-400: #f282f5; -$color-core-magenta-500: #db61db; -$color-core-magenta-600: #c44eb9; -$color-core-magenta-700: #ac44a8; -$color-core-magenta-800: #8f3896; -$color-core-magenta-900: #6c2277; -$color-core-magenta-1000: #451551; -$color-core-magenta-1100: #29192d; -$color-core-pink-0: #ffe9f3; -$color-core-pink-100: #fcdbeb; -$color-core-pink-200: #ffb5d5; -$color-core-pink-300: #ff95c1; -$color-core-pink-400: #ff76ae; -$color-core-pink-500: #ef588b; -$color-core-pink-600: #e0447c; -$color-core-pink-700: #ce3665; -$color-core-pink-800: #b22f5b; -$color-core-pink-900: #931847; -$color-core-pink-1000: #561231; -$color-core-pink-1100: #2b1721; -$color-core-red-0: #ffeae9; -$color-core-red-100: #ffd5d2; -$color-core-red-200: #ffb8b1; -$color-core-red-300: #ff9c8f; -$color-core-red-400: #ff7f6e; -$color-core-red-500: #f76054; -$color-core-red-600: #ed4c42; -$color-core-red-700: #db3e3e; -$color-core-red-800: #c63434; -$color-core-red-900: #992222; -$color-core-red-1000: #6d1313; -$color-core-red-1100: #2b1111; -$color-core-orange-0: #ffede3; -$color-core-orange-100: #fcdccc; -$color-core-orange-200: #ffc6a4; -$color-core-orange-300: #ffb180; -$color-core-orange-400: #ff9c5d; -$color-core-orange-500: #fc8943; -$color-core-orange-600: #f57d33; -$color-core-orange-700: #ed7024; -$color-core-orange-800: #ce5511; -$color-core-orange-900: #962c0b; -$color-core-orange-1000: #601700; -$color-core-orange-1100: #2d130e; -$color-core-neutral-0: #ffffff; -$color-core-neutral-100: #f3f4f4; -$color-core-neutral-200: #dee1e1; -$color-core-neutral-300: #c8cccc; -$color-core-neutral-400: #b0b6b7; -$color-core-neutral-500: #929a9b; -$color-core-neutral-600: #6e797a; -$color-core-neutral-700: #515e5f; -$color-core-neutral-800: #364141; -$color-core-neutral-900: #273333; -$color-core-neutral-1000: #162020; -$color-core-neutral-1100: #040404; -$color-core-yellow-0: #fff8e2; -$color-core-yellow-100: #fdefcd; -$color-core-yellow-200: #ffe99a; -$color-core-yellow-300: #ffe16e; -$color-core-yellow-400: #ffd943; -$color-core-yellow-500: #ffcd1c; -$color-core-yellow-600: #ffbc00; -$color-core-yellow-700: #dd9903; -$color-core-yellow-800: #ba7506; -$color-core-yellow-900: #944c0c; -$color-core-yellow-1000: #542a00; -$color-core-yellow-1100: #2d1a05; -$color-font-primary: #040404; -$color-font-secondary: #273333; -$color-font-tertiary: #364141; -$color-font-interactive: #0b8599; -$color-font-interactive-hover: #0b8599; -$color-font-interactive-active: #6f5ed3; -$color-font-interactive-disabled: #364141; -$color-font-danger: #6d1313; -$color-font-warning: #601700; -$color-font-success: #08422f; -$size-border-radius-large: 30rem; -$size-font-small: 0.75rem; -$size-font-medium: 1rem; -$size-font-large: 1.5rem; -$size-font-xl: 2.25rem; -$size-padding-small: 0.5rem; -$size-padding-medium: 1rem; -$size-padding-large: 1rem; -$size-padding-xl: 1rem; -" -`; +$size-padding-xl: 1rem !default; +$size-padding-large: 1rem !default; +$size-padding-medium: 1rem !default; +$size-padding-small: 0.5rem !default; +$size-font-xl: 2.25rem !default; +$size-font-large: 1.5rem !default; +$size-font-medium: 1rem !default; +$size-font-small: 0.75rem !default; +$size-border-radius-large: 30rem !default; +$color-core-yellow-1100: #2d1a05 !default; +$color-core-yellow-1000: #542a00 !default; +$color-core-yellow-900: #944c0c !default; +$color-core-yellow-800: #ba7506 !default; +$color-core-yellow-700: #dd9903 !default; +$color-core-yellow-600: #ffbc00 !default; +$color-core-yellow-500: #ffcd1c !default; +$color-core-yellow-400: #ffd943 !default; +$color-core-yellow-300: #ffe16e !default; +$color-core-yellow-200: #ffe99a !default; +$color-core-yellow-100: #fdefcd !default; +$color-core-yellow-0: #fff8e2 !default; +$color-core-neutral-1100: #040404 !default; +$color-core-neutral-1000: #162020 !default; +$color-core-neutral-900: #273333 !default; +$color-core-neutral-800: #364141 !default; +$color-core-neutral-700: #515e5f !default; +$color-core-neutral-600: #6e797a !default; +$color-core-neutral-500: #929a9b !default; +$color-core-neutral-400: #b0b6b7 !default; +$color-core-neutral-300: #c8cccc !default; +$color-core-neutral-200: #dee1e1 !default; +$color-core-neutral-100: #f3f4f4 !default; +$color-core-neutral-0: #ffffff !default; +$color-core-orange-1100: #2d130e !default; +$color-core-orange-1000: #601700 !default; +$color-core-orange-900: #962c0b !default; +$color-core-orange-800: #ce5511 !default; +$color-core-orange-700: #ed7024 !default; +$color-core-orange-600: #f57d33 !default; +$color-core-orange-500: #fc8943 !default; +$color-core-orange-400: #ff9c5d !default; +$color-core-orange-300: #ffb180 !default; +$color-core-orange-200: #ffc6a4 !default; +$color-core-orange-100: #fcdccc !default; +$color-core-orange-0: #ffede3 !default; +$color-core-red-1100: #2b1111 !default; +$color-core-red-1000: #6d1313 !default; +$color-core-red-900: #992222 !default; +$color-core-red-800: #c63434 !default; +$color-core-red-700: #db3e3e !default; +$color-core-red-600: #ed4c42 !default; +$color-core-red-500: #f76054 !default; +$color-core-red-400: #ff7f6e !default; +$color-core-red-300: #ff9c8f !default; +$color-core-red-200: #ffb8b1 !default; +$color-core-red-100: #ffd5d2 !default; +$color-core-red-0: #ffeae9 !default; +$color-core-pink-1100: #2b1721 !default; +$color-core-pink-1000: #561231 !default; +$color-core-pink-900: #931847 !default; +$color-core-pink-800: #b22f5b !default; +$color-core-pink-700: #ce3665 !default; +$color-core-pink-600: #e0447c !default; +$color-core-pink-500: #ef588b !default; +$color-core-pink-400: #ff76ae !default; +$color-core-pink-300: #ff95c1 !default; +$color-core-pink-200: #ffb5d5 !default; +$color-core-pink-100: #fcdbeb !default; +$color-core-pink-0: #ffe9f3 !default; +$color-core-magenta-1100: #29192d !default; +$color-core-magenta-1000: #451551 !default; +$color-core-magenta-900: #6c2277 !default; +$color-core-magenta-800: #8f3896 !default; +$color-core-magenta-700: #ac44a8 !default; +$color-core-magenta-600: #c44eb9 !default; +$color-core-magenta-500: #db61db !default; +$color-core-magenta-400: #f282f5 !default; +$color-core-magenta-300: #edadf2 !default; +$color-core-magenta-200: #f4c4f7 !default; +$color-core-magenta-100: #f9e3fc !default; +$color-core-magenta-0: #fef0ff !default; +$color-core-purple-1100: #1d1d38 !default; +$color-core-purple-1000: #2d246b !default; +$color-core-purple-900: #483a9c !default; +$color-core-purple-800: #5e4eba !default; +$color-core-purple-700: #6f5ed3 !default; +$color-core-purple-600: #816fea !default; +$color-core-purple-500: #9180f4 !default; +$color-core-purple-400: #a193f2 !default; +$color-core-purple-300: #c1c1f7 !default; +$color-core-purple-200: #d8d7f9 !default; +$color-core-purple-100: #eaeaf9 !default; +$color-core-purple-0: #f2f2f9 !default; +$color-core-blue-1100: #002138 !default; +$color-core-blue-1000: #0a3960 !default; +$color-core-blue-900: #0c5689 !default; +$color-core-blue-800: #116daa !default; +$color-core-blue-700: #2079c3 !default; +$color-core-blue-600: #2b87d3 !default; +$color-core-blue-500: #3896e3 !default; +$color-core-blue-400: #56adf5 !default; +$color-core-blue-300: #a1d2f8 !default; +$color-core-blue-200: #c7e4f9 !default; +$color-core-blue-100: #dcf2ff !default; +$color-core-blue-0: #e9f8ff !default; +$color-core-aqua-1100: #002838 !default; +$color-core-aqua-1000: #083d4f !default; +$color-core-aqua-900: #035e73 !default; +$color-core-aqua-800: #0f6e84 !default; +$color-core-aqua-700: #0b8599 !default; +$color-core-aqua-600: #0797ae !default; +$color-core-aqua-500: #17b8ce !default; +$color-core-aqua-400: #33d6e2 !default; +$color-core-aqua-300: #76e5e2 !default; +$color-core-aqua-200: #a5f2f2 !default; +$color-core-aqua-100: #c5f9f9 !default; +$color-core-aqua-0: #d9fcfb !default; +$color-core-teal-1100: #002528 !default; +$color-core-teal-1000: #083f3f !default; +$color-core-teal-900: #026661 !default; +$color-core-teal-800: #067c7c !default; +$color-core-teal-700: #0b968f !default; +$color-core-teal-600: #00a99c !default; +$color-core-teal-500: #08c4b2 !default; +$color-core-teal-400: #24e0c5 !default; +$color-core-teal-300: #7dead5 !default; +$color-core-teal-200: #b3f2e6 !default; +$color-core-teal-100: #cdf7ef !default; +$color-core-teal-0: #e5f9f5 !default; +$color-core-green-1100: #002b20 !default; +$color-core-green-1000: #08422f !default; +$color-core-green-900: #006b40 !default; +$color-core-green-800: #008b46 !default; +$color-core-green-700: #0ca750 !default; +$color-core-green-600: #2bb656 !default; +$color-core-green-500: #59cb59 !default; +$color-core-green-400: #75dd66 !default; +$color-core-green-300: #98e58e !default; +$color-core-green-200: #c2f2bd !default; +$color-core-green-100: #d7f4d7 !default; +$color-core-green-0: #ebf9eb !default; +$color-font-success: $color-core-green-1000 !default; +$color-font-warning: $color-core-orange-1000 !default; +$color-font-danger: $color-core-red-1000 !default; +$color-font-tertiary: $color-core-neutral-800 !default; +$color-font-secondary: $color-core-neutral-900 !default; +$color-font-primary: $color-core-neutral-1100 !default; +$color-brand-secondary: $color-core-purple-700 !default; +$color-brand-primary: $color-core-aqua-700 !default; +$color-border-primary: $color-core-neutral-300 !default; +$color-background-info: $color-core-blue-0 !default; +$color-background-success: $color-core-green-0 !default; +$color-background-warning: $color-core-orange-0 !default; +$color-background-danger: $color-core-red-0 !default; +$color-background-tertiary: $color-core-neutral-200 !default; +$color-background-secondary: $color-core-neutral-100 !default; +$color-background-primary: $color-core-neutral-0 !default; +$color-font-interactive-disabled: $color-font-tertiary !default; +$color-font-interactive-active: $color-brand-secondary !default; +$color-font-interactive-hover: $color-brand-primary !default; +$color-font-interactive: $color-brand-primary !default; +$color-background-disabled: $color-background-tertiary !default; -exports[`integration scss scss/variables with filter and output references should match snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +$design-system-tokens: ( + 'color': ( + 'background': ( + 'primary': $color-background-primary, + 'secondary': $color-background-secondary, + 'tertiary': $color-background-tertiary, + 'danger': $color-background-danger, + 'warning': $color-background-warning, + 'success': $color-background-success, + 'info': $color-background-info, + 'disabled': $color-background-disabled + ), + 'border': ( + 'primary': $color-border-primary, + 'secondary': ( -$color-background-info: $color-core-blue-0; -$color-background-success: $color-core-green-0; -$color-background-warning: $color-core-orange-0; -$color-background-danger: $color-core-red-0; -$color-background-tertiary: $color-core-neutral-200; -$color-background-secondary: $color-core-neutral-100; -$color-background-primary: $color-core-neutral-0 !default; -$color-background-disabled: $color-background-tertiary; -" + ), + 'tertiary': ( + + ) + ), + 'brand': ( + 'primary': $color-brand-primary, + 'secondary': $color-brand-secondary + ), + 'core': ( + 'green': ( + '0': $color-core-green-0, + '100': $color-core-green-100, + '200': $color-core-green-200, + '300': $color-core-green-300, + '400': $color-core-green-400, + '500': $color-core-green-500, + '600': $color-core-green-600, + '700': $color-core-green-700, + '800': $color-core-green-800, + '900': $color-core-green-900, + '1000': $color-core-green-1000, + '1100': $color-core-green-1100 + ), + 'teal': ( + '0': $color-core-teal-0, + '100': $color-core-teal-100, + '200': $color-core-teal-200, + '300': $color-core-teal-300, + '400': $color-core-teal-400, + '500': $color-core-teal-500, + '600': $color-core-teal-600, + '700': $color-core-teal-700, + '800': $color-core-teal-800, + '900': $color-core-teal-900, + '1000': $color-core-teal-1000, + '1100': $color-core-teal-1100 + ), + 'aqua': ( + '0': $color-core-aqua-0, + '100': $color-core-aqua-100, + '200': $color-core-aqua-200, + '300': $color-core-aqua-300, + '400': $color-core-aqua-400, + '500': $color-core-aqua-500, + '600': $color-core-aqua-600, + '700': $color-core-aqua-700, + '800': $color-core-aqua-800, + '900': $color-core-aqua-900, + '1000': $color-core-aqua-1000, + '1100': $color-core-aqua-1100 + ), + 'blue': ( + '0': $color-core-blue-0, + '100': $color-core-blue-100, + '200': $color-core-blue-200, + '300': $color-core-blue-300, + '400': $color-core-blue-400, + '500': $color-core-blue-500, + '600': $color-core-blue-600, + '700': $color-core-blue-700, + '800': $color-core-blue-800, + '900': $color-core-blue-900, + '1000': $color-core-blue-1000, + '1100': $color-core-blue-1100 + ), + 'purple': ( + '0': $color-core-purple-0, + '100': $color-core-purple-100, + '200': $color-core-purple-200, + '300': $color-core-purple-300, + '400': $color-core-purple-400, + '500': $color-core-purple-500, + '600': $color-core-purple-600, + '700': $color-core-purple-700, + '800': $color-core-purple-800, + '900': $color-core-purple-900, + '1000': $color-core-purple-1000, + '1100': $color-core-purple-1100 + ), + 'magenta': ( + '0': $color-core-magenta-0, + '100': $color-core-magenta-100, + '200': $color-core-magenta-200, + '300': $color-core-magenta-300, + '400': $color-core-magenta-400, + '500': $color-core-magenta-500, + '600': $color-core-magenta-600, + '700': $color-core-magenta-700, + '800': $color-core-magenta-800, + '900': $color-core-magenta-900, + '1000': $color-core-magenta-1000, + '1100': $color-core-magenta-1100 + ), + 'pink': ( + '0': $color-core-pink-0, + '100': $color-core-pink-100, + '200': $color-core-pink-200, + '300': $color-core-pink-300, + '400': $color-core-pink-400, + '500': $color-core-pink-500, + '600': $color-core-pink-600, + '700': $color-core-pink-700, + '800': $color-core-pink-800, + '900': $color-core-pink-900, + '1000': $color-core-pink-1000, + '1100': $color-core-pink-1100 + ), + 'red': ( + '0': $color-core-red-0, + '100': $color-core-red-100, + '200': $color-core-red-200, + '300': $color-core-red-300, + '400': $color-core-red-400, + '500': $color-core-red-500, + '600': $color-core-red-600, + '700': $color-core-red-700, + '800': $color-core-red-800, + '900': $color-core-red-900, + '1000': $color-core-red-1000, + '1100': $color-core-red-1100 + ), + 'orange': ( + '0': $color-core-orange-0, + '100': $color-core-orange-100, + '200': $color-core-orange-200, + '300': $color-core-orange-300, + '400': $color-core-orange-400, + '500': $color-core-orange-500, + '600': $color-core-orange-600, + '700': $color-core-orange-700, + '800': $color-core-orange-800, + '900': $color-core-orange-900, + '1000': $color-core-orange-1000, + '1100': $color-core-orange-1100 + ), + 'neutral': ( + '0': $color-core-neutral-0, + '100': $color-core-neutral-100, + '200': $color-core-neutral-200, + '300': $color-core-neutral-300, + '400': $color-core-neutral-400, + '500': $color-core-neutral-500, + '600': $color-core-neutral-600, + '700': $color-core-neutral-700, + '800': $color-core-neutral-800, + '900': $color-core-neutral-900, + '1000': $color-core-neutral-1000, + '1100': $color-core-neutral-1100 + ), + 'yellow': ( + '0': $color-core-yellow-0, + '100': $color-core-yellow-100, + '200': $color-core-yellow-200, + '300': $color-core-yellow-300, + '400': $color-core-yellow-400, + '500': $color-core-yellow-500, + '600': $color-core-yellow-600, + '700': $color-core-yellow-700, + '800': $color-core-yellow-800, + '900': $color-core-yellow-900, + '1000': $color-core-yellow-1000, + '1100': $color-core-yellow-1100 + ) + ), + 'font': ( + 'primary': $color-font-primary, + 'secondary': $color-font-secondary, + 'tertiary': $color-font-tertiary, + 'interactive': ( + '_': $color-font-interactive, + 'hover': $color-font-interactive-hover, + 'active': $color-font-interactive-active, + 'disabled': $color-font-interactive-disabled + ), + 'danger': $color-font-danger, + 'warning': $color-font-warning, + 'success': $color-font-success + ) + ), + 'size': ( + 'border': ( + 'radius': ( + 'large': $size-border-radius-large + ) + ), + 'font': ( + 'small': $size-font-small, + 'medium': $size-font-medium, + 'large': $size-font-large, + 'xl': $size-font-xl + ), + 'padding': ( + 'small': $size-padding-small, + 'medium': $size-padding-medium, + 'large': $size-padding-large, + 'xl': $size-padding-xl + ) + ) +); `; +/* end snapshot integration scss scss/map-deep with outputReferences should match snapshot */ -exports[`integration scss scss/variables with outputReferences should match snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +snapshots["integration scss scss/map-deep without themeable should match snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ -$size-padding-xl: 1rem; -$size-padding-large: 1rem; -$size-padding-medium: 1rem; -$size-padding-small: 0.5rem; -$size-font-xl: 2.25rem; -$size-font-large: 1.5rem; -$size-font-medium: 1rem; -$size-font-small: 0.75rem; -$size-border-radius-large: 30rem; -$color-core-yellow-1100: #2d1a05; -$color-core-yellow-1000: #542a00; -$color-core-yellow-900: #944c0c; -$color-core-yellow-800: #ba7506; -$color-core-yellow-700: #dd9903; -$color-core-yellow-600: #ffbc00; -$color-core-yellow-500: #ffcd1c; -$color-core-yellow-400: #ffd943; -$color-core-yellow-300: #ffe16e; -$color-core-yellow-200: #ffe99a; -$color-core-yellow-100: #fdefcd; -$color-core-yellow-0: #fff8e2; -$color-core-neutral-1100: #040404; -$color-core-neutral-1000: #162020; -$color-core-neutral-900: #273333; -$color-core-neutral-800: #364141; -$color-core-neutral-700: #515e5f; -$color-core-neutral-600: #6e797a; -$color-core-neutral-500: #929a9b; -$color-core-neutral-400: #b0b6b7; -$color-core-neutral-300: #c8cccc; -$color-core-neutral-200: #dee1e1; -$color-core-neutral-100: #f3f4f4; -$color-core-neutral-0: #ffffff; -$color-core-orange-1100: #2d130e; -$color-core-orange-1000: #601700; -$color-core-orange-900: #962c0b; -$color-core-orange-800: #ce5511; -$color-core-orange-700: #ed7024; -$color-core-orange-600: #f57d33; -$color-core-orange-500: #fc8943; -$color-core-orange-400: #ff9c5d; -$color-core-orange-300: #ffb180; -$color-core-orange-200: #ffc6a4; -$color-core-orange-100: #fcdccc; -$color-core-orange-0: #ffede3; -$color-core-red-1100: #2b1111; -$color-core-red-1000: #6d1313; -$color-core-red-900: #992222; -$color-core-red-800: #c63434; -$color-core-red-700: #db3e3e; -$color-core-red-600: #ed4c42; -$color-core-red-500: #f76054; -$color-core-red-400: #ff7f6e; -$color-core-red-300: #ff9c8f; -$color-core-red-200: #ffb8b1; -$color-core-red-100: #ffd5d2; -$color-core-red-0: #ffeae9; -$color-core-pink-1100: #2b1721; -$color-core-pink-1000: #561231; -$color-core-pink-900: #931847; -$color-core-pink-800: #b22f5b; -$color-core-pink-700: #ce3665; -$color-core-pink-600: #e0447c; -$color-core-pink-500: #ef588b; -$color-core-pink-400: #ff76ae; -$color-core-pink-300: #ff95c1; -$color-core-pink-200: #ffb5d5; -$color-core-pink-100: #fcdbeb; -$color-core-pink-0: #ffe9f3; -$color-core-magenta-1100: #29192d; -$color-core-magenta-1000: #451551; -$color-core-magenta-900: #6c2277; -$color-core-magenta-800: #8f3896; -$color-core-magenta-700: #ac44a8; -$color-core-magenta-600: #c44eb9; -$color-core-magenta-500: #db61db; -$color-core-magenta-400: #f282f5; -$color-core-magenta-300: #edadf2; -$color-core-magenta-200: #f4c4f7; -$color-core-magenta-100: #f9e3fc; -$color-core-magenta-0: #fef0ff; -$color-core-purple-1100: #1d1d38; -$color-core-purple-1000: #2d246b; -$color-core-purple-900: #483a9c; -$color-core-purple-800: #5e4eba; -$color-core-purple-700: #6f5ed3; -$color-core-purple-600: #816fea; -$color-core-purple-500: #9180f4; -$color-core-purple-400: #a193f2; -$color-core-purple-300: #c1c1f7; -$color-core-purple-200: #d8d7f9; -$color-core-purple-100: #eaeaf9; -$color-core-purple-0: #f2f2f9; -$color-core-blue-1100: #002138; -$color-core-blue-1000: #0a3960; -$color-core-blue-900: #0c5689; -$color-core-blue-800: #116daa; -$color-core-blue-700: #2079c3; -$color-core-blue-600: #2b87d3; -$color-core-blue-500: #3896e3; -$color-core-blue-400: #56adf5; -$color-core-blue-300: #a1d2f8; -$color-core-blue-200: #c7e4f9; -$color-core-blue-100: #dcf2ff; -$color-core-blue-0: #e9f8ff; -$color-core-aqua-1100: #002838; -$color-core-aqua-1000: #083d4f; -$color-core-aqua-900: #035e73; -$color-core-aqua-800: #0f6e84; -$color-core-aqua-700: #0b8599; -$color-core-aqua-600: #0797ae; -$color-core-aqua-500: #17b8ce; -$color-core-aqua-400: #33d6e2; -$color-core-aqua-300: #76e5e2; -$color-core-aqua-200: #a5f2f2; -$color-core-aqua-100: #c5f9f9; -$color-core-aqua-0: #d9fcfb; -$color-core-teal-1100: #002528; -$color-core-teal-1000: #083f3f; -$color-core-teal-900: #026661; -$color-core-teal-800: #067c7c; -$color-core-teal-700: #0b968f; -$color-core-teal-600: #00a99c; -$color-core-teal-500: #08c4b2; -$color-core-teal-400: #24e0c5; -$color-core-teal-300: #7dead5; -$color-core-teal-200: #b3f2e6; -$color-core-teal-100: #cdf7ef; -$color-core-teal-0: #e5f9f5; -$color-core-green-1100: #002b20; -$color-core-green-1000: #08422f; -$color-core-green-900: #006b40; -$color-core-green-800: #008b46; -$color-core-green-700: #0ca750; -$color-core-green-600: #2bb656; -$color-core-green-500: #59cb59; -$color-core-green-400: #75dd66; -$color-core-green-300: #98e58e; -$color-core-green-200: #c2f2bd; -$color-core-green-100: #d7f4d7; +$color-background-primary: #ffffff !default; +$color-background-secondary: #f3f4f4; +$color-background-tertiary: #dee1e1; +$color-background-danger: #ffeae9; +$color-background-warning: #ffede3; +$color-background-success: #ebf9eb; +$color-background-info: #e9f8ff; +$color-background-disabled: #dee1e1; +$color-border-primary: #c8cccc; +$color-brand-primary: #0b8599; +$color-brand-secondary: #6f5ed3; $color-core-green-0: #ebf9eb; -$color-font-success: $color-core-green-1000; -$color-font-warning: $color-core-orange-1000; -$color-font-danger: $color-core-red-1000; -$color-font-tertiary: $color-core-neutral-800; -$color-font-secondary: $color-core-neutral-900; -$color-font-primary: $color-core-neutral-1100; -$color-brand-secondary: $color-core-purple-700; -$color-brand-primary: $color-core-aqua-700; -$color-border-primary: $color-core-neutral-300; -$color-background-info: $color-core-blue-0; -$color-background-success: $color-core-green-0; -$color-background-warning: $color-core-orange-0; -$color-background-danger: $color-core-red-0; -$color-background-tertiary: $color-core-neutral-200; -$color-background-secondary: $color-core-neutral-100; -$color-background-primary: $color-core-neutral-0 !default; -$color-font-interactive-disabled: $color-font-tertiary; -$color-font-interactive-active: $color-brand-secondary; -$color-font-interactive-hover: $color-brand-primary; -$color-font-interactive: $color-brand-primary; -$color-background-disabled: $color-background-tertiary; -" +$color-core-green-100: #d7f4d7; +$color-core-green-200: #c2f2bd; +$color-core-green-300: #98e58e; +$color-core-green-400: #75dd66; +$color-core-green-500: #59cb59; +$color-core-green-600: #2bb656; +$color-core-green-700: #0ca750; +$color-core-green-800: #008b46; +$color-core-green-900: #006b40; +$color-core-green-1000: #08422f; +$color-core-green-1100: #002b20; +$color-core-teal-0: #e5f9f5; +$color-core-teal-100: #cdf7ef; +$color-core-teal-200: #b3f2e6; +$color-core-teal-300: #7dead5; +$color-core-teal-400: #24e0c5; +$color-core-teal-500: #08c4b2; +$color-core-teal-600: #00a99c; +$color-core-teal-700: #0b968f; +$color-core-teal-800: #067c7c; +$color-core-teal-900: #026661; +$color-core-teal-1000: #083f3f; +$color-core-teal-1100: #002528; +$color-core-aqua-0: #d9fcfb; +$color-core-aqua-100: #c5f9f9; +$color-core-aqua-200: #a5f2f2; +$color-core-aqua-300: #76e5e2; +$color-core-aqua-400: #33d6e2; +$color-core-aqua-500: #17b8ce; +$color-core-aqua-600: #0797ae; +$color-core-aqua-700: #0b8599; +$color-core-aqua-800: #0f6e84; +$color-core-aqua-900: #035e73; +$color-core-aqua-1000: #083d4f; +$color-core-aqua-1100: #002838; +$color-core-blue-0: #e9f8ff; +$color-core-blue-100: #dcf2ff; +$color-core-blue-200: #c7e4f9; +$color-core-blue-300: #a1d2f8; +$color-core-blue-400: #56adf5; +$color-core-blue-500: #3896e3; +$color-core-blue-600: #2b87d3; +$color-core-blue-700: #2079c3; +$color-core-blue-800: #116daa; +$color-core-blue-900: #0c5689; +$color-core-blue-1000: #0a3960; +$color-core-blue-1100: #002138; +$color-core-purple-0: #f2f2f9; +$color-core-purple-100: #eaeaf9; +$color-core-purple-200: #d8d7f9; +$color-core-purple-300: #c1c1f7; +$color-core-purple-400: #a193f2; +$color-core-purple-500: #9180f4; +$color-core-purple-600: #816fea; +$color-core-purple-700: #6f5ed3; +$color-core-purple-800: #5e4eba; +$color-core-purple-900: #483a9c; +$color-core-purple-1000: #2d246b; +$color-core-purple-1100: #1d1d38; +$color-core-magenta-0: #fef0ff; +$color-core-magenta-100: #f9e3fc; +$color-core-magenta-200: #f4c4f7; +$color-core-magenta-300: #edadf2; +$color-core-magenta-400: #f282f5; +$color-core-magenta-500: #db61db; +$color-core-magenta-600: #c44eb9; +$color-core-magenta-700: #ac44a8; +$color-core-magenta-800: #8f3896; +$color-core-magenta-900: #6c2277; +$color-core-magenta-1000: #451551; +$color-core-magenta-1100: #29192d; +$color-core-pink-0: #ffe9f3; +$color-core-pink-100: #fcdbeb; +$color-core-pink-200: #ffb5d5; +$color-core-pink-300: #ff95c1; +$color-core-pink-400: #ff76ae; +$color-core-pink-500: #ef588b; +$color-core-pink-600: #e0447c; +$color-core-pink-700: #ce3665; +$color-core-pink-800: #b22f5b; +$color-core-pink-900: #931847; +$color-core-pink-1000: #561231; +$color-core-pink-1100: #2b1721; +$color-core-red-0: #ffeae9; +$color-core-red-100: #ffd5d2; +$color-core-red-200: #ffb8b1; +$color-core-red-300: #ff9c8f; +$color-core-red-400: #ff7f6e; +$color-core-red-500: #f76054; +$color-core-red-600: #ed4c42; +$color-core-red-700: #db3e3e; +$color-core-red-800: #c63434; +$color-core-red-900: #992222; +$color-core-red-1000: #6d1313; +$color-core-red-1100: #2b1111; +$color-core-orange-0: #ffede3; +$color-core-orange-100: #fcdccc; +$color-core-orange-200: #ffc6a4; +$color-core-orange-300: #ffb180; +$color-core-orange-400: #ff9c5d; +$color-core-orange-500: #fc8943; +$color-core-orange-600: #f57d33; +$color-core-orange-700: #ed7024; +$color-core-orange-800: #ce5511; +$color-core-orange-900: #962c0b; +$color-core-orange-1000: #601700; +$color-core-orange-1100: #2d130e; +$color-core-neutral-0: #ffffff; +$color-core-neutral-100: #f3f4f4; +$color-core-neutral-200: #dee1e1; +$color-core-neutral-300: #c8cccc; +$color-core-neutral-400: #b0b6b7; +$color-core-neutral-500: #929a9b; +$color-core-neutral-600: #6e797a; +$color-core-neutral-700: #515e5f; +$color-core-neutral-800: #364141; +$color-core-neutral-900: #273333; +$color-core-neutral-1000: #162020; +$color-core-neutral-1100: #040404; +$color-core-yellow-0: #fff8e2; +$color-core-yellow-100: #fdefcd; +$color-core-yellow-200: #ffe99a; +$color-core-yellow-300: #ffe16e; +$color-core-yellow-400: #ffd943; +$color-core-yellow-500: #ffcd1c; +$color-core-yellow-600: #ffbc00; +$color-core-yellow-700: #dd9903; +$color-core-yellow-800: #ba7506; +$color-core-yellow-900: #944c0c; +$color-core-yellow-1000: #542a00; +$color-core-yellow-1100: #2d1a05; +$color-font-primary: #040404; +$color-font-secondary: #273333; +$color-font-tertiary: #364141; +$color-font-interactive: #0b8599; +$color-font-interactive-hover: #0b8599; +$color-font-interactive-active: #6f5ed3; +$color-font-interactive-disabled: #364141; +$color-font-danger: #6d1313; +$color-font-warning: #601700; +$color-font-success: #08422f; +$size-border-radius-large: 30rem; +$size-font-small: 0.75rem; +$size-font-medium: 1rem; +$size-font-large: 1.5rem; +$size-font-xl: 2.25rem; +$size-padding-small: 0.5rem; +$size-padding-medium: 1rem; +$size-padding-large: 1rem; +$size-padding-xl: 1rem; + +$design-system-tokens: ( + 'color': ( + 'background': ( + 'primary': $color-background-primary, + 'secondary': $color-background-secondary, + 'tertiary': $color-background-tertiary, + 'danger': $color-background-danger, + 'warning': $color-background-warning, + 'success': $color-background-success, + 'info': $color-background-info, + 'disabled': $color-background-disabled + ), + 'border': ( + 'primary': $color-border-primary, + 'secondary': ( + + ), + 'tertiary': ( + + ) + ), + 'brand': ( + 'primary': $color-brand-primary, + 'secondary': $color-brand-secondary + ), + 'core': ( + 'green': ( + '0': $color-core-green-0, + '100': $color-core-green-100, + '200': $color-core-green-200, + '300': $color-core-green-300, + '400': $color-core-green-400, + '500': $color-core-green-500, + '600': $color-core-green-600, + '700': $color-core-green-700, + '800': $color-core-green-800, + '900': $color-core-green-900, + '1000': $color-core-green-1000, + '1100': $color-core-green-1100 + ), + 'teal': ( + '0': $color-core-teal-0, + '100': $color-core-teal-100, + '200': $color-core-teal-200, + '300': $color-core-teal-300, + '400': $color-core-teal-400, + '500': $color-core-teal-500, + '600': $color-core-teal-600, + '700': $color-core-teal-700, + '800': $color-core-teal-800, + '900': $color-core-teal-900, + '1000': $color-core-teal-1000, + '1100': $color-core-teal-1100 + ), + 'aqua': ( + '0': $color-core-aqua-0, + '100': $color-core-aqua-100, + '200': $color-core-aqua-200, + '300': $color-core-aqua-300, + '400': $color-core-aqua-400, + '500': $color-core-aqua-500, + '600': $color-core-aqua-600, + '700': $color-core-aqua-700, + '800': $color-core-aqua-800, + '900': $color-core-aqua-900, + '1000': $color-core-aqua-1000, + '1100': $color-core-aqua-1100 + ), + 'blue': ( + '0': $color-core-blue-0, + '100': $color-core-blue-100, + '200': $color-core-blue-200, + '300': $color-core-blue-300, + '400': $color-core-blue-400, + '500': $color-core-blue-500, + '600': $color-core-blue-600, + '700': $color-core-blue-700, + '800': $color-core-blue-800, + '900': $color-core-blue-900, + '1000': $color-core-blue-1000, + '1100': $color-core-blue-1100 + ), + 'purple': ( + '0': $color-core-purple-0, + '100': $color-core-purple-100, + '200': $color-core-purple-200, + '300': $color-core-purple-300, + '400': $color-core-purple-400, + '500': $color-core-purple-500, + '600': $color-core-purple-600, + '700': $color-core-purple-700, + '800': $color-core-purple-800, + '900': $color-core-purple-900, + '1000': $color-core-purple-1000, + '1100': $color-core-purple-1100 + ), + 'magenta': ( + '0': $color-core-magenta-0, + '100': $color-core-magenta-100, + '200': $color-core-magenta-200, + '300': $color-core-magenta-300, + '400': $color-core-magenta-400, + '500': $color-core-magenta-500, + '600': $color-core-magenta-600, + '700': $color-core-magenta-700, + '800': $color-core-magenta-800, + '900': $color-core-magenta-900, + '1000': $color-core-magenta-1000, + '1100': $color-core-magenta-1100 + ), + 'pink': ( + '0': $color-core-pink-0, + '100': $color-core-pink-100, + '200': $color-core-pink-200, + '300': $color-core-pink-300, + '400': $color-core-pink-400, + '500': $color-core-pink-500, + '600': $color-core-pink-600, + '700': $color-core-pink-700, + '800': $color-core-pink-800, + '900': $color-core-pink-900, + '1000': $color-core-pink-1000, + '1100': $color-core-pink-1100 + ), + 'red': ( + '0': $color-core-red-0, + '100': $color-core-red-100, + '200': $color-core-red-200, + '300': $color-core-red-300, + '400': $color-core-red-400, + '500': $color-core-red-500, + '600': $color-core-red-600, + '700': $color-core-red-700, + '800': $color-core-red-800, + '900': $color-core-red-900, + '1000': $color-core-red-1000, + '1100': $color-core-red-1100 + ), + 'orange': ( + '0': $color-core-orange-0, + '100': $color-core-orange-100, + '200': $color-core-orange-200, + '300': $color-core-orange-300, + '400': $color-core-orange-400, + '500': $color-core-orange-500, + '600': $color-core-orange-600, + '700': $color-core-orange-700, + '800': $color-core-orange-800, + '900': $color-core-orange-900, + '1000': $color-core-orange-1000, + '1100': $color-core-orange-1100 + ), + 'neutral': ( + '0': $color-core-neutral-0, + '100': $color-core-neutral-100, + '200': $color-core-neutral-200, + '300': $color-core-neutral-300, + '400': $color-core-neutral-400, + '500': $color-core-neutral-500, + '600': $color-core-neutral-600, + '700': $color-core-neutral-700, + '800': $color-core-neutral-800, + '900': $color-core-neutral-900, + '1000': $color-core-neutral-1000, + '1100': $color-core-neutral-1100 + ), + 'yellow': ( + '0': $color-core-yellow-0, + '100': $color-core-yellow-100, + '200': $color-core-yellow-200, + '300': $color-core-yellow-300, + '400': $color-core-yellow-400, + '500': $color-core-yellow-500, + '600': $color-core-yellow-600, + '700': $color-core-yellow-700, + '800': $color-core-yellow-800, + '900': $color-core-yellow-900, + '1000': $color-core-yellow-1000, + '1100': $color-core-yellow-1100 + ) + ), + 'font': ( + 'primary': $color-font-primary, + 'secondary': $color-font-secondary, + 'tertiary': $color-font-tertiary, + 'interactive': ( + '_': $color-font-interactive, + 'hover': $color-font-interactive-hover, + 'active': $color-font-interactive-active, + 'disabled': $color-font-interactive-disabled + ), + 'danger': $color-font-danger, + 'warning': $color-font-warning, + 'success': $color-font-success + ) + ), + 'size': ( + 'border': ( + 'radius': ( + 'large': $size-border-radius-large + ) + ), + 'font': ( + 'small': $size-font-small, + 'medium': $size-font-medium, + 'large': $size-font-large, + 'xl': $size-font-xl + ), + 'padding': ( + 'small': $size-padding-small, + 'medium': $size-padding-medium, + 'large': $size-padding-large, + 'xl': $size-padding-xl + ) + ) +); `; +/* end snapshot integration scss scss/map-deep without themeable should match snapshot */ -exports[`integration scss scss/variables with themeable should match snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -$color-background-primary: #ffffff !default; -$color-background-secondary: #f3f4f4 !default; -$color-background-tertiary: #dee1e1 !default; -$color-background-danger: #ffeae9 !default; -$color-background-warning: #ffede3 !default; -$color-background-success: #ebf9eb !default; -$color-background-info: #e9f8ff !default; -$color-background-disabled: #dee1e1 !default; -$color-border-primary: #c8cccc !default; -$color-brand-primary: #0b8599 !default; -$color-brand-secondary: #6f5ed3 !default; -$color-core-green-0: #ebf9eb !default; -$color-core-green-100: #d7f4d7 !default; -$color-core-green-200: #c2f2bd !default; -$color-core-green-300: #98e58e !default; -$color-core-green-400: #75dd66 !default; -$color-core-green-500: #59cb59 !default; -$color-core-green-600: #2bb656 !default; -$color-core-green-700: #0ca750 !default; -$color-core-green-800: #008b46 !default; -$color-core-green-900: #006b40 !default; -$color-core-green-1000: #08422f !default; -$color-core-green-1100: #002b20 !default; -$color-core-teal-0: #e5f9f5 !default; -$color-core-teal-100: #cdf7ef !default; -$color-core-teal-200: #b3f2e6 !default; -$color-core-teal-300: #7dead5 !default; -$color-core-teal-400: #24e0c5 !default; -$color-core-teal-500: #08c4b2 !default; -$color-core-teal-600: #00a99c !default; -$color-core-teal-700: #0b968f !default; -$color-core-teal-800: #067c7c !default; -$color-core-teal-900: #026661 !default; -$color-core-teal-1000: #083f3f !default; -$color-core-teal-1100: #002528 !default; -$color-core-aqua-0: #d9fcfb !default; -$color-core-aqua-100: #c5f9f9 !default; -$color-core-aqua-200: #a5f2f2 !default; -$color-core-aqua-300: #76e5e2 !default; -$color-core-aqua-400: #33d6e2 !default; -$color-core-aqua-500: #17b8ce !default; -$color-core-aqua-600: #0797ae !default; -$color-core-aqua-700: #0b8599 !default; -$color-core-aqua-800: #0f6e84 !default; -$color-core-aqua-900: #035e73 !default; -$color-core-aqua-1000: #083d4f !default; -$color-core-aqua-1100: #002838 !default; -$color-core-blue-0: #e9f8ff !default; -$color-core-blue-100: #dcf2ff !default; -$color-core-blue-200: #c7e4f9 !default; -$color-core-blue-300: #a1d2f8 !default; -$color-core-blue-400: #56adf5 !default; -$color-core-blue-500: #3896e3 !default; -$color-core-blue-600: #2b87d3 !default; -$color-core-blue-700: #2079c3 !default; -$color-core-blue-800: #116daa !default; -$color-core-blue-900: #0c5689 !default; -$color-core-blue-1000: #0a3960 !default; -$color-core-blue-1100: #002138 !default; -$color-core-purple-0: #f2f2f9 !default; -$color-core-purple-100: #eaeaf9 !default; -$color-core-purple-200: #d8d7f9 !default; -$color-core-purple-300: #c1c1f7 !default; -$color-core-purple-400: #a193f2 !default; -$color-core-purple-500: #9180f4 !default; -$color-core-purple-600: #816fea !default; -$color-core-purple-700: #6f5ed3 !default; -$color-core-purple-800: #5e4eba !default; -$color-core-purple-900: #483a9c !default; -$color-core-purple-1000: #2d246b !default; -$color-core-purple-1100: #1d1d38 !default; -$color-core-magenta-0: #fef0ff !default; -$color-core-magenta-100: #f9e3fc !default; -$color-core-magenta-200: #f4c4f7 !default; -$color-core-magenta-300: #edadf2 !default; -$color-core-magenta-400: #f282f5 !default; -$color-core-magenta-500: #db61db !default; -$color-core-magenta-600: #c44eb9 !default; -$color-core-magenta-700: #ac44a8 !default; -$color-core-magenta-800: #8f3896 !default; -$color-core-magenta-900: #6c2277 !default; -$color-core-magenta-1000: #451551 !default; -$color-core-magenta-1100: #29192d !default; -$color-core-pink-0: #ffe9f3 !default; -$color-core-pink-100: #fcdbeb !default; -$color-core-pink-200: #ffb5d5 !default; -$color-core-pink-300: #ff95c1 !default; -$color-core-pink-400: #ff76ae !default; -$color-core-pink-500: #ef588b !default; -$color-core-pink-600: #e0447c !default; -$color-core-pink-700: #ce3665 !default; -$color-core-pink-800: #b22f5b !default; -$color-core-pink-900: #931847 !default; -$color-core-pink-1000: #561231 !default; -$color-core-pink-1100: #2b1721 !default; -$color-core-red-0: #ffeae9 !default; -$color-core-red-100: #ffd5d2 !default; -$color-core-red-200: #ffb8b1 !default; -$color-core-red-300: #ff9c8f !default; -$color-core-red-400: #ff7f6e !default; -$color-core-red-500: #f76054 !default; -$color-core-red-600: #ed4c42 !default; -$color-core-red-700: #db3e3e !default; -$color-core-red-800: #c63434 !default; -$color-core-red-900: #992222 !default; -$color-core-red-1000: #6d1313 !default; -$color-core-red-1100: #2b1111 !default; -$color-core-orange-0: #ffede3 !default; -$color-core-orange-100: #fcdccc !default; -$color-core-orange-200: #ffc6a4 !default; -$color-core-orange-300: #ffb180 !default; -$color-core-orange-400: #ff9c5d !default; -$color-core-orange-500: #fc8943 !default; -$color-core-orange-600: #f57d33 !default; -$color-core-orange-700: #ed7024 !default; -$color-core-orange-800: #ce5511 !default; -$color-core-orange-900: #962c0b !default; -$color-core-orange-1000: #601700 !default; -$color-core-orange-1100: #2d130e !default; -$color-core-neutral-0: #ffffff !default; -$color-core-neutral-100: #f3f4f4 !default; -$color-core-neutral-200: #dee1e1 !default; -$color-core-neutral-300: #c8cccc !default; -$color-core-neutral-400: #b0b6b7 !default; -$color-core-neutral-500: #929a9b !default; -$color-core-neutral-600: #6e797a !default; -$color-core-neutral-700: #515e5f !default; -$color-core-neutral-800: #364141 !default; -$color-core-neutral-900: #273333 !default; -$color-core-neutral-1000: #162020 !default; -$color-core-neutral-1100: #040404 !default; -$color-core-yellow-0: #fff8e2 !default; -$color-core-yellow-100: #fdefcd !default; -$color-core-yellow-200: #ffe99a !default; -$color-core-yellow-300: #ffe16e !default; -$color-core-yellow-400: #ffd943 !default; -$color-core-yellow-500: #ffcd1c !default; -$color-core-yellow-600: #ffbc00 !default; -$color-core-yellow-700: #dd9903 !default; -$color-core-yellow-800: #ba7506 !default; -$color-core-yellow-900: #944c0c !default; -$color-core-yellow-1000: #542a00 !default; -$color-core-yellow-1100: #2d1a05 !default; -$color-font-primary: #040404 !default; -$color-font-secondary: #273333 !default; -$color-font-tertiary: #364141 !default; -$color-font-interactive: #0b8599 !default; -$color-font-interactive-hover: #0b8599 !default; -$color-font-interactive-active: #6f5ed3 !default; -$color-font-interactive-disabled: #364141 !default; -$color-font-danger: #6d1313 !default; -$color-font-warning: #601700 !default; -$color-font-success: #08422f !default; -$size-border-radius-large: 30rem !default; -$size-font-small: 0.75rem !default; -$size-font-medium: 1rem !default; -$size-font-large: 1.5rem !default; -$size-font-xl: 2.25rem !default; -$size-padding-small: 0.5rem !default; -$size-padding-medium: 1rem !default; -$size-padding-large: 1rem !default; -$size-padding-xl: 1rem !default; -" -`; diff --git a/__integration__/__snapshots__/showFileHeader.test.js.snap b/__integration__/__snapshots__/showFileHeader.test.js.snap deleted file mode 100644 index 9a1173c45..000000000 --- a/__integration__/__snapshots__/showFileHeader.test.js.snap +++ /dev/null @@ -1,51 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration showFileHeader with platform options set to false should not show file header if no file options set 1`] = ` -":root { - --size-padding-small: 0.5rem; - --size-padding-medium: 1rem; - --size-padding-large: 1rem; - --size-padding-xl: 1rem; -} -" -`; - -exports[`integration showFileHeader with platform options set to false should show file header if file options set to true 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --size-padding-small: 0.5rem; - --size-padding-medium: 1rem; - --size-padding-large: 1rem; - --size-padding-xl: 1rem; -} -" -`; - -exports[`integration showFileHeader without platform options should not show file header if file options set to false 1`] = ` -":root { - --size-padding-small: 0.5rem; - --size-padding-medium: 1rem; - --size-padding-large: 1rem; - --size-padding-xl: 1rem; -} -" -`; - -exports[`integration showFileHeader without platform options should show file header if no file options set 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --size-padding-small: 0.5rem; - --size-padding-medium: 1rem; - --size-padding-large: 1rem; - --size-padding-xl: 1rem; -} -" -`; diff --git a/__integration__/__snapshots__/showFileHeader.test.snap.js b/__integration__/__snapshots__/showFileHeader.test.snap.js new file mode 100644 index 000000000..a5b0dfa81 --- /dev/null +++ b/__integration__/__snapshots__/showFileHeader.test.snap.js @@ -0,0 +1,51 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration showFileHeader without platform options should show file header if no file options set"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --size-padding-small: 0.5rem; + --size-padding-medium: 1rem; + --size-padding-large: 1rem; + --size-padding-xl: 1rem; +} +`; +/* end snapshot integration showFileHeader without platform options should show file header if no file options set */ + +snapshots["integration showFileHeader without platform options should not show file header if file options set to false"] = +`:root { + --size-padding-small: 0.5rem; + --size-padding-medium: 1rem; + --size-padding-large: 1rem; + --size-padding-xl: 1rem; +} +`; +/* end snapshot integration showFileHeader without platform options should not show file header if file options set to false */ + +snapshots["integration showFileHeader with platform options set to false should not show file header if no file options set"] = +`:root { + --size-padding-small: 0.5rem; + --size-padding-medium: 1rem; + --size-padding-large: 1rem; + --size-padding-xl: 1rem; +} +`; +/* end snapshot integration showFileHeader with platform options set to false should not show file header if no file options set */ + +snapshots["integration showFileHeader with platform options set to false should show file header if file options set to true"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --size-padding-small: 0.5rem; + --size-padding-medium: 1rem; + --size-padding-large: 1rem; + --size-padding-xl: 1rem; +} +`; +/* end snapshot integration showFileHeader with platform options set to false should show file header if file options set to true */ + diff --git a/__integration__/__snapshots__/swift.test.js.snap b/__integration__/__snapshots__/swift.test.snap.js similarity index 98% rename from __integration__/__snapshots__/swift.test.js.snap rename to __integration__/__snapshots__/swift.test.snap.js index aff693bce..f54195afb 100644 --- a/__integration__/__snapshots__/swift.test.js.snap +++ b/__integration__/__snapshots__/swift.test.snap.js @@ -1,13 +1,13 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; -exports[`integration swift ios-swift/class.swift should match snapshot 1`] = ` -" +snapshots["integration swift ios-swift/class.swift should match snapshot"] = +` // // style_dictionary.swift // -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +// Do not edit directly, this file was auto-generated. import UIKit @@ -175,18 +175,16 @@ public class StyleDictionary { public static let sizePaddingMedium = CGFloat(16.00) public static let sizePaddingSmall = CGFloat(8.00) public static let sizePaddingXl = CGFloat(16.00) -} -" -`; +}`; +/* end snapshot integration swift ios-swift/class.swift should match snapshot */ -exports[`integration swift ios-swift/class.swift with references should match snapshot 1`] = ` -" +snapshots["integration swift ios-swift/class.swift with references should match snapshot"] = +` // // style_dictionary_with_references.swift // -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT +// Do not edit directly, this file was auto-generated. import UIKit @@ -354,6 +352,6 @@ public class StyleDictionary { public static let colorFontInteractiveHover = colorBrandPrimary public static let colorFontInteractive = colorBrandPrimary public static let colorBackgroundDisabled = colorBackgroundTertiary -} -" -`; +}`; +/* end snapshot integration swift ios-swift/class.swift with references should match snapshot */ + diff --git a/__integration__/__snapshots__/w3c-forward-compat.test.snap.js b/__integration__/__snapshots__/w3c-forward-compat.test.snap.js new file mode 100644 index 000000000..073b827b7 --- /dev/null +++ b/__integration__/__snapshots__/w3c-forward-compat.test.snap.js @@ -0,0 +1,16 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration DTCG draft spec forward compatibility should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --colors-black-500: rgb(0, 0, 0); + --colors-black-dimension: 5px; /* Some description */ + --colors-foo: rgb(0, 0, 0); +} +`; +/* end snapshot integration DTCG draft spec forward compatibility should match snapshot */ + diff --git a/__integration__/_constants.js b/__integration__/_constants.js index 6bdb7c823..dbc0dba15 100644 --- a/__integration__/_constants.js +++ b/__integration__/_constants.js @@ -1,10 +1,14 @@ -module.exports = { - buildPath: `__integration__/build/`, - cleanConsoleOutput: (str) => { - const arr = str.split(`\n`) - // Remove ANSI stuff from the console output so we get human-readable strings - // https://github.com/chalk/ansi-regex/blob/main/index.js#L3 - .map(s => s.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,'').trim()); - return arr.join(`\n`) - } -} \ No newline at end of file +export const buildPath = `__integration__/build/`; +export const cleanConsoleOutput = (str) => { + const arr = str + .split(`\n`) + // Remove ANSI stuff from the console output so we get human-readable strings + // https://github.com/chalk/ansi-regex/blob/main/index.js#L3 + .map((s) => + s + // eslint-disable-next-line no-control-regex + .replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '') + .trim(), + ); + return arr.join(`\n`); +}; diff --git a/__integration__/android.test.js b/__integration__/android.test.js index b554f61e3..6ee3b2fcf 100644 --- a/__integration__/android.test.js +++ b/__integration__/android.test.js @@ -10,66 +10,77 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('android', () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { android: { transformGroup: `android`, buildPath, - files: [{ - destination: `resources.xml`, - format: `android/resources` - },{ - destination: `resourcesWithReferences.xml`, - format: `android/resources`, - options: { - outputReferences: true - } - },{ - destination: `colors.xml`, - format: `android/resources`, - filter: { - attributes: { category: `color` } - } - }] - } - } - }).buildAllPlatforms(); + files: [ + { + destination: `resources.xml`, + format: `android/resources`, + }, + { + destination: `resourcesWithReferences.xml`, + format: `android/resources`, + options: { + outputReferences: true, + }, + }, + { + destination: `colors.xml`, + format: `android/resources`, + filter: { + type: `color`, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); - describe(`android/resources`, () => { - const output = fs.readFileSync(`${buildPath}resources.xml`, {encoding:'UTF-8'}); + afterEach(() => { + clearOutput(buildPath); + }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('android', async () => { + describe(`android/resources`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}resources.xml`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}resourcesWithReferences.xml`, {encoding:'UTF-8'}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}resourcesWithReferences.xml`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - }); - describe(`with filter`, () => { - const output = fs.readFileSync(`${buildPath}colors.xml`, {encoding:'UTF-8'}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with filter`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}colors.xml`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/async.test.js b/__integration__/async.test.js new file mode 100644 index 000000000..af57d2ede --- /dev/null +++ b/__integration__/async.test.js @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fileHeader, formattedVariables } from 'style-dictionary/utils'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; + +const sleep = async (time) => { + await new Promise((resolve) => setTimeout(resolve, time)); +}; + +const textFile = resolve(`${buildPath}text.txt`); + +// Tests all hooks async, into a single config +describe('integration', async function () { + this.timeout(10000); + before(async () => { + // so we don't accidentally create side-effects on the StyleDictionary class + // that will affect outputs of other tests. + const SDExtension = class extends StyleDictionary {}; + + SDExtension.registerParser({ + name: 'json-parser', + pattern: /^.+\.json$/g, + parser: async ({ contents }) => { + await sleep(10); + // TODO: verify this is called + return JSON.parse(contents); + }, + }); + + SDExtension.registerPreprocessor({ + name: 'foo-processor', + preprocessor: async (tokens) => { + await sleep(10); + return { + ...tokens, + foo: { + value: 'foo', + type: 'other', + }, + }; + }, + }); + + SDExtension.registerTransform({ + name: 'foo-value-transform', + type: 'value', + filter: (token) => token.value === 'foo', + transform: async () => { + await sleep(10); + return 'bar'; + }, + }); + + SDExtension.registerFormat({ + name: 'custom/css', + format: async function ({ dictionary, file, options }) { + await sleep(10); + const { outputReferences } = options; + return ( + (await fileHeader({ file })) + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, + }); + + SDExtension.registerAction({ + name: 'custom/action', + do: async function () { + await fs.promises.writeFile(textFile, 'foo', 'UTF-8'); + }, + undo: async function () { + await fs.promises.unlink(textFile); + }, + }); + + const sd = new SDExtension({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + preprocessors: ['foo-processor'], + platforms: { + css: { + transforms: [ + 'attribute/cti', + 'name/kebab', + 'time/seconds', + 'html/icon', + 'size/rem', + 'color/css', + 'foo-value-transform', + ], + buildPath, + actions: ['custom/action'], + files: [ + { + destination: 'variables.css', + format: 'custom/css', + options: { + fileHeader: async () => { + await sleep(10); + return ['foo', 'bar']; + }, + }, + filter: async (token) => { + await sleep(2); + return token.attributes.item !== 'info'; + }, + }, + ], + }, + }, + }); + + await sd.buildAllPlatforms(); + }); + + afterEach(() => { + clearOutput(buildPath); + }); + + describe('async hooks', async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variables.css`), 'utf-8'); + const textFileContents = fs.readFileSync(textFile, 'utf-8'); + expect(textFileContents).to.equal('foo'); + await expect(output).to.matchSnapshot(); + }); + }); +}); diff --git a/__integration__/compose.test.js b/__integration__/compose.test.js index 5e5774204..0394349f6 100644 --- a/__integration__/compose.test.js +++ b/__integration__/compose.test.js @@ -10,56 +10,67 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('compose', () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { compose: { transformGroup: `compose`, buildPath, - files: [{ - destination: "StyleDictionary.kt", - format: "compose/object", - className: "StyleDictionary", - packageName: "com.example.tokens" - },{ - destination: "StyleDictionaryWithReferences.kt", - format: "compose/object", - className: "StyleDictionary", - packageName: "com.example.tokens", - options: { - outputReferences: true - } - }] + files: [ + { + destination: 'StyleDictionary.kt', + format: 'compose/object', + options: { + className: 'StyleDictionary', + packageName: 'com.example.tokens', + }, + }, + { + destination: 'StyleDictionaryWithReferences.kt', + format: 'compose/object', + options: { + outputReferences: true, + className: 'StyleDictionary', + packageName: 'com.example.tokens', + }, + }, + ], }, - } - }).buildAllPlatforms(); + }, + }); + await sd.buildAllPlatforms(); + }); - describe(`compose/object`, () => { - const output = fs.readFileSync(`${buildPath}StyleDictionary.kt`, {encoding:`UTF-8`}); + afterEach(() => { + clearOutput(buildPath); + }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('compose', async () => { + describe(`compose/object`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}StyleDictionary.kt`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}StyleDictionaryWithReferences.kt`, {encoding:`UTF-8`}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}StyleDictionaryWithReferences.kt`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/css.test.js b/__integration__/css.test.js index 4c855bb1f..0cff267c7 100644 --- a/__integration__/css.test.js +++ b/__integration__/css.test.js @@ -10,67 +10,109 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('css', () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], // Testing proper string interpolation with multiple references here. // This is a CSS/web-specific thing so only including them in this // integration test. - properties: { + tokens: { breakpoint: { - xs: { value: "304px" }, - sm: { value: "768px" }, - md: { value: "calc({breakpoint.xs.value} / {breakpoint.sm.value})"} - } + xs: { value: '304px' }, + sm: { value: '768px' }, + md: { value: 'calc({breakpoint.xs.value} / {breakpoint.sm.value})' }, + }, }, platforms: { css: { transformGroup: 'css', buildPath, - files: [{ - destination: 'variables.css', - format: 'css/variables' - },{ - destination: 'variablesWithReferences.css', - format: 'css/variables', - options: { - outputReferences: true, - outputReferenceFallbacks: true - } - },{ - destination: 'variablesWithSelector.css', - format: 'css/variables', - options: { - selector: '.test' - } - }] - } - } - }).buildAllPlatforms(); + files: [ + { + destination: 'variables.css', + format: 'css/variables', + options: { + formatting: { indentation: ' ' }, + }, + }, + { + destination: 'variablesWithReferences.css', + format: 'css/variables', + options: { + outputReferences: true, + outputReferenceFallbacks: false, + }, + }, + { + destination: 'variablesWithReferenceFallbacks.css', + format: 'css/variables', + options: { + outputReferences: true, + outputReferenceFallbacks: true, + }, + }, + { + destination: 'variablesWithSelector.css', + format: 'css/variables', + options: { + selector: '.test', + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); + + afterEach(() => { + clearOutput(buildPath); + }); - describe('css/variables', () => { - const output = fs.readFileSync(`${buildPath}variables.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('css', async () => { + describe('css/variables', async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variables.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}variablesWithReferences.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variablesWithReferences.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe(`with selector`, () => { - const output = fs.readFileSync(`${buildPath}variablesWithSelector.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with referenceFallbacks`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync( + resolve(`${buildPath}variablesWithReferenceFallbacks.css`), + { + encoding: 'UTF-8', + }, + ); + await expect(output).to.matchSnapshot(); + }); + }); + + describe(`with selector`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variablesWithSelector.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); @@ -78,7 +120,3 @@ describe('integration', () => { }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/customFileHeader.test.js b/__integration__/customFileHeader.test.js index 733e0a311..ab3c75e13 100644 --- a/__integration__/customFileHeader.test.js +++ b/__integration__/customFileHeader.test.js @@ -10,147 +10,176 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe(`integration`, () => { - describe(`valid custom file headers`, () => { +describe(`integration`, async () => { + before(async () => { // Adding a custom file header with the `.registerFileHeader` StyleDictionary.registerFileHeader({ - name: `registeredFileHeader`, + name: `valid custom file headers test fileHeader`, fileHeader: (defaultMessage) => { - return [ - `hello`, - ...defaultMessage - ] - } + return [`hello`, ...defaultMessage]; + }, }); - StyleDictionary.extend({ - fileHeader: { - configFileHeader: (defaultMessage) => { - return [ - ...defaultMessage, - 'hello, world!' - ]; - } + const sd = new StyleDictionary({ + hooks: { + fileHeaders: { + configFileHeader: (defaultMessage) => { + return [...defaultMessage, 'hello, world!']; + }, + }, }, // only testing the file header in these tests so we are - // using a small properties object with a single token - properties: { + // using a small tokens object with a single token + tokens: { color: { - red: { value: '#ff0000' } - } + red: { value: '#ff0000' }, + }, }, platforms: { css: { transformGroup: `css`, buildPath, - files: [{ - destination: `registeredFileHeader.css`, - format: `css/variables`, - options: { - fileHeader: `registeredFileHeader` - } - },{ - destination: `configFileHeader.css`, - format: `css/variables`, - options: { - fileHeader: `configFileHeader` - } - },{ - destination: `inlineFileHeader.css`, - format: `css/variables`, - options: { - fileHeader: () => { - return [ - `build version 1.0.0` - ] - } - } - }] + files: [ + { + destination: `registeredFileHeader.css`, + format: `css/variables`, + options: { + fileHeader: `valid custom file headers test fileHeader`, + }, + }, + { + destination: `configFileHeader.css`, + format: `css/variables`, + options: { + fileHeader: `configFileHeader`, + }, + }, + { + destination: `inlineFileHeader.css`, + format: `css/variables`, + options: { + fileHeader: () => { + return [`build version 1.0.0`]; + }, + }, + }, + ], }, js: { transformGroup: `js`, buildPath, options: { - fileHeader: `configFileHeader` + fileHeader: `configFileHeader`, }, - files: [{ - destination: `noOptions.js`, - format: `javascript/module` - },{ - destination: `showFileHeader.js`, - format: `javascript/module`, - options: { - showFileHeader: false - } - },{ - destination: `fileHeaderOverride.js`, - format: `javascript/module`, - options: { - fileHeader: () => [`Header overridden`] - } - }] - } - } - }).buildAllPlatforms(); + files: [ + { + destination: `noOptions.js`, + format: `javascript/module`, + }, + { + destination: `showFileHeader.js`, + format: `javascript/module`, + options: { + showFileHeader: false, + }, + }, + { + destination: `fileHeaderOverride.js`, + format: `javascript/module`, + options: { + fileHeader: () => [`Header overridden`], + }, + }, + ], + }, + }, + }); - describe('file options', () => { - it(`registered file header should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}registeredFileHeader.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + await sd.buildAllPlatforms(); + }); + + afterEach(() => { + clearOutput(buildPath); + }); + + describe(`valid custom file headers`, async () => { + describe('file options', async () => { + it(`registered file header should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}registeredFileHeader.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`config file header should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}configFileHeader.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`config file header should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}configFileHeader.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`inline file header should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}inlineFileHeader.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`inline file header should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}inlineFileHeader.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe('platform options', () => { - it(`no file options should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}noOptions.js`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + describe('platform options', async () => { + it(`no file options should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}noOptions.js`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`showFileHeader should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}showFileHeader.js`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`showFileHeader should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}showFileHeader.js`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`file header override should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}fileHeaderOverride.js`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`file header override should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}fileHeaderOverride.js`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); - describe(`invalid custom file headers`, () => { - it(`should throw if trying to use an undefined file header`, () => { - expect(() => { - StyleDictionary.extend({ - platforms: { - css: { - buildPath, - files: [{ + + describe(`invalid custom file headers`, async () => { + it(`should throw if trying to use an undefined file header`, async () => { + const sd = new StyleDictionary({ + platforms: { + css: { + buildPath, + files: [ + { destination: `variables.css`, options: { - fileHeader: `nonexistentFileHeader` - } - }] - } - } - }).buildAllPlatforms(); - }).toThrow(`Can't find fileHeader: nonexistentFileHeader`); + fileHeader: `nonexistentFileHeader`, + }, + }, + ], + }, + }, + }); + + await expect(sd.buildAllPlatforms()).to.eventually.be.rejectedWith( + `Can't find fileHeader: nonexistentFileHeader`, + ); }); }); }); diff --git a/__integration__/customFormats.test.js b/__integration__/customFormats.test.js index c63493b54..bff5ac866 100644 --- a/__integration__/customFormats.test.js +++ b/__integration__/customFormats.test.js @@ -10,22 +10,26 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('custom formats', () => { - const styleDictionary = StyleDictionary.extend({ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; + +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ source: [`__integration__/tokens/size/padding.json`], // Adding formats directly to SD - format: { - inlineCustomFormatWithOldArgs: (dictionary, platform, file) => { - return JSON.stringify({dictionary, platform, file}, null, 2); - }, - inlineCustomFormatWithNewArgs: (opts) => { - return JSON.stringify(opts, null, 2); + hooks: { + formats: { + inlineCustomFormatWithOldArgs: (dictionary, platform, file) => { + return JSON.stringify({ dictionary, platform, file }, null, 2); + }, + inlineCustomFormatWithNewArgs: (opts) => { + return JSON.stringify(opts, null, 2); + }, }, }, platforms: { @@ -33,134 +37,108 @@ describe('integration', () => { transformGroup: 'js', buildPath, options: { - otherOption: `platform option` + otherOption: `platform option`, }, - files: [{ - destination: 'inlineCustomFormatWithOldArgs.json', - format: 'inlineCustomFormatWithOldArgs', - options: { - showFileHeader: true, - otherOption: 'Test' - } - },{ - destination: 'inlineCustomFormatWithNewArgs.json', - format: 'inlineCustomFormatWithNewArgs', - options: { - showFileHeader: true, - otherOption: 'Test' - } - }] + files: [ + { + destination: 'inlineCustomFormatWithOldArgs.json', + format: 'inlineCustomFormatWithOldArgs', + options: { + showFileHeader: true, + otherOption: 'Test', + }, + }, + { + destination: 'inlineCustomFormatWithNewArgs.json', + format: 'inlineCustomFormatWithNewArgs', + options: { + showFileHeader: true, + otherOption: 'Test', + }, + }, + ], }, customFormats: { transformGroup: 'js', buildPath, options: { - otherOption: `platform option` + otherOption: `platform option`, }, - files: [{ - destination: 'registerCustomFormatWithOldArgs.json', - format: 'registerCustomFormatWithOldArgs', - options: { - showFileHeader: true, - otherOption: 'Test' - } - },{ - destination: 'registerCustomFormatWithNewArgs.json', - format: 'registerCustomFormatWithNewArgs', - options: { - showFileHeader: true, - otherOption: 'Test' - } - }] - } - } - }); - - styleDictionary.registerFormat({ - name: 'registerCustomFormatWithOldArgs', - formatter: (dictionary, platform, file) => { - return JSON.stringify({dictionary, platform, file}, null, 2); - } + files: [ + { + destination: 'registerCustomFormatWithNewArgs.json', + format: 'registerCustomFormatWithNewArgs', + options: { + showFileHeader: true, + otherOption: 'Test', + }, + }, + ], + }, + }, }); - styleDictionary.registerFormat({ + sd.registerFormat({ name: 'registerCustomFormatWithNewArgs', - formatter: (opts) => { + format: (opts) => { return JSON.stringify(opts, null, 2); - } + }, }); - styleDictionary.buildAllPlatforms(); - - describe(`inline custom with old args`, () => { - const output = fs.readFileSync(`${buildPath}inlineCustomFormatWithOldArgs.json`, {encoding:'UTF-8'}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); - }); + await sd.buildAllPlatforms(); + }); - it(`should receive proper arguments`, () => { - const { dictionary, platform, file } = JSON.parse(output); - expect(dictionary).toHaveProperty(`properties`); - expect(dictionary).toHaveProperty(`allProperties`); - expect(platform).toHaveProperty(`options.otherOption`, `platform option`); - expect(file).toHaveProperty(`options.otherOption`, `Test`); - }); - }); + afterEach(() => { + clearOutput(buildPath); + }); - describe(`inline custom with new args`, () => { - const output = fs.readFileSync(`${buildPath}inlineCustomFormatWithNewArgs.json`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('custom formats', async () => { + describe(`inline custom with new args`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}inlineCustomFormatWithNewArgs.json`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); it(`should receive proper arguments`, () => { + const output = fs.readFileSync(resolve(`${buildPath}inlineCustomFormatWithNewArgs.json`), { + encoding: 'UTF-8', + }); const { dictionary, platform, file, options } = JSON.parse(output); - expect(dictionary).toHaveProperty(`properties`); - expect(dictionary).toHaveProperty(`allProperties`); - expect(platform).toHaveProperty(`options.otherOption`, `platform option`); - expect(file).toHaveProperty(`options.otherOption`, `Test`); - expect(options).toHaveProperty(`otherOption`, `Test`); + expect(dictionary).to.have.property(`tokens`); + expect(dictionary).to.have.property(`allTokens`); + expect(platform).to.have.nested.property(`options.otherOption`, `platform option`); + expect(file).to.have.nested.property(`options.otherOption`, `Test`); + expect(options).to.have.property(`otherOption`, `Test`); }); }); - - describe(`register custom format with old args`, () => { - const output = fs.readFileSync(`${buildPath}registerCustomFormatWithOldArgs.json`, {encoding:'UTF-8'}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); - }); - - it(`should receive proper arguments`, () => { - const { dictionary, platform, file } = JSON.parse(output); - expect(dictionary).toHaveProperty(`properties`); - expect(dictionary).toHaveProperty(`allProperties`); - expect(platform).toHaveProperty(`options.otherOption`, `platform option`); - expect(file).toHaveProperty(`options.otherOption`, `Test`); - }); - }); - - describe(`register custom format with new args`, () => { - const output = fs.readFileSync(`${buildPath}registerCustomFormatWithNewArgs.json`, {encoding:'UTF-8'}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`register custom format with new args`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync( + resolve(`${buildPath}registerCustomFormatWithNewArgs.json`), + { + encoding: 'UTF-8', + }, + ); + await expect(output).to.matchSnapshot(); }); it(`should receive proper arguments`, () => { + const output = fs.readFileSync( + resolve(`${buildPath}registerCustomFormatWithNewArgs.json`), + { + encoding: 'UTF-8', + }, + ); const { dictionary, platform, file, options } = JSON.parse(output); - expect(dictionary).toHaveProperty(`properties`); - expect(dictionary).toHaveProperty(`allProperties`); - expect(platform).toHaveProperty(`options.otherOption`, `platform option`); - expect(file).toHaveProperty(`options.otherOption`, `Test`); - expect(options).toHaveProperty(`otherOption`, `Test`); + expect(dictionary).to.have.property(`tokens`); + expect(dictionary).to.have.property(`allTokens`); + expect(platform).to.have.nested.property(`options.otherOption`, `platform option`); + expect(file).to.have.nested.property(`options.otherOption`, `Test`); + expect(options).to.have.property(`otherOption`, `Test`); }); }); - }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/flutter.test.js b/__integration__/flutter.test.js index fa7ffe90e..9ee512393 100644 --- a/__integration__/flutter.test.js +++ b/__integration__/flutter.test.js @@ -10,86 +10,105 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('flutter', () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { flutter: { transformGroup: `flutter`, buildPath, - files: [{ - destination: "style_dictionary.dart", - format: "flutter/class.dart", - className: "StyleDictionary" - },{ - destination: "style_dictionary_with_references.dart", - format: "flutter/class.dart", - className: "StyleDictionary", - options: { - outputReferences: true - } - }] + files: [ + { + destination: 'style_dictionary.dart', + format: 'flutter/class.dart', + options: { + className: 'StyleDictionary', + }, + }, + { + destination: 'style_dictionary_with_references.dart', + format: 'flutter/class.dart', + options: { + outputReferences: true, + className: 'StyleDictionary', + }, + }, + ], }, flutter_separate: { transformGroup: `flutter-separate`, buildPath, - files: [{ - destination: "style_dictionary_color.dart", - format: "flutter/class.dart", - className: "StyleDictionaryColor", - type: "color", - filter: { - attributes: { - category: "color" - } - } - },{ - destination: "style_dictionary_sizes.dart", - format: "flutter/class.dart", - className: "StyleDictionarySize", - type: "float", - filter: { - attributes: { - category: "size" - } - } - }] - } - } - }).buildAllPlatforms(); + files: [ + { + destination: 'style_dictionary_color.dart', + format: 'flutter/class.dart', + options: { + className: 'StyleDictionaryColor', + type: 'color', + }, + filter: { + type: 'color', + }, + }, + { + destination: 'style_dictionary_sizes.dart', + format: 'flutter/class.dart', + options: { + className: 'StyleDictionarySize', + type: 'float', + }, + filter: { + type: 'color', + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); - describe(`flutter/class.dart`, () => { - const output = fs.readFileSync(`${buildPath}style_dictionary.dart`, {encoding:`UTF-8`}); + afterEach(() => { + clearOutput(buildPath); + }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('flutter', async () => { + describe(`flutter/class.dart`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}style_dictionary.dart`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}style_dictionary_with_references.dart`, {encoding:`UTF-8`}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync( + resolve(`${buildPath}style_dictionary_with_references.dart`), + { + encoding: `UTF-8`, + }, + ); + await expect(output).to.matchSnapshot(); }); - }); - describe(`separate`, () => { - const output = fs.readFileSync(`${buildPath}style_dictionary_color.dart`,{encoding:`UTF-8`}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`separate`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}style_dictionary_color.dart`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - }) + }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/iOSObjectiveC.test.js b/__integration__/iOSObjectiveC.test.js index d1e7b41c8..0f78e1e7f 100644 --- a/__integration__/iOSObjectiveC.test.js +++ b/__integration__/iOSObjectiveC.test.js @@ -10,96 +10,135 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('ios objective-c', () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { flutter: { transformGroup: `ios`, buildPath, - files: [{ - destination: "singleton.m", - format: "ios/singleton.m", - className: "StyleDictionary" - },{ - destination: "singleton.h", - format: "ios/singleton.h", - className: "StyleDictionary" - },{ - destination: "color.h", - format: "ios/colors.h", - className: "StyleDictionaryColor", - type: "StyleDictionaryColorName", - filter: (token) => token.attributes.category === 'color' - },{ - destination: "color.m", - format: "ios/colors.m", - className: "StyleDictionaryColor", - type: "StyleDictionaryColorName", - filter: (token) => token.attributes.category === 'color' - },{ - destination: "macros.h", - format: "ios/macros", - },{ - destination: "static.h", - format: "ios/static.h", - className: "StyleDictionaryStatic", - type: "CGFloat", - filter: (token) => token.attributes.category === 'size' - },{ - destination: "static.m", - format: "ios/static.m", - className: "StyleDictionaryStatic", - type: "CGFloat", - filter: (token) => token.attributes.category === 'size' - }] + files: [ + { + destination: 'singleton.m', + format: 'ios/singleton.m', + options: { + className: 'StyleDictionary', + }, + }, + { + destination: 'singleton.h', + format: 'ios/singleton.h', + options: { + className: 'StyleDictionary', + }, + }, + { + destination: 'color.h', + format: 'ios/colors.h', + options: { + className: 'StyleDictionaryColor', + type: 'StyleDictionaryColorName', + }, + filter: (token) => token.type === 'color', + }, + { + destination: 'color.m', + format: 'ios/colors.m', + options: { + className: 'StyleDictionaryColor', + type: 'StyleDictionaryColorName', + }, + filter: (token) => token.type === 'color', + }, + { + destination: 'macros.h', + format: 'ios/macros', + }, + { + destination: 'static.h', + format: 'ios/static.h', + options: { + className: 'StyleDictionaryStatic', + type: 'CGFloat', + }, + filter: (token) => token.type === 'dimension' || token.type === 'fontSize', + }, + { + destination: 'static.m', + format: 'ios/static.m', + options: { + className: 'StyleDictionaryStatic', + type: 'CGFloat', + }, + filter: (token) => token.type === 'dimension' || token.type === 'fontSize', + }, + ], }, - } - }).buildAllPlatforms(); + }, + }); + await sd.buildAllPlatforms(); + }); - it(`ios/singleton.m should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}singleton.m`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + afterEach(() => { + clearOutput(buildPath); + }); + + describe('ios objective-c', async () => { + it(`ios/singleton.m should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}singleton.m`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - it(`ios/singleton.h should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}singleton.h`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + it(`ios/singleton.h should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}singleton.h`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - it(`ios/color.m should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}color.m`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + it(`ios/color.m should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}color.m`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - it(`ios/color.h should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}color.h`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + it(`ios/color.h should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}color.h`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - it(`ios/macros.h should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}macros.h`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + it(`ios/macros.h should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}macros.h`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - it(`ios/static.h should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}static.h`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + it(`ios/static.h should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}static.h`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - it(`ios/static.m should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}static.m`, {encoding:`UTF-8`}); - expect(output).toMatchSnapshot(); + it(`ios/static.m should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}static.m`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/logging/__snapshots__/config.test.js.snap b/__integration__/logging/__snapshots__/config.test.js.snap deleted file mode 100644 index f4a2e2791..000000000 --- a/__integration__/logging/__snapshots__/config.test.js.snap +++ /dev/null @@ -1,39 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration > logging > config > property value collisions should not show warnings if given higher log level 1`] = ` -" -Property Value Collisions: -Collision detected at: size.padding.small! Original value: 0.5, New value: 0.5 -Collision detected at: size.padding.small! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.small! Original value: true, New value: true -Collision detected at: size.padding.medium! Original value: 1, New value: 1 -Collision detected at: size.padding.medium! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.medium! Original value: true, New value: true -Collision detected at: size.padding.large! Original value: 1, New value: 1 -Collision detected at: size.padding.large! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.large! Original value: true, New value: true -Collision detected at: size.padding.xl! Original value: 1, New value: 1 -Collision detected at: size.padding.xl! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.xl! Original value: true, New value: true - -" -`; - -exports[`integration > logging > config > property value collisions should not throw, but notify users by default 1`] = ` -" -Property Value Collisions: -Collision detected at: size.padding.small! Original value: 0.5, New value: 0.5 -Collision detected at: size.padding.small! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.small! Original value: true, New value: true -Collision detected at: size.padding.medium! Original value: 1, New value: 1 -Collision detected at: size.padding.medium! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.medium! Original value: true, New value: true -Collision detected at: size.padding.large! Original value: 1, New value: 1 -Collision detected at: size.padding.large! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.large! Original value: true, New value: true -Collision detected at: size.padding.xl! Original value: 1, New value: 1 -Collision detected at: size.padding.xl! Original value: __integration__/tokens/size/padding.json, New value: __integration__/tokens/size/padding.json -Collision detected at: size.padding.xl! Original value: true, New value: true - -" -`; diff --git a/__integration__/logging/__snapshots__/config.test.snap.js b/__integration__/logging/__snapshots__/config.test.snap.js new file mode 100644 index 000000000..0abd10932 --- /dev/null +++ b/__integration__/logging/__snapshots__/config.test.snap.js @@ -0,0 +1,14 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; +snapshots["integration > logging > config > property value collisions should not throw, but notify users by default"] = +` +Token collisions detected (4): +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration > logging > config > property value collisions should not throw, but notify users by default */ + +snapshots["integration > logging > config > property value collisions should not show warnings if given higher log level"] = +` +Token collisions detected (4): +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration > logging > config > property value collisions should not show warnings if given higher log level */ + diff --git a/__integration__/logging/__snapshots__/file.test.js.snap b/__integration__/logging/__snapshots__/file.test.snap.js similarity index 67% rename from __integration__/logging/__snapshots__/file.test.js.snap rename to __integration__/logging/__snapshots__/file.test.snap.js index 9691896ce..ec93c2e86 100644 --- a/__integration__/logging/__snapshots__/file.test.js.snap +++ b/__integration__/logging/__snapshots__/file.test.snap.js @@ -1,31 +1,40 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; -exports[`integration logging file should not warn user of empty properties with log level set to error 1`] = ` -" +snapshots["integration logging file empty tokens should warn user about empty tokens"] = +` css -No properties for empty.css. File not created." -`; +No tokens for empty.css. File not created.`; +/* end snapshot integration logging file empty tokens should warn user about empty tokens */ -exports[`integration logging file should not warn user of filtered references with log level set to error 1`] = ` -" +snapshots["integration logging file name collisions should warn users briefly of name collisions by default"] = +` css -⚠️ __integration__/build/filteredReferences.css -While building filteredReferences.css, filtered out token references were found; output may be unexpected. Here are the references that are used but not defined in the file -color.core.neutral.100 -color.core.neutral.0 -color.core.neutral.200 -color.core.red.0 -color.core.orange.0 -color.core.green.0 -color.core.blue.0 -This is caused when combining a filter and \`outputReferences\`." -`; +⚠️ __integration__/build/nameCollisions.css +While building nameCollisions.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration logging file name collisions should warn users briefly of name collisions by default */ + +snapshots["integration logging file name collisions should throw a brief error of name collisions with log level set to error"] = +`⚠️ __integration__/build/nameCollisions.css +While building nameCollisions.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration logging file name collisions should throw a brief error of name collisions with log level set to error */ -exports[`integration logging file should not warn user of name collisions with log level set to error 1`] = ` -" +snapshots["integration logging file name collisions should throw a brief error of name collisions with log level set to error on platform level"] = +`⚠️ __integration__/build/nameCollisions.css +While building nameCollisions.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration logging file name collisions should throw a brief error of name collisions with log level set to error on platform level */ + +snapshots["integration logging file name collisions should warn user of name collisions with a detailed message through \"verbose\" verbosity"] = +` css ⚠️ __integration__/build/nameCollisions.css -While building nameCollisions.css, token collisions were found; output may be unexpected. +While building nameCollisions.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. Output name 0 was generated by: color.core.green.0 #ebf9eb color.core.teal.0 #e5f9f5 @@ -195,37 +204,14 @@ Output name disabled was generated by: color.background.disabled #dee1e1 color.font.interactive.disabled #364141 This many-to-one issue is usually caused by some combination of: -* conflicting or similar paths/names in property definitions +* conflicting or similar paths/names in token definitions * platform transforms/transformGroups affecting names, especially when removing specificity -* overly inclusive file filters" -`; +* overly inclusive file filters`; +/* end snapshot integration logging file name collisions should warn user of name collisions with a detailed message through "verbose" verbosity */ -exports[`integration logging file should warn user empty properties 1`] = ` -" -css -No properties for empty.css. File not created." -`; - -exports[`integration logging file should warn user of filtered references 1`] = ` -" -css -⚠️ __integration__/build/filteredReferences.css -While building filteredReferences.css, filtered out token references were found; output may be unexpected. Here are the references that are used but not defined in the file -color.core.neutral.100 -color.core.neutral.0 -color.core.neutral.200 -color.core.red.0 -color.core.orange.0 -color.core.green.0 -color.core.blue.0 -This is caused when combining a filter and \`outputReferences\`." -`; - -exports[`integration logging file should warn user of name collisions 1`] = ` -" -css -⚠️ __integration__/build/nameCollisions.css -While building nameCollisions.css, token collisions were found; output may be unexpected. +snapshots["integration logging file name collisions should throw detailed error of name collisions through \"verbose\" verbosity and log level set to error"] = +`⚠️ __integration__/build/nameCollisions.css +While building nameCollisions.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. Output name 0 was generated by: color.core.green.0 #ebf9eb color.core.teal.0 #e5f9f5 @@ -395,7 +381,67 @@ Output name disabled was generated by: color.background.disabled #dee1e1 color.font.interactive.disabled #364141 This many-to-one issue is usually caused by some combination of: -* conflicting or similar paths/names in property definitions +* conflicting or similar paths/names in token definitions * platform transforms/transformGroups affecting names, especially when removing specificity -* overly inclusive file filters" -`; +* overly inclusive file filters`; +/* end snapshot integration logging file name collisions should throw detailed error of name collisions through "verbose" verbosity and log level set to error */ + +snapshots["integration logging file filtered references should warn users briefly of filtered references by default"] = +` +css +⚠️ __integration__/build/filteredReferences.css +While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration logging file filtered references should warn users briefly of filtered references by default */ + +snapshots["integration logging file filtered references should throw a brief error of filtered references with log level set to error"] = +`⚠️ __integration__/build/filteredReferences.css +While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration logging file filtered references should throw a brief error of filtered references with log level set to error */ + +snapshots["integration logging file filtered references should throw a brief error of filtered references with log level set to error on platform level"] = +`⚠️ __integration__/build/filteredReferences.css +While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration logging file filtered references should throw a brief error of filtered references with log level set to error on platform level */ + +snapshots["integration logging file filtered references should warn user of filtered references with a detailed message through \"verbose\" verbosity"] = +` +css +⚠️ __integration__/build/filteredReferences.css +While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. +Here are the references that are used but not defined in the file: +color.core.neutral.100 +color.core.neutral.0 +color.core.neutral.200 +color.core.red.0 +color.core.orange.0 +color.core.green.0 +color.core.blue.0 +This is caused when combining a filter and \`outputReferences\`.`; +/* end snapshot integration logging file filtered references should warn user of filtered references with a detailed message through "verbose" verbosity */ + +snapshots["integration logging file filtered references should throw detailed error of filtered references through \"verbose\" verbosity and log level set to error"] = +`⚠️ __integration__/build/filteredReferences.css +While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. +Here are the references that are used but not defined in the file: +color.core.neutral.100 +color.core.neutral.0 +color.core.neutral.200 +color.core.red.0 +color.core.orange.0 +color.core.green.0 +color.core.blue.0 +This is caused when combining a filter and \`outputReferences\`.`; +/* end snapshot integration logging file filtered references should throw detailed error of filtered references through "verbose" verbosity and log level set to error */ + +snapshots["integration logging file empty tokens should not warn user about empty tokens with silent log verbosity"] = +` +css +No tokens for empty.css. File not created.`; +/* end snapshot integration logging file empty tokens should not warn user about empty tokens with silent log verbosity */ + diff --git a/__integration__/logging/__snapshots__/platform.test.js.snap b/__integration__/logging/__snapshots__/platform.test.js.snap deleted file mode 100644 index 282070757..000000000 --- a/__integration__/logging/__snapshots__/platform.test.js.snap +++ /dev/null @@ -1,37 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`integration logging platform property reference errors circular references should throw notify users 1`] = ` -" -css - -Property Reference Errors: -Circular definition cycle: color.foo.value, color.foo.value, color.foo.value -Circular definition cycle: color.teal.value, color.blue.value, color.green.value, color.teal.value - -" -`; - -exports[`integration logging platform property reference errors should throw and notify users of unknown references 1`] = ` -" -css - -Property Reference Errors: -Reference doesn't exist: color.danger.value tries to reference color.red.value, which is not defined - -" -`; - -exports[`integration logging platform should throw and notify users of unknown actions 1`] = ` -" -css" -`; - -exports[`integration logging platform should throw and notify users of unknown transformGroups 1`] = ` -" -css" -`; - -exports[`integration logging platform should throw and notify users of unknown transforms 1`] = ` -" -css" -`; diff --git a/__integration__/logging/__snapshots__/platform.test.snap.js b/__integration__/logging/__snapshots__/platform.test.snap.js new file mode 100644 index 000000000..e24d12e2a --- /dev/null +++ b/__integration__/logging/__snapshots__/platform.test.snap.js @@ -0,0 +1,36 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration logging platform should throw and notify users of unknown actions"] = +`Cannot read properties of undefined (reading 'undo')`; +/* end snapshot integration logging platform should throw and notify users of unknown actions */ + +snapshots["integration logging platform should throw and notify users of unknown transforms"] = +` +Unknown transforms "foo", "bar" found in platform "css": +None of "foo", "bar" match the name of a registered transform. +`; +/* end snapshot integration logging platform should throw and notify users of unknown transforms */ + +snapshots["integration logging platform should throw and notify users of unknown transformGroups"] = +` +Unknown transformGroup "foo" found in platform "css": +"foo" does not match the name of a registered transformGroup. +`; +/* end snapshot integration logging platform should throw and notify users of unknown transformGroups */ +snapshots["integration logging platform property reference errors should throw and notify users of unknown references"] = +` +Reference Errors: +Some token references (1) could not be found. +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`; +/* end snapshot integration logging platform property reference errors should throw and notify users of unknown references */ + +snapshots["integration logging platform property reference errors circular references should throw and notify users"] = +` +Reference Errors: +Some token references (2) could not be found. +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`; +/* end snapshot integration logging platform property reference errors circular references should throw and notify users */ + diff --git a/__integration__/logging/config.test.js b/__integration__/logging/config.test.js index 7cb3bad61..cbe8ca040 100644 --- a/__integration__/logging/config.test.js +++ b/__integration__/logging/config.test.js @@ -10,65 +10,104 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const StyleDictionary = require('../../index'); -const {buildPath, cleanConsoleOutput} = require('../_constants'); - -// Spy on console.log and add all messages to an array -let consoleOutput = []; -const log = jest.spyOn(console, "log") - .mockImplementation(message => consoleOutput.push(message)) +import { expect } from 'chai'; +import { restore, stubMethod } from 'hanbi'; +import StyleDictionary from 'style-dictionary'; +import { buildPath, cleanConsoleOutput } from '../_constants.js'; +import { clearOutput } from '../../__tests__/__helpers.js'; /** * These integration tests will verify the behavior and logging at the *config* * level. These messages happen when `.extend()` is called to verify * proper configuration such as source being an array. This will also check * for collisions in source files and any errors that happen when parsing - * and merging properties. This is the first of 3 phases of logging, the + * and merging tokens. This is the first of 3 phases of logging, the * next two are: platform and file. */ describe(`integration >`, () => { - // before each test clear the mocked console.log and the output array + let stub; beforeEach(() => { - log.mockClear(); - consoleOutput = []; + stub = stubMethod(console, 'log'); + }); + afterEach(() => { + restore(); + clearOutput(buildPath); }); describe(`logging >`, () => { describe(`config >`, () => { describe(`property value collisions`, () => { - it(`should not throw, but notify users by default`, () => { - StyleDictionary.extend({ + it(`should not throw, but notify users by default`, async () => { + const sd = new StyleDictionary({ source: [ // including a specific file twice will throw value collision warnings `__integration__/tokens/size/padding.json`, - `__integration__/tokens/size/padding.json` + `__integration__/tokens/size/_padding.json`, ], - platforms: { - } + platforms: {}, }); - expect(consoleOutput.map(cleanConsoleOutput).join(`\n`)).toMatchSnapshot(); + await sd.hasInitialized; + const consoleOutput = stub.firstCall.args.map(cleanConsoleOutput).join('\n'); + await expect(consoleOutput).to.matchSnapshot(); }); - it(`should not show warnings if given higher log level`, () => { - StyleDictionary.extend({ - logLevel: `error`, + it(`should not log anything if the log verbosity is set to silent`, async () => { + const sd = new StyleDictionary({ + log: { + verbosity: 'silent', + }, source: [ // including a specific file twice will throw value collision warnings `__integration__/tokens/size/padding.json`, - `__integration__/tokens/size/padding.json` + `__integration__/tokens/size/_padding.json`, ], - platforms: { - } + platforms: {}, }); - expect(consoleOutput.map(cleanConsoleOutput).join(`\n`)).toMatchSnapshot(); + await sd.hasInitialized; + await expect(stub.callCount).to.equal(0); + }); + + it(`should not log anything if the log warnings is set to disabled`, async () => { + const sd = new StyleDictionary({ + log: { + warnings: 'disabled', + }, + source: [ + // including a specific file twice will throw value collision warnings + `__integration__/tokens/size/padding.json`, + `__integration__/tokens/size/_padding.json`, + ], + platforms: {}, + }); + await sd.hasInitialized; + await expect(stub.callCount).to.equal(0); + }); + + it(`should not show warnings if given higher log level`, async () => { + const sd = new StyleDictionary( + { + log: { warnings: `error` }, + source: [ + // including a specific file twice will throw value collision warnings + `__integration__/tokens/size/padding.json`, + `__integration__/tokens/size/_padding.json`, + ], + platforms: {}, + }, + { init: false }, + ); + + let error; + try { + await sd.init(); + } catch (e) { + error = e; + } + + await expect(error.message).to.matchSnapshot(); + expect(stub.called).to.be.false; }); }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/logging/file.test.js b/__integration__/logging/file.test.js index 6617d3e54..99a47bd2c 100644 --- a/__integration__/logging/file.test.js +++ b/__integration__/logging/file.test.js @@ -10,17 +10,11 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const StyleDictionary = require('../../index'); -const {buildPath, cleanConsoleOutput} = require('../_constants'); - -// Spy on console.log and add all messages to an array -let consoleOutput = []; -const log = jest.spyOn(console, "log") - .mockImplementation(message => consoleOutput.push(message)) - - +import { expect } from 'chai'; +import { restore, stubMethod } from 'hanbi'; +import StyleDictionary from 'style-dictionary'; +import { buildPath, cleanConsoleOutput } from '../_constants.js'; +import { clearOutput } from '../../__tests__/__helpers.js'; /** * The last and final level of logging: file. * These logs happen when a file is being built and will notify the user @@ -29,139 +23,527 @@ const log = jest.spyOn(console, "log") * out references. */ describe(`integration`, () => { - // before each test clear the mocked console.log and the output array + let stub; beforeEach(() => { - log.mockClear(); - consoleOutput = []; + stub = stubMethod(console, 'log'); + }); + afterEach(() => { + restore(); + clearOutput(buildPath); }); describe(`logging`, () => { describe(`file`, () => { - it(`should warn user empty properties`, () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], - platforms: { - css: { - transformGroup: `css`, - files: [{ - destination: `empty.css`, - format: `css/variables`, - filter: (token) => token.attributes.category === `foo` - }] - } - } - }).buildAllPlatforms(); + describe('empty tokens', () => { + it(`should warn user about empty tokens`, async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + files: [ + { + destination: `empty.css`, + format: `css/variables`, + filter: (token) => token.type === `foo`, + }, + ], + }, + }, + }); + + await sd.buildAllPlatforms(); + const logs = Array.from(stub.calls).flatMap((call) => call.args); + const consoleOutput = logs.map(cleanConsoleOutput).join('\n'); + await expect(consoleOutput).to.matchSnapshot(); + }); + + it(`should not warn user about empty tokens with silent log verbosity`, async () => { + const sd = new StyleDictionary({ + log: { verbosity: 'silent' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + files: [ + { + destination: `empty.css`, + format: `css/variables`, + filter: (token) => token.type === `foo`, + }, + ], + }, + }, + }); + + await sd.buildAllPlatforms(); + expect(stub.callCount).to.equal(0); + }); + + it(`should not warn user about empty tokens with silent log verbosity`, async () => { + const sd = new StyleDictionary({ + log: { warnings: 'disabled' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + files: [ + { + destination: `empty.css`, + format: `css/variables`, + filter: (token) => token.type === `foo`, + }, + ], + }, + }, + }); + + await sd.buildAllPlatforms(); + // 1 due to success log "css" + expect(stub.callCount).to.equal(1); + }); + + it(`should not warn user about empty tokens with log level set to error`, async () => { + const sd = new StyleDictionary({ + log: { warnings: 'error' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + files: [ + { + destination: `empty.css`, + format: `css/variables`, + filter: (token) => token.type === `foo`, + }, + ], + }, + }, + }); + + await expect(sd.buildAllPlatforms()).to.eventually.rejectedWith( + 'No tokens for empty.css. File not created.', + ); + }); + + it(`should not warn user about empty tokens with log level set to error on platform level`, async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + log: { warnings: 'error' }, + transformGroup: `css`, + files: [ + { + destination: `empty.css`, + format: `css/variables`, + filter: (token) => token.type === `foo`, + }, + ], + }, + }, + }); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); + await expect(sd.buildAllPlatforms()).to.eventually.rejectedWith( + 'No tokens for empty.css. File not created.', + ); + }); }); - it(`should not warn user of empty properties with log level set to error`, () => { - StyleDictionary.extend({ - logLevel: `error`, - source: [`__integration__/tokens/**/*.json?(c)`], - platforms: { - css: { - transformGroup: `css`, - files: [{ - destination: `empty.css`, - format: `css/variables`, - filter: (token) => token.attributes.category === `foo` - }] - } + describe('name collisions', () => { + it(`should warn users briefly of name collisions by default`, async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + const logs = Array.from(stub.calls).flatMap((call) => call.args); + const consoleOutput = logs.map(cleanConsoleOutput).join('\n'); + await expect(consoleOutput).to.matchSnapshot(); + }); + + it(`should not warn user of name collisions with log verbosity silent`, async () => { + const sd = new StyleDictionary({ + log: { verbosity: 'silent' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + expect(stub.callCount).to.equal(0); + }); + + it(`should not warn user of name collisions with log verbosity silent`, async () => { + const sd = new StyleDictionary({ + log: { warnings: 'disabled' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + // 1 due to success log "css" + expect(stub.callCount).to.equal(1); + }); + + it(`should throw a brief error of name collisions with log level set to error`, async () => { + const sd = new StyleDictionary({ + log: { warnings: `error` }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; } - }).buildAllPlatforms(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); - }); + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); + }); - it(`should warn user of name collisions`, () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], - platforms: { - css: { - // no name transform means there will be name collisions - transforms: [`attribute/cti`], - buildPath, - files: [{ - destination: `nameCollisions.css`, - format: `css/variables`, - filter: (token) => token.attributes.category === `color` - }] - } + it(`should throw a brief error of name collisions with log level set to error on platform level`, async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + log: { warnings: `error` }, + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; } - }).buildAllPlatforms(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); - }); + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); + // only log is the platform name at the start of the buildPlatform method + }); + + it(`should warn user of name collisions with a detailed message through "verbose" verbosity`, async () => { + const sd = new StyleDictionary({ + log: { verbosity: 'verbose' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + const logs = Array.from(stub.calls).flatMap((call) => call.args); + const consoleOutput = logs.map(cleanConsoleOutput).join('\n'); + await expect(consoleOutput).to.matchSnapshot(); + }); - it(`should not warn user of name collisions with log level set to error`, () => { - StyleDictionary.extend({ - logLevel: `error`, - source: [`__integration__/tokens/**/*.json?(c)`], - platforms: { - css: { - // no name transform means there will be name collisions - transforms: [`attribute/cti`], - buildPath, - files: [{ - destination: `nameCollisions.css`, - format: `css/variables`, - filter: (token) => token.attributes.category === `color` - }] - } + it(`should throw detailed error of name collisions through "verbose" verbosity and log level set to error`, async () => { + const sd = new StyleDictionary({ + log: { warnings: `error`, verbosity: 'verbose' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + // no name transform means there will be name collisions + transforms: [`attribute/cti`], + buildPath, + files: [ + { + destination: `nameCollisions.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + ], + }, + }, + }); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; } - }).buildAllPlatforms(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); + }); }); - it(`should warn user of filtered references`, () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], - platforms: { - css: { - transformGroup: `css`, - buildPath, - files: [{ - destination: `filteredReferences.css`, - format: `css/variables`, - options: { - outputReferences: true - }, - // background colors have references, only including them - // should warn the user - filter: (token) => token.attributes.type === `background` - }] - } + describe('filtered references', () => { + it(`should warn users briefly of filtered references by default`, async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + const logs = Array.from(stub.calls).flatMap((call) => call.args); + const consoleOutput = logs.map(cleanConsoleOutput).join('\n'); + await expect(consoleOutput).to.matchSnapshot(); + }); + + it(`should not warn user of filtered references with log verbosity silent`, async () => { + const sd = new StyleDictionary({ + log: { verbosity: 'silent' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + expect(stub.callCount).to.equal(0); + }); + + it(`should not warn user of filtered references with log verbosity silent`, async () => { + const sd = new StyleDictionary({ + log: { warnings: 'disabled' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + // 1 due to success log "css" + expect(stub.callCount).to.equal(1); + }); + + it(`should throw a brief error of filtered references with log level set to error`, async () => { + const sd = new StyleDictionary({ + log: { warnings: `error` }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; } - }).buildAllPlatforms(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); - }); + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); + // only log is the platform name at the start of the buildPlatform method + }); - it(`should not warn user of filtered references with log level set to error`, () => { - StyleDictionary.extend({ - logLevel: `error`, - source: [`__integration__/tokens/**/*.json?(c)`], - platforms: { - css: { - transformGroup: `css`, - buildPath, - files: [{ - destination: `filteredReferences.css`, - format: `css/variables`, - options: { - outputReferences: true - }, - // background colors have references, only including them - // should warn the user - filter: (token) => token.attributes.type === `background` - }] - } + it(`should throw a brief error of filtered references with log level set to error on platform level`, async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + log: { warnings: `error` }, + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; } - }).buildAllPlatforms(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); + // only log is the platform name at the start of the buildPlatform method + }); + + it(`should warn user of filtered references with a detailed message through "verbose" verbosity`, async () => { + const sd = new StyleDictionary({ + log: { verbosity: 'verbose' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + const logs = Array.from(stub.calls).flatMap((call) => call.args); + const consoleOutput = logs.map(cleanConsoleOutput).join('\n'); + await expect(consoleOutput).to.matchSnapshot(); + }); + + it(`should throw detailed error of filtered references through "verbose" verbosity and log level set to error`, async () => { + const sd = new StyleDictionary({ + log: { warnings: `error`, verbosity: 'verbose' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: `css`, + buildPath, + files: [ + { + destination: `filteredReferences.css`, + format: `css/variables`, + options: { + outputReferences: true, + }, + // background colors have references, only including them + // should warn the user + filter: (token) => token.attributes.type === `background`, + }, + ], + }, + }, + }); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; + } + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); + }); }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/logging/platform.test.js b/__integration__/logging/platform.test.js index 6178b9af8..d5ef74e35 100644 --- a/__integration__/logging/platform.test.js +++ b/__integration__/logging/platform.test.js @@ -10,15 +10,10 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const StyleDictionary = require('../../index'); -const {buildPath, cleanConsoleOutput} = require('../_constants'); - -// Spy on console.log and add all messages to an array -let consoleOutput = []; -const log = jest.spyOn(console, "log") - .mockImplementation(message => consoleOutput.push(message)) +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { buildPath, cleanConsoleOutput } from '../_constants.js'; +import { clearOutput } from '../../__tests__/__helpers.js'; /** * This is the 2nd phase of logging: the platform configuration. This happens @@ -30,96 +25,114 @@ const log = jest.spyOn(console, "log") * */ describe(`integration`, () => { - // before each test clear the mocked console.log and the output array - beforeEach(() => { - log.mockClear(); - consoleOutput = []; + afterEach(() => { + clearOutput(buildPath); }); describe(`logging`, () => { describe(`platform`, () => { - it(`should throw and notify users of unknown actions`, () => { + it(`should throw and notify users of unknown actions`, async () => { + const sd = new StyleDictionary({ + tokens: {}, + platforms: { + css: { + actions: [`foo`], + }, + }, + }); // unknown actions should throw - expect(() => { - StyleDictionary.extend({ - properties: {}, - platforms: { - css: { - actions: [`foo`] - } - } - }).buildAllPlatforms(); - }).toThrow(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; + } + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); }); - it(`should throw and notify users of unknown transforms`, () => { - expect(() => { - StyleDictionary.extend({ - platforms: { - css: { - transforms: [`foo`,`bar`] - } - } - }).buildAllPlatforms(); - }).toThrow(); - expect(consoleOutput.map(cleanConsoleOutput).join(`\n`)).toMatchSnapshot(); + it(`should throw and notify users of unknown transforms`, async () => { + const sd = new StyleDictionary({ + platforms: { + css: { + transforms: [`foo`, `bar`], + }, + }, + }); + // unknown actions should throw + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; + } + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); }); - it(`should throw and notify users of unknown transformGroups`, () => { - expect(() => { - StyleDictionary.extend({ - platforms: { - css: { - transformGroup: `foo` - } - } - }).buildAllPlatforms(); - }).toThrow(); - expect(consoleOutput.map(cleanConsoleOutput).join(`\n`)).toMatchSnapshot(); + it(`should throw and notify users of unknown transformGroups`, async () => { + const sd = new StyleDictionary({ + platforms: { + css: { + transformGroup: `foo`, + }, + }, + }); + // unknown actions should throw + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; + } + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); }); describe(`property reference errors`, () => { - it(`should throw and notify users of unknown references`, () => { - expect(() => { - StyleDictionary.extend({ - properties: { - color: { - danger: { value: "{color.red.value}" }, - } + it(`should throw and notify users of unknown references`, async () => { + const sd = new StyleDictionary({ + tokens: { + color: { + danger: { value: '{color.red.value}' }, }, - platforms: { - css: {} - } - }).buildAllPlatforms(); - }).toThrow(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); + }, + platforms: { + css: {}, + }, + }); + // unknown actions should throw + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; + } + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); }); - it(`circular references should throw notify users`, () => { - expect(() => { - StyleDictionary.extend({ - properties: { - color: { - foo: { value: "{color.foo.value}" }, - teal: { value: "{color.blue.value}" }, - blue: { value: "{color.green.value}" }, - green: { value: "{color.teal.value}" }, - purple: { value: "{color.teal.value}" } - } + it(`circular references should throw and notify users`, async () => { + const sd = new StyleDictionary({ + tokens: { + color: { + foo: { value: '{color.foo.value}' }, + teal: { value: '{color.blue.value}' }, + blue: { value: '{color.green.value}' }, + green: { value: '{color.teal.value}' }, + purple: { value: '{color.teal.value}' }, }, - platforms: { - css: {} - } - }).buildAllPlatforms(); - }).toThrow(); - expect(consoleOutput.map(cleanConsoleOutput).join('\n')).toMatchSnapshot(); + }, + platforms: { + css: {}, + }, + }); + // unknown actions should throw + let error; + try { + await sd.buildAllPlatforms(); + } catch (e) { + error = e; + } + await expect(cleanConsoleOutput(error.message)).to.matchSnapshot(); }); }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/nameCollisions.test.js b/__integration__/nameCollisions.test.js index 7cdf0fb0e..428686d9f 100644 --- a/__integration__/nameCollisions.test.js +++ b/__integration__/nameCollisions.test.js @@ -10,65 +10,97 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { stubMethod, restore } from 'hanbi'; +import { buildPath, cleanConsoleOutput } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const chalk = require('chalk'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -const properties = { +const tokens = { color: { red: { value: '#f00' }, background: { - red: { value: '{color.red.value}' } - } - } -} + red: { value: '{color.red.value}' }, + }, + }, +}; + +describe('integration', async () => { + let stub; + beforeEach(() => { + stub = stubMethod(console, 'log'); + }); -describe('integration', () => { - describe('name collisions', () => { - it(`should warn users of name collisions for flat files`, () => { - console.log = jest.fn(); - StyleDictionary.extend({ + afterEach(() => { + clearOutput(buildPath); + restore(); + }); + + describe('name collisions', async () => { + it(`should warn users of name collisions for flat files, brief version`, async () => { + const sd = new StyleDictionary({ // we are only testing name collision warnings options so we don't need // the full source. - properties, + tokens, platforms: { web: { buildPath, - files: [{ - destination: 'variables.css', - format: 'css/variables', - }] + files: [ + { + destination: 'variables.css', + format: 'css/variables', + }, + ], }, - } - }).buildAllPlatforms(); - expect(console.log).toHaveBeenCalledWith(`⚠️ ${buildPath}variables.css`); + }, + }); + await sd.buildAllPlatforms(); + await expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.matchSnapshot(); }); - it(`should not warn users of name collisions for nested files`, () => { - console.log = jest.fn(); - StyleDictionary.extend({ + it(`should warn users of name collisions for flat files`, async () => { + const sd = new StyleDictionary({ // we are only testing name collision warnings options so we don't need // the full source. - properties, + tokens, + log: { verbosity: 'verbose' }, platforms: { web: { buildPath, - files: [{ - destination: 'tokens.json', - format: 'json/nested' - }] + files: [ + { + destination: 'variables.css', + format: 'css/variables', + }, + ], }, - } - }).buildAllPlatforms(); - expect(console.log).toHaveBeenCalledWith(chalk.bold.green(`✔︎ ${buildPath}tokens.json`)); + }, + }); + await sd.buildAllPlatforms(); + await expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.matchSnapshot(); }); - + it(`should not warn users of name collisions for nested files`, async () => { + const sd = new StyleDictionary({ + // we are only testing name collision warnings options so we don't need + // the full source. + tokens, + platforms: { + web: { + buildPath, + files: [ + { + destination: 'tokens.json', + format: 'json/nested', + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.equal( + `✔︎ ${buildPath}tokens.json`, + ); + }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/objectValues.test.js b/__integration__/objectValues.test.js index d97582f11..22042587f 100644 --- a/__integration__/objectValues.test.js +++ b/__integration__/objectValues.test.js @@ -10,253 +10,288 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import Color from 'tinycolor2'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const Color = require('tinycolor2'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -const options = { - outputReferences: true -} - -describe('integration', () => { - describe('object values', () => { - StyleDictionary.extend({ - properties: { +describe('integration', async () => { + before(async () => { + const options = { + outputReferences: true, + }; + const sd = new StyleDictionary({ + tokens: { hue: `120`, saturation: `50%`, lightness: `50%`, color: { - red: { value: "#f00" }, + red: { value: '#f00', type: 'color' }, green: { value: { - h: "{hue}", - s: "{saturation}", - l: "{lightness}" - } - } + h: '{hue}', + s: '{saturation}', + l: '{lightness}', + }, + type: 'color', + }, }, size: { - border: { value: 0.125 } + border: { value: 0.125, type: 'dimension' }, }, border: { primary: { // getReferences should work on objects like this: value: { - color: "{color.red.value}", - width: "{size.border.value}", - style: "solid" - } + color: '{color.red.value}', + width: '{size.border.value}', + style: 'solid', + }, + type: 'border', }, }, shadow: { light: { - value: [{ - color: "{color.red.value}" - },{ - color: "{color.green.value}" - }] + value: [ + { + color: '{color.red.value}', + }, + { + color: '{color.green.value}', + }, + ], + type: 'shadow', }, dark: { - value: [{ - color: "{color.green.value}" - },{ - color: "{color.red.value}" - }] - } - } - }, - transform: { - hsl: { - type: 'value', - transitive: true, - matcher: (token) => token.original.value.h, - transformer: (token) => { - return `hsl(${token.value.h}, ${token.value.s}, ${token.value.l})` - } - }, - hslToHex: { - type: 'value', - transitive: true, - matcher: (token) => token.original.value.h, - transformer: (token) => { - return Color(`hsl(${token.value.h}, ${token.value.s}, ${token.value.l})`).toHexString(); - } + value: [ + { + color: '{color.green.value}', + }, + { + color: '{color.red.value}', + }, + ], + type: 'shadow', + }, }, - cssBorder: { - type: 'value', - transitive: true, - matcher: (token) => token.path[0] === `border`, - transformer: (token) => { - return `${token.value.width} ${token.value.style} ${token.value.color}` - } + }, + hooks: { + transforms: { + hsl: { + type: 'value', + transitive: true, + filter: (token) => token.original.value.h, + transform: (token) => { + return `hsl(${token.value.h}, ${token.value.s}, ${token.value.l})`; + }, + }, + hslToHex: { + type: 'value', + transitive: true, + filter: (token) => token.original.value.h, + transform: (token) => { + return Color( + `hsl(${token.value.h}, ${token.value.s}, ${token.value.l})`, + ).toHexString(); + }, + }, }, - shadow: { - type: 'value', - transitive: true, - matcher: (token) => token.attributes.category === 'shadow', - transformer: (token) => { - return token.value.map(obj => obj.color).join(', ') - } - } }, platforms: { // This will test to see if a value object for an hsl color works // with and without `outputReferences` cssHsl: { buildPath, - transforms: StyleDictionary.transformGroup.css.concat([`hsl`]), - files: [{ - destination: `hsl.css`, - format: `css/variables`, - filter: (token) => token.attributes.category === `color` - },{ - destination: `hslWithReferences.css`, - format: `css/variables`, - filter: (token) => token.attributes.category === `color`, - options - }] + transforms: StyleDictionary.hooks.transformGroups.css.concat([`hsl`]), + files: [ + { + destination: `hsl.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + }, + { + destination: `hslWithReferences.css`, + format: `css/variables`, + filter: (token) => token.type === `color`, + options, + }, + ], }, // This will test to see if a value object for an hsl that has been // transformed to a hex color works with and without `outputReferences` cssHex: { buildPath, - transforms: StyleDictionary.transformGroup.css.concat([`cssBorder`,`hslToHex`]), - files: [{ - destination: 'hex.css', - format: 'css/variables', - filter: (token) => token.attributes.category === `color`, - },{ - destination: 'hexWithReferences.css', - format: 'css/variables', - filter: (token) => token.attributes.category === `color`, - options - }] + transforms: StyleDictionary.hooks.transformGroups.css.concat([`hslToHex`]), + files: [ + { + destination: 'hex.css', + format: 'css/variables', + filter: (token) => token.type === `color`, + }, + { + destination: 'hexWithReferences.css', + format: 'css/variables', + filter: (token) => token.type === `color`, + options, + }, + ], }, // This will test to see if a value object for a border // works with and without `outputReferences` cssBorder: { buildPath, - transforms: StyleDictionary.transformGroup.css.concat([`cssBorder`]), - files: [{ - destination: 'border.css', - format: 'css/variables', - filter: (token) => token.attributes.category === `border`, - },{ - destination: 'borderWithReferences.css', - format: 'css/variables', - filter: (token) => token.attributes.category === `border`, - options - }] + transforms: StyleDictionary.hooks.transformGroups.css, + files: [ + { + destination: 'border.css', + format: 'css/variables', + filter: (token) => token.type === `border`, + }, + { + destination: 'borderWithReferences.css', + format: 'css/variables', + filter: (token) => token.type === `border`, + options, + }, + ], }, - cssShadow: { buildPath, - transforms: StyleDictionary.transformGroup.css.concat([`shadow`,`hslToHex`]), - files: [{ - destination: 'shadow.css', - format: 'css/variables', - filter: (token) => token.attributes.category === `shadow`, - },{ - destination: 'shadowWithReferences.css', - format: 'css/variables', - filter: (token) => token.attributes.category === `shadow`, - options - }] + transforms: StyleDictionary.hooks.transformGroups.css.concat([`hslToHex`]), + files: [ + { + destination: 'shadow.css', + format: 'css/variables', + filter: (token) => token.type === `shadow`, + }, + { + destination: 'shadowWithReferences.css', + format: 'css/variables', + filter: (token) => token.type === `shadow`, + options, + }, + ], }, scss: { buildPath, - transforms: StyleDictionary.transformGroup.css.concat([`cssBorder`,`hslToHex`]), - files: [{ - destination: 'border.scss', - format: 'scss/variables', - filter: (token) => token.attributes.category === `border`, - },{ - destination: 'borderWithReferences.scss', - format: 'scss/variables', - filter: (token) => token.attributes.category === `border`, - options - }] + transforms: StyleDictionary.hooks.transformGroups.css.concat([`hslToHex`]), + files: [ + { + destination: 'border.scss', + format: 'scss/variables', + filter: (token) => token.type === `border`, + }, + { + destination: 'borderWithReferences.scss', + format: 'scss/variables', + filter: (token) => token.type === `border`, + options, + }, + ], }, - } - }).buildAllPlatforms(); + }, + }); + await sd.buildAllPlatforms(); + }); + + afterEach(() => { + clearOutput(buildPath); + }); - describe('css/variables', () => { - describe(`hsl syntax`, () => { - const output = fs.readFileSync(`${buildPath}hsl.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('object values', async () => { + describe('css/variables', async () => { + describe(`hsl syntax`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}hsl.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}hslWithReferences.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}hslWithReferences.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); - describe(`hex syntax`, () => { - const output = fs.readFileSync(`${buildPath}hex.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`hex syntax`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}hex.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}hexWithReferences.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}hexWithReferences.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); - describe(`border`, () => { - const output = fs.readFileSync(`${buildPath}border.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`border`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}border.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}borderWithReferences.css`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}borderWithReferences.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); - describe('shadow', () => { - it(`should match snapshot`, () => { - const output = fs.readFileSync(`${buildPath}shadow.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + describe('shadow', async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}shadow.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`should match snapshot with references`, () => { - const output = fs.readFileSync(`${buildPath}shadowWithReferences.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`should match snapshot with references`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}shadowWithReferences.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - }) + }); }); - describe('scss/variables', () => { - const output = fs.readFileSync(`${buildPath}border.scss`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('scss/variables', async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}border.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}borderWithReferences.scss`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}borderWithReferences.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/outputReferences.test.js b/__integration__/outputReferences.test.js index 552c1608e..917ef8ad6 100644 --- a/__integration__/outputReferences.test.js +++ b/__integration__/outputReferences.test.js @@ -10,43 +10,171 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { restore, stubMethod } from 'hanbi'; +import { buildPath, cleanConsoleOutput } from './_constants.js'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { clearOutput } from '../__tests__/__helpers.js'; +import { outputReferencesFilter } from '../dist/esm/utils/references/outputReferencesFilter.mjs'; +import { outputReferencesTransformed } from 'style-dictionary/utils'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); +describe('integration', async () => { + let stub; + beforeEach(() => { + stub = stubMethod(console, 'log'); + }); + + afterEach(() => { + clearOutput(buildPath); + restore(); + }); + + describe('output references', async () => { + it('should allow using outputReferencesTransformed to not output refs when value has been transitively transformed', async () => { + restore(); + const sd = new StyleDictionary({ + tokens: { + base: { + value: 'rgb(0,0,0)', + type: 'color', + }, + referred: { + value: 'rgba({base},0.12)', + type: 'color', + }, + }, + hooks: { + transforms: { + 'rgb-in-rgba': { + type: 'value', + transitive: true, + filter: (token) => token.type === 'color', + // quite naive transform to support rgb inside rgba + transform: (token) => { + const reg = /rgba\((rgb\((\d,\d,\d)\)),((0\.)?\d+?)\)/g; + const match = reg.exec(token.value); + if (match && match[1] && match[2]) { + return token.value.replace(match[1], match[2]); + } + return token.value; + }, + }, + }, + }, + platforms: { + css: { + transforms: ['rgb-in-rgba'], + buildPath, + files: [ + { + destination: 'transformedFilteredVariables.css', + format: 'css/variables', + options: { + outputReferences: outputReferencesTransformed, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + const output = fs.readFileSync(resolve(`${buildPath}transformedFilteredVariables.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); + }); + + it('should warn the user if filters out references briefly', async () => { + const sd = new StyleDictionary({ + // we are only testing showFileHeader options so we don't need + // the full source. + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: 'css', + buildPath, + files: [ + { + destination: 'filteredVariables.css', + format: 'css/variables', + // filter tokens and use outputReferences + // Style Dictionary should build this file ok + // but warn the user + filter: (token) => token.attributes.type === 'background', + options: { + outputReferences: true, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + await expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.matchSnapshot(); + }); -describe('integration', () => { - describe('output references', () => { - it('should warn the user if filters out references', () => { - console.log = jest.fn(); - StyleDictionary.extend({ + it('should not warn the user if filters out references is prevented with outputReferencesFilter', async () => { + const sd = new StyleDictionary({ // we are only testing showFileHeader options so we don't need // the full source. - source: [`__integration__/tokens/**/*.json?(c)`], + log: { verbosity: 'verbose' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { transformGroup: 'css', buildPath, - files: [{ - destination: 'filteredVariables.css', - format: 'css/variables', - // filter tokens and use outputReferences - // Style Dictionary should build this file ok - // but warn the user - filter: (token) => token.attributes.type === 'background', - options: { - outputReferences: true - } - }] - } - } - }).buildAllPlatforms(); + files: [ + { + destination: 'filteredVariables.css', + format: 'css/variables', + // filter tokens and use outputReferences + // Style Dictionary should build this file ok + // but warn the user + filter: (token) => token.attributes.type === 'background', + options: { + outputReferences: outputReferencesFilter, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + await expect( + [...stub.calls].map((cal) => cal.args.map(cleanConsoleOutput)).join('\n'), + ).to.matchSnapshot(); + }); - expect(console.log).toHaveBeenCalledWith(`⚠️ ${buildPath}filteredVariables.css`); + it('should warn the user if filters out references with a detailed message when using verbose logging', async () => { + const sd = new StyleDictionary({ + log: { verbosity: 'verbose' }, + // we are only testing showFileHeader options so we don't need + // the full source. + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: 'css', + buildPath, + files: [ + { + destination: 'filteredVariables.css', + format: 'css/variables', + // filter tokens and use outputReferences + // Style Dictionary should build this file ok + // but warn the user + filter: (token) => token.attributes.type === 'background', + options: { + outputReferences: true, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + await expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.matchSnapshot(); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/scss.test.js b/__integration__/scss.test.js index c013bd8fe..e799316ba 100644 --- a/__integration__/scss.test.js +++ b/__integration__/scss.test.js @@ -10,181 +10,220 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const scss = require('node-sass'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe(`integration`, () => { - describe(`scss`, () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { compileString } from 'sass'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; + +describe(`integration`, async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { transformGroup: `scss`, buildPath, - files: [{ - destination: `variables.scss`, - format: `scss/variables` - }, - { - destination: `variables-themeable.scss`, - format: `scss/variables`, - options: { - themeable: true - } - }, { - destination: `variables-with-references.scss`, - format: `scss/variables`, - options: { - outputReferences: true - } - },{ - destination: `filtered-variables-with-references.scss`, - format: `scss/variables`, - filter: (token) => token.path[1] === 'background', - options: { - outputReferences: true - } - },{ - destination: `map-flat.scss`, - format: `scss/map-flat`, - mapName: 'design-system-tokens' - },{ - destination: `map-deep.scss`, - format: `scss/map-deep`, - mapName: 'design-system-tokens' - },{ - destination: `map-deep-with-references.scss`, - format: `scss/map-deep`, - mapName: 'design-system-tokens', - options: { - outputReferences: true - } - },{ - destination: `map-deep-not-themeable.scss`, - format: `scss/map-deep`, - mapName: 'design-system-tokens', - options: { - themeable: false - } - }] - } - } - }).buildAllPlatforms(); - - describe(`scss/variables`, () => { - const output = fs.readFileSync(`${buildPath}variables.scss`, {encoding:'UTF-8'}); + files: [ + { + destination: `variables.scss`, + format: `scss/variables`, + }, + { + destination: `variables-themeable.scss`, + format: `scss/variables`, + options: { + themeable: true, + }, + }, + { + destination: `variables-with-references.scss`, + format: `scss/variables`, + options: { + outputReferences: true, + }, + }, + { + destination: `filtered-variables-with-references.scss`, + format: `scss/variables`, + filter: (token) => token.path[1] === 'background', + options: { + outputReferences: true, + }, + }, + { + destination: `map-flat.scss`, + format: `scss/map-flat`, + options: { + mapName: 'design-system-tokens', + }, + }, + { + destination: `map-deep.scss`, + format: `scss/map-deep`, + options: { + mapName: 'design-system-tokens', + }, + }, + { + destination: `map-deep-with-references.scss`, + format: `scss/map-deep`, + options: { + mapName: 'design-system-tokens', + outputReferences: true, + }, + }, + { + destination: `map-deep-not-themeable.scss`, + format: `scss/map-deep`, + options: { + mapName: 'design-system-tokens', + themeable: false, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); + afterEach(() => { + clearOutput(buildPath); + }); + + describe(`scss`, async () => { + describe(`scss/variables`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}variables.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variables.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with themeable`, () => { - const output = fs.readFileSync(`${buildPath}variables-themeable.scss`, {encoding:'UTF-8'}); + describe(`with themeable`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}variables-themeable.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variables-themeable.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe(`with outputReferences`, () => { - const output = fs.readFileSync(`${buildPath}variables-with-references.scss`, {encoding:'UTF-8'}); + describe(`with outputReferences`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}variables-with-references.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}variables-with-references.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe(`with filter and output references`, () => { - const output = fs.readFileSync(`${buildPath}filtered-variables-with-references.scss`, {encoding:'UTF-8'}); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with filter and output references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync( + resolve(`${buildPath}filtered-variables-with-references.scss`), + { + encoding: 'UTF-8', + }, + ); + await expect(output).to.matchSnapshot(); }); }); }); - describe(`scss/map-flat`, () => { - const output = fs.readFileSync(`${buildPath}map-flat.scss`, {encoding:'UTF-8'}); - + describe(`scss/map-flat`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}map-flat.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}map-flat.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe(`scss/map-deep`, () => { - const output = fs.readFileSync(`${buildPath}map-deep.scss`, {encoding:'UTF-8'}); - + describe(`scss/map-deep`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}map-deep.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}map-deep.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - describe(`with outputReferences`, () => { - const output = fs.readFileSync(`${buildPath}map-deep-with-references.scss`, { encoding: 'UTF-8' }); + describe(`with outputReferences`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}map-deep-with-references.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}map-deep-with-references.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe(`without themeable`, () => { - const output = fs.readFileSync(`${buildPath}map-deep-not-themeable.scss`, { encoding: 'UTF-8' }); + describe(`without themeable`, async () => { it(`should have a valid scss syntax`, () => { - const result = scss.renderSync({ - data: output, + const output = fs.readFileSync(resolve(`${buildPath}map-deep-not-themeable.scss`), { + encoding: 'UTF-8', }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}map-deep-not-themeable.scss`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); diff --git a/__integration__/showFileHeader.test.js b/__integration__/showFileHeader.test.js index 8459bef30..d75f94647 100644 --- a/__integration__/showFileHeader.test.js +++ b/__integration__/showFileHeader.test.js @@ -10,14 +10,16 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('showFileHeader', () => { - StyleDictionary.extend({ +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ // we are only testing showFileHeader options so we don't need // the full source. source: [`__integration__/tokens/size/padding.json`], @@ -25,63 +27,80 @@ describe('integration', () => { css: { transformGroup: 'css', buildPath, - files: [{ - destination: 'platform-none-file-none.css', - format: 'css/variables' - },{ - destination: 'platform-none-file-false.css', - format: 'css/variables', - options: { - showFileHeader: false - } - }] + files: [ + { + destination: 'platform-none-file-none.css', + format: 'css/variables', + }, + { + destination: 'platform-none-file-false.css', + format: 'css/variables', + options: { + showFileHeader: false, + }, + }, + ], }, fileHeader: { transformGroup: 'css', buildPath, options: { - showFileHeader: false + showFileHeader: false, }, - files: [{ - destination: 'platform-false-file-none.css', - format: 'css/variables' - },{ - destination: 'platform-false-file-true.css', - format: 'css/variables', - options: { - showFileHeader: true - } - }] - } - } - }).buildAllPlatforms(); + files: [ + { + destination: 'platform-false-file-none.css', + format: 'css/variables', + }, + { + destination: 'platform-false-file-true.css', + format: 'css/variables', + options: { + showFileHeader: true, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); - describe(`without platform options`, () => { - it(`should show file header if no file options set`, () => { - const output = fs.readFileSync(`${buildPath}platform-none-file-none.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + afterEach(() => { + clearOutput(buildPath); + }); + + describe('showFileHeader', async () => { + describe(`without platform options`, async () => { + it(`should show file header if no file options set`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}platform-none-file-none.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`should not show file header if file options set to false`, () => { - const output = fs.readFileSync(`${buildPath}platform-none-file-false.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`should not show file header if file options set to false`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}platform-none-file-false.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); - describe(`with platform options set to false`, () => { - it(`should not show file header if no file options set`, () => { - const output = fs.readFileSync(`${buildPath}platform-false-file-none.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + describe(`with platform options set to false`, async () => { + it(`should not show file header if no file options set`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}platform-false-file-none.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); - it(`should show file header if file options set to true`, () => { - const output = fs.readFileSync(`${buildPath}platform-false-file-true.css`, {encoding:'UTF-8'}); - expect(output).toMatchSnapshot(); + it(`should show file header if file options set to true`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}platform-false-file-true.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/swift.test.js b/__integration__/swift.test.js index 6e5b103e2..2458edf32 100644 --- a/__integration__/swift.test.js +++ b/__integration__/swift.test.js @@ -10,61 +10,68 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; -const fs = require('fs-extra'); -const StyleDictionary = require('../index'); -const {buildPath} = require('./_constants'); - -describe('integration', () => { - describe('swift', () => { - StyleDictionary.extend({ - source: [`__integration__/tokens/**/*.json?(c)`], +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { flutter: { transformGroup: `ios-swift`, buildPath, - files: [{ - destination: "style_dictionary.swift", - format: "ios-swift/class.swift", - className: "StyleDictionary" - },{ - destination: "style_dictionary_with_references.swift", - format: "ios-swift/class.swift", - className: "StyleDictionary", - options: { - outputReferences: true - } - }] + files: [ + { + destination: 'style_dictionary.swift', + format: 'ios-swift/class.swift', + options: { + className: 'StyleDictionary', + }, + }, + { + destination: 'style_dictionary_with_references.swift', + format: 'ios-swift/class.swift', + options: { + className: 'StyleDictionary', + outputReferences: true, + }, + }, + ], }, - } - }).buildAllPlatforms(); + }, + }); + await sd.buildAllPlatforms(); + }); - describe(`ios-swift/class.swift`, () => { - const output = fs.readFileSync(`${buildPath}style_dictionary.swift`, {encoding:`UTF-8`}); + afterEach(() => { + clearOutput(buildPath); + }); - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe('swift', async () => { + describe(`ios-swift/class.swift`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}style_dictionary.swift`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); }); - describe(`with references`, () => { - const output = fs.readFileSync(`${buildPath}style_dictionary_with_references.swift`, {encoding:`UTF-8`}); - - it(`should match snapshot`, () => { - expect(output).toMatchSnapshot(); + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync( + resolve(`${buildPath}style_dictionary_with_references.swift`), + { + encoding: `UTF-8`, + }, + ); + await expect(output).to.matchSnapshot(); }); - }); - - // describe(`separate`, () => { - // const output = fs.readFileSync(`${buildPath}style_dictionary_color.dart`); - // it(`should match snapshot`, () => { - // expect(output).toMatchSnapshot(); - // }); - // }); }); }); }); - -afterAll(() => { - fs.emptyDirSync(buildPath); -}); \ No newline at end of file diff --git a/__integration__/tokens/color/background.json b/__integration__/tokens/color/background.json index 066b22fbb..ba1040129 100644 --- a/__integration__/tokens/color/background.json +++ b/__integration__/tokens/color/background.json @@ -1,14 +1,14 @@ { "color": { "background": { - "primary": { "value": "{color.core.neutral.0.value}", "themeable": true }, - "secondary": { "value": "{color.core.neutral.100.value}" }, - "tertiary": { "value": "{color.core.neutral.200.value}" }, - "danger": { "value": "{color.core.red.0.value}" }, - "warning": { "value": "{color.core.orange.0.value}" }, - "success": { "value": "{color.core.green.0.value}" }, - "info": { "value": "{color.core.blue.0.value}" }, - "disabled": { "value": "{color.background.tertiary.value}" } + "primary": { "value": "{color.core.neutral.0.value}", "type": "color", "themeable": true }, + "secondary": { "value": "{color.core.neutral.100.value}", "type": "color" }, + "tertiary": { "value": "{color.core.neutral.200.value}", "type": "color" }, + "danger": { "value": "{color.core.red.0.value}", "type": "color" }, + "warning": { "value": "{color.core.orange.0.value}", "type": "color" }, + "success": { "value": "{color.core.green.0.value}", "type": "color" }, + "info": { "value": "{color.core.blue.0.value}", "type": "color" }, + "disabled": { "value": "{color.background.tertiary.value}", "type": "color" } } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/color/border.json b/__integration__/tokens/color/border.json index c344aae51..41ff3ed06 100644 --- a/__integration__/tokens/color/border.json +++ b/__integration__/tokens/color/border.json @@ -1,9 +1,9 @@ { "color": { "border": { - "primary": { "value": "{color.core.neutral.300.value}" }, + "primary": { "value": "{color.core.neutral.300.value}", "type": "color" }, "secondary": {}, "tertiary": {} } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/color/brand.json b/__integration__/tokens/color/brand.json index 66cde45ce..9e1ab032b 100644 --- a/__integration__/tokens/color/brand.json +++ b/__integration__/tokens/color/brand.json @@ -2,12 +2,14 @@ "color": { "brand": { "primary": { - "value": "{color.core.aqua.700.value}" + "value": "{color.core.aqua.700.value}", + "type": "color" }, - + "secondary": { - "value": "{color.core.purple.700.value}" + "value": "{color.core.purple.700.value}", + "type": "color" } } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/color/core.json b/__integration__/tokens/color/core.json index e3294792a..c5c330f56 100644 --- a/__integration__/tokens/color/core.json +++ b/__integration__/tokens/color/core.json @@ -2,169 +2,169 @@ "color": { "core": { "green": { - "0": { "value": "#ebf9eb" }, - "100" : { "value": "#d7f4d7" }, - "200" : { "value": "#c2f2bd" }, - "300" : { "value": "#98e58e" }, - "400" : { "value": "#75dd66" }, - "500" : { "value": "#59cb59" }, - "600" : { "value": "#2bb656" }, - "700" : { "value": "#0ca750" }, - "800" : { "value": "#008b46" }, - "900" : { "value": "#006b40" }, - "1000" : { "value": "#08422f" }, - "1100" : { "value": "#002b20" } + "0": { "value": "#ebf9eb", "type": "color" }, + "100": { "value": "#d7f4d7", "type": "color" }, + "200": { "value": "#c2f2bd", "type": "color" }, + "300": { "value": "#98e58e", "type": "color" }, + "400": { "value": "#75dd66", "type": "color" }, + "500": { "value": "#59cb59", "type": "color" }, + "600": { "value": "#2bb656", "type": "color" }, + "700": { "value": "#0ca750", "type": "color" }, + "800": { "value": "#008b46", "type": "color" }, + "900": { "value": "#006b40", "type": "color" }, + "1000": { "value": "#08422f", "type": "color" }, + "1100": { "value": "#002b20", "type": "color" } }, - + "teal": { - "0": { "value": "#e5f9f5" }, - "100" : { "value": "#cdf7ef" }, - "200" : { "value": "#b3f2e6" }, - "300" : { "value": "#7dead5" }, - "400" : { "value": "#24e0c5" }, - "500" : { "value": "#08c4b2" }, - "600" : { "value": "#00a99c" }, - "700" : { "value": "#0b968f" }, - "800" : { "value": "#067c7c" }, - "900" : { "value": "#026661" }, - "1000" : { "value": "#083f3f" }, - "1100" : { "value": "#002528" } + "0": { "value": "#e5f9f5", "type": "color" }, + "100": { "value": "#cdf7ef", "type": "color" }, + "200": { "value": "#b3f2e6", "type": "color" }, + "300": { "value": "#7dead5", "type": "color" }, + "400": { "value": "#24e0c5", "type": "color" }, + "500": { "value": "#08c4b2", "type": "color" }, + "600": { "value": "#00a99c", "type": "color" }, + "700": { "value": "#0b968f", "type": "color" }, + "800": { "value": "#067c7c", "type": "color" }, + "900": { "value": "#026661", "type": "color" }, + "1000": { "value": "#083f3f", "type": "color" }, + "1100": { "value": "#002528", "type": "color" } }, - + "aqua": { - "0": { "value": "#d9fcfb" }, - "100" : { "value": "#c5f9f9" }, - "200" : { "value": "#a5f2f2" }, - "300" : { "value": "#76e5e2" }, - "400" : { "value": "#33d6e2" }, - "500" : { "value": "#17b8ce" }, - "600" : { "value": "#0797ae" }, - "700" : { "value": "#0b8599" }, - "800" : { "value": "#0f6e84" }, - "900" : { "value": "#035e73" }, - "1000" : { "value": "#083d4f" }, - "1100" : { "value": "#002838" } + "0": { "value": "#d9fcfb", "type": "color" }, + "100": { "value": "#c5f9f9", "type": "color" }, + "200": { "value": "#a5f2f2", "type": "color" }, + "300": { "value": "#76e5e2", "type": "color" }, + "400": { "value": "#33d6e2", "type": "color" }, + "500": { "value": "#17b8ce", "type": "color" }, + "600": { "value": "#0797ae", "type": "color" }, + "700": { "value": "#0b8599", "type": "color" }, + "800": { "value": "#0f6e84", "type": "color" }, + "900": { "value": "#035e73", "type": "color" }, + "1000": { "value": "#083d4f", "type": "color" }, + "1100": { "value": "#002838", "type": "color" } }, - + "blue": { - "0": { "value": "#e9f8ff" }, - "100" : { "value": "#dcf2ff" }, - "200" : { "value": "#c7e4f9" }, - "300" : { "value": "#a1d2f8" }, - "400" : { "value": "#56adf5" }, - "500" : { "value": "#3896e3" }, - "600" : { "value": "#2b87d3" }, - "700" : { "value": "#2079c3" }, - "800" : { "value": "#116daa" }, - "900" : { "value": "#0c5689" }, - "1000" : { "value": "#0a3960" }, - "1100" : { "value": "#002138" } + "0": { "value": "#e9f8ff", "type": "color" }, + "100": { "value": "#dcf2ff", "type": "color" }, + "200": { "value": "#c7e4f9", "type": "color" }, + "300": { "value": "#a1d2f8", "type": "color" }, + "400": { "value": "#56adf5", "type": "color" }, + "500": { "value": "#3896e3", "type": "color" }, + "600": { "value": "#2b87d3", "type": "color" }, + "700": { "value": "#2079c3", "type": "color" }, + "800": { "value": "#116daa", "type": "color" }, + "900": { "value": "#0c5689", "type": "color" }, + "1000": { "value": "#0a3960", "type": "color" }, + "1100": { "value": "#002138", "type": "color" } }, - + "purple": { - "0": { "value": "#f2f2f9" }, - "100" : { "value": "#eaeaf9" }, - "200" : { "value": "#d8d7f9" }, - "300" : { "value": "#c1c1f7" }, - "400" : { "value": "#a193f2" }, - "500" : { "value": "#9180f4" }, - "600" : { "value": "#816fea" }, - "700" : { "value": "#6f5ed3" }, - "800" : { "value": "#5e4eba" }, - "900" : { "value": "#483a9c" }, - "1000" : { "value": "#2d246b" }, - "1100" : { "value": "#1d1d38" } + "0": { "value": "#f2f2f9", "type": "color" }, + "100": { "value": "#eaeaf9", "type": "color" }, + "200": { "value": "#d8d7f9", "type": "color" }, + "300": { "value": "#c1c1f7", "type": "color" }, + "400": { "value": "#a193f2", "type": "color" }, + "500": { "value": "#9180f4", "type": "color" }, + "600": { "value": "#816fea", "type": "color" }, + "700": { "value": "#6f5ed3", "type": "color" }, + "800": { "value": "#5e4eba", "type": "color" }, + "900": { "value": "#483a9c", "type": "color" }, + "1000": { "value": "#2d246b", "type": "color" }, + "1100": { "value": "#1d1d38", "type": "color" } }, - + "magenta": { - "0": { "value": "#fef0ff" }, - "100" : { "value": "#f9e3fc" }, - "200" : { "value": "#f4c4f7" }, - "300" : { "value": "#edadf2" }, - "400" : { "value": "#f282f5" }, - "500" : { "value": "#db61db" }, - "600" : { "value": "#c44eb9" }, - "700" : { "value": "#ac44a8" }, - "800" : { "value": "#8f3896" }, - "900" : { "value": "#6c2277" }, - "1000" : { "value": "#451551" }, - "1100" : { "value": "#29192d" } + "0": { "value": "#fef0ff", "type": "color" }, + "100": { "value": "#f9e3fc", "type": "color" }, + "200": { "value": "#f4c4f7", "type": "color" }, + "300": { "value": "#edadf2", "type": "color" }, + "400": { "value": "#f282f5", "type": "color" }, + "500": { "value": "#db61db", "type": "color" }, + "600": { "value": "#c44eb9", "type": "color" }, + "700": { "value": "#ac44a8", "type": "color" }, + "800": { "value": "#8f3896", "type": "color" }, + "900": { "value": "#6c2277", "type": "color" }, + "1000": { "value": "#451551", "type": "color" }, + "1100": { "value": "#29192d", "type": "color" } }, - + "pink": { - "0": { "value": "#ffe9f3" }, - "100" : { "value": "#fcdbeb" }, - "200" : { "value": "#ffb5d5" }, - "300" : { "value": "#ff95c1" }, - "400" : { "value": "#ff76ae" }, - "500" : { "value": "#ef588b" }, - "600" : { "value": "#e0447c" }, - "700" : { "value": "#ce3665" }, - "800" : { "value": "#b22f5b" }, - "900" : { "value": "#931847" }, - "1000" : { "value": "#561231" }, - "1100" : { "value": "#2b1721" } + "0": { "value": "#ffe9f3", "type": "color" }, + "100": { "value": "#fcdbeb", "type": "color" }, + "200": { "value": "#ffb5d5", "type": "color" }, + "300": { "value": "#ff95c1", "type": "color" }, + "400": { "value": "#ff76ae", "type": "color" }, + "500": { "value": "#ef588b", "type": "color" }, + "600": { "value": "#e0447c", "type": "color" }, + "700": { "value": "#ce3665", "type": "color" }, + "800": { "value": "#b22f5b", "type": "color" }, + "900": { "value": "#931847", "type": "color" }, + "1000": { "value": "#561231", "type": "color" }, + "1100": { "value": "#2b1721", "type": "color" } }, - + "red": { - "0": { "value": "#ffeae9" }, - "100" : { "value": "#ffd5d2" }, - "200" : { "value": "#ffb8b1" }, - "300" : { "value": "#ff9c8f" }, - "400" : { "value": "#ff7f6e" }, - "500" : { "value": "#f76054" }, - "600" : { "value": "#ed4c42" }, - "700" : { "value": "#db3e3e" }, - "800" : { "value": "#c63434" }, - "900" : { "value": "#992222" }, - "1000" : { "value": "#6d1313" }, - "1100" : { "value": "#2b1111" } + "0": { "value": "#ffeae9", "type": "color" }, + "100": { "value": "#ffd5d2", "type": "color" }, + "200": { "value": "#ffb8b1", "type": "color" }, + "300": { "value": "#ff9c8f", "type": "color" }, + "400": { "value": "#ff7f6e", "type": "color" }, + "500": { "value": "#f76054", "type": "color" }, + "600": { "value": "#ed4c42", "type": "color" }, + "700": { "value": "#db3e3e", "type": "color" }, + "800": { "value": "#c63434", "type": "color" }, + "900": { "value": "#992222", "type": "color" }, + "1000": { "value": "#6d1313", "type": "color" }, + "1100": { "value": "#2b1111", "type": "color" } }, - + "orange": { - "0": { "value": "#ffede3" }, - "100" : { "value": "#fcdccc" }, - "200" : { "value": "#ffc6a4" }, - "300" : { "value": "#ffb180" }, - "400" : { "value": "#ff9c5d" }, - "500" : { "value": "#fc8943" }, - "600" : { "value": "#f57d33" }, - "700" : { "value": "#ed7024" }, - "800" : { "value": "#ce5511" }, - "900" : { "value": "#962c0b" }, - "1000" : { "value": "#601700" }, - "1100" : { "value": "#2d130e" } + "0": { "value": "#ffede3", "type": "color" }, + "100": { "value": "#fcdccc", "type": "color" }, + "200": { "value": "#ffc6a4", "type": "color" }, + "300": { "value": "#ffb180", "type": "color" }, + "400": { "value": "#ff9c5d", "type": "color" }, + "500": { "value": "#fc8943", "type": "color" }, + "600": { "value": "#f57d33", "type": "color" }, + "700": { "value": "#ed7024", "type": "color" }, + "800": { "value": "#ce5511", "type": "color" }, + "900": { "value": "#962c0b", "type": "color" }, + "1000": { "value": "#601700", "type": "color" }, + "1100": { "value": "#2d130e", "type": "color" } }, - + "neutral": { - "0" : { "value": "#FFFFFF" }, - "100" : { "value": "#f3f4f4" }, - "200" : { "value": "#dee1e1" }, - "300" : { "value": "#c8cccc" }, - "400" : { "value": "#b0b6b7" }, - "500" : { "value": "#929a9b" }, - "600" : { "value": "#6e797a" }, - "700" : { "value": "#515e5f" }, - "800" : { "value": "#364141" }, - "900" : { "value": "#273333" }, - "1000" : { "value": "#162020" }, - "1100" : { "value": "#040404" } + "0": { "value": "#FFFFFF", "type": "color" }, + "100": { "value": "#f3f4f4", "type": "color" }, + "200": { "value": "#dee1e1", "type": "color" }, + "300": { "value": "#c8cccc", "type": "color" }, + "400": { "value": "#b0b6b7", "type": "color" }, + "500": { "value": "#929a9b", "type": "color" }, + "600": { "value": "#6e797a", "type": "color" }, + "700": { "value": "#515e5f", "type": "color" }, + "800": { "value": "#364141", "type": "color" }, + "900": { "value": "#273333", "type": "color" }, + "1000": { "value": "#162020", "type": "color" }, + "1100": { "value": "#040404", "type": "color" } }, - + "yellow": { - "0": { "value": "#fff8e2" }, - "100" : { "value": "#fdefcd" }, - "200" : { "value": "#ffe99a" }, - "300" : { "value": "#ffe16e" }, - "400" : { "value": "#ffd943" }, - "500" : { "value": "#ffcd1c" }, - "600" : { "value": "#ffbc00" }, - "700" : { "value": "#dd9903" }, - "800" : { "value": "#ba7506" }, - "900" : { "value": "#944c0c" }, - "1000" : { "value": "#542a00" }, - "1100" : { "value": "#2d1a05" } + "0": { "value": "#fff8e2", "type": "color" }, + "100": { "value": "#fdefcd", "type": "color" }, + "200": { "value": "#ffe99a", "type": "color" }, + "300": { "value": "#ffe16e", "type": "color" }, + "400": { "value": "#ffd943", "type": "color" }, + "500": { "value": "#ffcd1c", "type": "color" }, + "600": { "value": "#ffbc00", "type": "color" }, + "700": { "value": "#dd9903", "type": "color" }, + "800": { "value": "#ba7506", "type": "color" }, + "900": { "value": "#944c0c", "type": "color" }, + "1000": { "value": "#542a00", "type": "color" }, + "1100": { "value": "#2d1a05", "type": "color" } } } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/color/font.jsonc b/__integration__/tokens/color/font.jsonc index cfa6fed10..ff99069e6 100644 --- a/__integration__/tokens/color/font.jsonc +++ b/__integration__/tokens/color/font.jsonc @@ -1,21 +1,21 @@ { "color": { "font": { - "primary": { "value": "{color.core.neutral.1100.value}" }, - "secondary": { "value": "{color.core.neutral.900.value}" }, - "tertiary": { "value": "{color.core.neutral.800.value}" }, + "primary": { "value": "{color.core.neutral.1100.value}", "type": "color" }, + "secondary": { "value": "{color.core.neutral.900.value}", "type": "color" }, + "tertiary": { "value": "{color.core.neutral.800.value}", "type": "color" }, "interactive": { - "_": { "value": "{color.brand.primary.value}" }, - "hover": { "value": "{color.brand.primary.value}" }, - "active": { "value": "{color.brand.secondary.value}" }, - "disabled": { "value": "{color.font.tertiary.value}" } + "_": { "value": "{color.brand.primary.value}", "type": "color" }, + "hover": { "value": "{color.brand.primary.value}", "type": "color" }, + "active": { "value": "{color.brand.secondary.value}", "type": "color" }, + "disabled": { "value": "{color.font.tertiary.value}", "type": "color" } }, - "danger": { "value": "{color.core.red.1000.value}" }, - "warning": { "value": "{color.core.orange.1000.value}" }, + "danger": { "value": "{color.core.red.1000.value}", "type": "color" }, + "warning": { "value": "{color.core.orange.1000.value}", "type": "color" }, // make sure references without .value work too - "success": { "value": "{color.core.green.1000}" } + "success": { "value": "{color.core.green.1000}", "type": "color" } } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/size/_padding.json b/__integration__/tokens/size/_padding.json new file mode 100644 index 000000000..f000f8c17 --- /dev/null +++ b/__integration__/tokens/size/_padding.json @@ -0,0 +1,10 @@ +{ + "size": { + "padding": { + "small": { "value": 0.5, "type": "dimension" }, + "medium": { "value": 1, "type": "dimension" }, + "large": { "value": 1, "type": "dimension" }, + "xl": { "value": 1, "type": "dimension" } + } + } +} diff --git a/__integration__/tokens/size/border.json b/__integration__/tokens/size/border.json index d70a7cd0c..1829b447e 100644 --- a/__integration__/tokens/size/border.json +++ b/__integration__/tokens/size/border.json @@ -2,8 +2,8 @@ "size": { "border": { "radius": { - "large": { "value": 30 } + "large": { "value": 30, "type": "dimension" } } } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/size/font.json b/__integration__/tokens/size/font.json index 3056392aa..8644337e4 100644 --- a/__integration__/tokens/size/font.json +++ b/__integration__/tokens/size/font.json @@ -1,10 +1,10 @@ { "size": { "font": { - "small": { "value": 0.75 }, - "medium": { "value": 1 }, - "large": { "value": 1.5 }, - "xl": { "value": 2.25 } + "small": { "value": 0.75, "type": "fontSize" }, + "medium": { "value": 1, "type": "fontSize" }, + "large": { "value": 1.5, "type": "fontSize" }, + "xl": { "value": 2.25, "type": "fontSize" } } } -} \ No newline at end of file +} diff --git a/__integration__/tokens/size/padding.json b/__integration__/tokens/size/padding.json index 6d2358d71..f000f8c17 100644 --- a/__integration__/tokens/size/padding.json +++ b/__integration__/tokens/size/padding.json @@ -1,10 +1,10 @@ { "size": { "padding": { - "small": { "value": 0.5 }, - "medium": { "value": 1 }, - "large": { "value": 1 }, - "xl": { "value": 1 } + "small": { "value": 0.5, "type": "dimension" }, + "medium": { "value": 1, "type": "dimension" }, + "large": { "value": 1, "type": "dimension" }, + "xl": { "value": 1, "type": "dimension" } } } -} \ No newline at end of file +} diff --git a/__integration__/w3c-forward-compat.test.js b/__integration__/w3c-forward-compat.test.js new file mode 100644 index 000000000..e3cddf729 --- /dev/null +++ b/__integration__/w3c-forward-compat.test.js @@ -0,0 +1,98 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import Color from 'tinycolor2'; +import { resolve } from '../dist/esm/resolve.mjs'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; + +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + tokens: { + colors: { + $type: 'color', // $type should be inherited by the children + black: { + 500: { + $value: '#000000', // $value should work + value: {}, // should be allowed as $ prop takes precedence -> bad practice though + type: 'dimension', // should be allowed as the inherited $type takes precedence -> bad practice though + }, + dimension: { + $value: '5', + value: 'something else', // should be allowed as $ prop takes precedence -> bad practice though + $type: 'dimension', + type: 'color', // should be allowed as $ prop takes precedence -> bad practice though + $description: 'Some description', + }, + }, + foo: { + $value: '{colors.black.500}', + }, + }, + }, + hooks: { + transforms: { + 'custom/css/color': { + type: 'value', + filter: (token) => token.$type === 'color', + transform: (token) => { + return Color(sd.usesDtcg ? token.$value : token.value).toRgbString(); + }, + }, + 'custom/add/px': { + type: 'value', + filter: (token) => token.$type === 'dimension', + transform: (token) => { + return `${sd.usesDtcg ? token.$value : token.value}px`; + }, + }, + }, + }, + platforms: { + css: { + transforms: ['name/kebab', 'custom/css/color', 'custom/add/px'], + buildPath, + files: [ + { + destination: 'vars.css', + format: 'css/variables', + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); + + afterEach(() => { + clearOutput(buildPath); + }); + + /** + * Integration test for forward compatibility with https://design-tokens.github.io/community-group/format/ + * - $value special property + * - $type special property & inherits from ancestors + * - $description special property + */ + describe('DTCG draft spec forward compatibility', async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}vars.css`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); + }); + }); +}); diff --git a/__node_tests__/cliBuild.test.js b/__node_tests__/cliBuild.test.js new file mode 100644 index 000000000..cff765c6a --- /dev/null +++ b/__node_tests__/cliBuild.test.js @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import childProcess from 'child_process'; +import fs from 'node:fs'; +import { clearOutput, fileExists } from '../__tests__/__helpers.js'; + +describe('cliBuildWithJsConfig', () => { + beforeEach(() => { + clearOutput(undefined, fs); + }); + + afterEach(() => { + clearOutput(); + }); + + it('should work with json config', () => { + childProcess.execSync('node ./bin/style-dictionary build --config __tests__/__configs/test.js'); + expect(fileExists('__tests__/__output/web/_icons.css', fs)).to.be.true; + expect(fileExists('__tests__/__output/android/colors.xml', fs)).to.be.true; + }); + + it('should work with javascript config', () => { + childProcess.execSync('node ./bin/style-dictionary build --config __tests__/__configs/test.js'); + expect(fileExists('__tests__/__output/web/_icons.css', fs)).to.be.true; + expect(fileExists('__tests__/__output/android/colors.xml', fs)).to.be.true; + }); + + describe('logging args', () => { + it('should not log anything if --silent is used', () => { + const result = childProcess.execSync( + 'node ./bin/style-dictionary build --config __tests__/__configs/test.js --silent', + ); + expect(result.toString()).to.equal(``); + }); + + it('should only log success logs if --no-warn is used', () => { + const result = childProcess.execSync( + 'node ./bin/style-dictionary build --config __tests__/__configs/test.js --no-warn', + ); + + expect(result.toString().match('Token collisions detected')).to.be.null; + }); + + it('should log briefly if neither --verbose nor --silent is used', () => { + //const logStub = stubMethod(console, 'log'); + const result = childProcess.execSync( + 'node ./bin/style-dictionary build --config __tests__/__configs/tokenCollisions.json', + ); + expect(result.toString()).to.equal(` +css +⚠️ __tests__/__output/css/vars.css +While building vars.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.\n`); + }); + + it('should log verbosely if --verbose is used', () => { + //const logStub = stubMethod(console, 'log'); + const result = childProcess.execSync( + 'node ./bin/style-dictionary build --config __tests__/__configs/tokenCollisions.json --verbose', + ); + expect(result.toString()).to.equal(` +css +⚠️ __tests__/__output/css/vars.css +While building vars.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + Output name red was generated by: + color.red #f00 + color.background.red #f00 +This many-to-one issue is usually caused by some combination of: + * conflicting or similar paths/names in token definitions + * platform transforms/transformGroups affecting names, especially when removing specificity + * overly inclusive file filters\n`); + }); + }); +}); diff --git a/__tests__/StyleDictionary.test.js b/__tests__/StyleDictionary.test.js new file mode 100644 index 000000000..b4bf15c25 --- /dev/null +++ b/__tests__/StyleDictionary.test.js @@ -0,0 +1,1330 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { restore, stubMethod } from 'hanbi'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import chalk from 'chalk'; +import { fileToJSON, clearOutput, fileExists, clearSDMeta } from './__helpers.js'; +import { resolve } from '../dist/esm/resolve.mjs'; +import GroupMessages from '../dist/esm/utils/groupMessages.mjs'; +import flattenTokens from '../dist/esm/utils/flattenTokens.mjs'; +import formats from '../dist/esm/common/formats.mjs'; + +function traverseObj(obj, fn) { + for (let key in obj) { + fn.apply(this, [obj, key, obj[key]]); + if (obj[key] && typeof obj[key] === 'object') { + traverseObj(obj[key], fn); + } + } +} + +function stripMeta(obj) { + Object.keys(obj).forEach((key) => { + if (['attributes', 'name', 'original', 'path'].includes(key)) { + delete obj[key]; + } + if (typeof obj[key] === 'object') { + stripMeta(obj[key]); + } + }); + return obj; +} + +const test_props = { + size: { + padding: { + tiny: { value: '0' }, + }, + }, +}; + +// extend method is called by StyleDictionary constructor, therefore we're basically testing both things here +describe('StyleDictionary class', () => { + beforeEach(() => { + restore(); + clearOutput(); + }); + + afterEach(() => { + clearOutput(); + }); + + it('should accept a string as a path to a JSON5 file', async () => { + const StyleDictionaryExtended = new StyleDictionary('__tests__/__configs/test.json5'); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended).to.have.nested.property('platforms.web'); + }); + + it('should accept a string as a path to a JSONC file', async () => { + const StyleDictionaryExtended = new StyleDictionary('__tests__/__configs/test.jsonc'); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended).to.have.nested.property('platforms.web'); + }); + + it('should allow for chained extends and not mutate the original', async () => { + const StyleDictionary1 = new StyleDictionary({ + foo: 'bar', + bar: 'other', + }); + const StyleDictionary2 = await StyleDictionary1.extend({ + foo: 'baz', + }); + const StyleDictionary3 = await ( + await StyleDictionary2.extend({ + foo: 'bar', + }) + ).extend({ + foo: 'boo', + }); + expect(StyleDictionary1.foo).to.equal('bar'); + expect(StyleDictionary2.foo).to.equal('baz'); + expect(StyleDictionary3.foo).to.equal('boo'); + // check that the bar prop from SD1 is not lost in SD3 + expect(StyleDictionary3.bar).to.equal('other'); + expect(StyleDictionary).not.to.have.property('foo'); + }); + + it(`should not pollute the prototype`, async () => { + const obj = {}; + // method 1 + new StyleDictionary(JSON.parse('{"__proto__":{"polluted":"yes"}}')); + // method 2, which executes a deepmerge under the hood + // this verifies that this deepmerge util is also protected against prototype pollution + const sd = new StyleDictionary(); + await sd.hasInitialized; + await sd.extend(JSON.parse('{"__proto__":{"polluted":"yes"}}')); + + // FIXME: method 3, by putting it into a design token, currently not tested + // for these we use our own deepExtend utility, which must be prototype pollution protected + // however, we don't actually test this here.. + + expect(obj.polluted).to.be.undefined; + }); + + it('should not merge tokens together but rather override on collision', async () => { + const sd = new StyleDictionary({ + source: [ + '__tests__/__json_files/token-collision-1.json', + '__tests__/__json_files/token-collision-2.json', + ], + }); + await sd.hasInitialized; + expect(sd.tokens.test.value).to.equal('#ff0000'); + expect(sd.tokens.test.$extensions).to.be.undefined; + }); + + describe('method signature', () => { + it('should accept a string as a path to a JSON file', () => { + const StyleDictionaryExtended = new StyleDictionary('__tests__/__configs/test.json'); + expect(StyleDictionaryExtended).to.have.nested.property('platforms.web'); + }); + + it('should accept an object as options', () => { + const config = fileToJSON('__tests__/__configs/test.json'); + const StyleDictionaryExtended = new StyleDictionary(config); + expect(StyleDictionaryExtended).to.have.nested.property('platforms.web'); + }); + + it('should override config props', () => { + const StyleDictionaryExtended = new StyleDictionary({ + tokens: { + foo: 'bar', + }, + }); + expect(StyleDictionaryExtended).to.have.nested.property('tokens.foo', 'bar'); + }); + }); + + describe('includes', () => { + it('should throw if include isnt an array', async () => { + const sd = new StyleDictionary({ include: {} }, { init: false }); + await expect(sd.init()).to.eventually.be.rejectedWith('include must be an array'); + }); + + it('should not update tokens if include glob paths dont resolve to anything', () => { + const StyleDictionaryExtended = new StyleDictionary({ + include: ['foo'], + }); + expect(typeof StyleDictionaryExtended.tokens.size).to.equal('undefined'); + }); + + it('should properly glob paths', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + include: ['__tests__/__tokens/*.json'], + }); + await StyleDictionaryExtended.hasInitialized; + expect(typeof StyleDictionaryExtended.tokens.size.padding.tiny).to.equal('object'); + }); + + it('should build the tokens object if an include is given', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + include: ['__tests__/__tokens/paddings.json'], + }); + const output = fileToJSON('__tests__/__tokens/paddings.json'); + traverseObj(output, (obj) => { + if (Object.hasOwn(obj, 'value') && !obj.filePath) { + obj.filePath = '__tests__/__tokens/paddings.json'; + obj.isSource = false; + } + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql(output); + }); + + it('should override existing tokens if include is given', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + tokens: test_props, + include: ['__tests__/__tokens/paddings.json'], + }); + const output = fileToJSON('__tests__/__tokens/paddings.json'); + traverseObj(output, (obj) => { + if (Object.hasOwn(obj, 'value') && !obj.filePath) { + obj.filePath = '__tests__/__tokens/paddings.json'; + obj.isSource = false; + } + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql(output); + }); + + it('should update tokens if there are includes', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + include: ['__tests__/__configs/include.json'], + }); + await StyleDictionaryExtended.hasInitialized; + expect(typeof StyleDictionaryExtended.tokens.size.padding.tiny).to.equal('object'); + }); + + it('should override existing tokens if there are includes', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + tokens: test_props, + include: ['__tests__/__configs/include.json'], + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended).to.have.nested.property( + 'tokens.size.padding.tiny.value', + '3', + ); + }); + }); + + describe('source', () => { + it('should throw if source isnt an array', async () => { + const sd = new StyleDictionary({ source: {} }, { init: false }); + await expect(sd.init()).to.eventually.be.rejectedWith('source must be an array'); + }); + + it("should not update tokens if source glob paths don't resolve to anything", async () => { + const StyleDictionaryExtended = new StyleDictionary({ + source: ['foo'], + }); + await StyleDictionaryExtended.hasInitialized; + expect(typeof StyleDictionaryExtended.tokens.size).to.equal('undefined'); + }); + + it('should build the tokens object if a source is given', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + source: ['__tests__/__tokens/paddings.json'], + }); + const output = fileToJSON('__tests__/__tokens/paddings.json'); + traverseObj(output, (obj) => { + if (Object.hasOwn(obj, 'value') && !obj.filePath) { + obj.filePath = '__tests__/__tokens/paddings.json'; + obj.isSource = true; + } + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql(output); + }); + + it('should use relative filePaths for the filePath property', async () => { + const filePath = '__tests__/__tokens/paddings.json'; + const StyleDictionaryExtended = new StyleDictionary({ + source: [filePath], + }); + const output = fileToJSON('__tests__/__tokens/paddings.json'); + traverseObj(output, (obj) => { + if (Object.hasOwn(obj, 'value') && !obj.filePath) { + obj.filePath = filePath; + obj.isSource = true; + } + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql(output); + }); + + it('should override existing tokens source is given', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + tokens: test_props, + source: ['__tests__/__tokens/paddings.json'], + }); + const output = fileToJSON('__tests__/__tokens/paddings.json'); + traverseObj(output, (obj) => { + if (Object.hasOwn(obj, 'value') && !obj.filePath) { + obj.filePath = '__tests__/__tokens/paddings.json'; + obj.isSource = true; + } + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql(output); + }); + }); + + describe('collisions', () => { + it('should not throw a collision error if a source file collides with an include', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + include: ['__tests__/__tokens/paddings.json'], + source: ['__tests__/__tokens/paddings.json'], + log: 'error', + }); + const output = fileToJSON('__tests__/__tokens/paddings.json'); + traverseObj(output, (obj) => { + if (Object.hasOwn(obj, 'value') && !obj.filePath) { + obj.filePath = '__tests__/__tokens/paddings.json'; + obj.isSource = true; + } + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql(output); + }); + + it('should throw an error if the collision is in source files and log is set to error', async () => { + const sd = new StyleDictionary( + { + source: ['__tests__/__tokens/paddings.json', '__tests__/__tokens/_paddings.json'], + log: { warnings: 'error', verbosity: 'verbose' }, + }, + { init: false }, + ); + let error; + try { + await sd.init(); + } catch (e) { + error = e; + } + await expect(error.message).to.matchSnapshot(); + }); + + it('should throw a brief error if the collision is in source files and log is set to error and verbosity default', async () => { + const sd = new StyleDictionary( + { + source: ['__tests__/__tokens/paddings.json', '__tests__/__tokens/_paddings.json'], + log: { warnings: 'error' }, + }, + { init: false }, + ); + let error; + try { + await sd.init(); + } catch (e) { + error = e; + } + await expect(error.message).to.matchSnapshot(); + }); + + it('should throw a warning if the collision is in source files and log is set to warn', async () => { + const sd = new StyleDictionary( + { + source: ['__tests__/__tokens/paddings.json', '__tests__/__tokens/paddings.json'], + log: 'warn', + }, + { init: false }, + ); + await expect(sd.init()).to.eventually.be.fulfilled; + }); + }); + + describe('reference errors', () => { + it('should throw an error by default if broken references are encountered', async () => { + const sd = new StyleDictionary({ + tokens: { + foo: { + value: '{bar}', + type: 'other', + }, + }, + platforms: { + css: {}, + }, + }); + + await expect(sd.exportPlatform('css')).to.eventually.be.rejectedWith(` +Reference Errors: +Some token references (1) could not be found. +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`); + }); + + it('should only log an error if broken references are encountered and log.errors.brokenReferences is set to console', async () => { + const stub = stubMethod(console, 'error'); + const sd = new StyleDictionary({ + log: { + errors: { + brokenReferences: 'console', + }, + }, + tokens: { + foo: { + value: '{bar}', + type: 'other', + }, + }, + platforms: { + css: {}, + }, + }); + await sd.exportPlatform('css'); + expect(stub.firstCall.args[0]).to.equal(` +Reference Errors: +Some token references (1) could not be found. +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`); + }); + + it('should allow silencing broken references errors with log.verbosity set to silent and log.errors.brokenReferences set to console', async () => { + const stub = stubMethod(console, 'error'); + const sd = new StyleDictionary({ + log: { + verbosity: 'silent', + errors: { + brokenReferences: 'console', + }, + }, + tokens: { + foo: { + value: '{bar}', + type: 'other', + }, + }, + platforms: { + css: {}, + }, + }); + await sd.exportPlatform('css'); + expect(stub.callCount).to.equal(0); + }); + + it('should resolve correct references when the tokenset contains broken references and log.errors.brokenReferences is set to console', async () => { + const stub = stubMethod(console, 'error'); + const sd = new StyleDictionary({ + log: { + errors: { + brokenReferences: 'console', + }, + }, + tokens: { + foo: { + value: '{bar}', + type: 'other', + }, + baz: { + value: '8px', + type: 'dimension', + }, + qux: { + value: '{baz}', + type: 'dimension', + }, + }, + platforms: { + css: {}, + }, + }); + const transformed = await sd.exportPlatform('css'); + expect(stub.firstCall.args[0]).to.equal(` +Reference Errors: +Some token references (1) could not be found. +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`); + + expect(clearSDMeta(transformed)).to.eql({ + foo: { + value: '{bar}', + type: 'other', + }, + baz: { + value: '8px', + type: 'dimension', + }, + qux: { + value: '8px', + type: 'dimension', + }, + }); + }); + }); + + describe('expand object value tokens', () => { + it('should not expand object value tokens by default', async () => { + const input = { + border: { + type: 'border', + value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + }; + const sd = new StyleDictionary({ + tokens: input, + }); + await sd.hasInitialized; + expect(sd.tokens).to.eql(input); + }); + + it('should allow expanding tokens globally', async () => { + const input = { + border: { + type: 'border', + value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + }; + const sd = new StyleDictionary({ + tokens: input, + expand: true, + }); + await sd.hasInitialized; + expect(sd.tokens).to.eql({ + border: { + color: { + type: 'color', + value: '#000', + }, + style: { + type: 'strokeStyle', + value: 'solid', + }, + width: { + type: 'dimension', + value: '2px', + }, + }, + }); + }); + + it('should allow expanding tokens on a per platform basis', async () => { + const input = { + border: { + type: 'border', + value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + }; + const sd = new StyleDictionary({ + tokens: input, + platforms: { + css: { + expand: true, + }, + js: {}, + }, + }); + await sd.hasInitialized; + const cssTokens = await sd.exportPlatform('css'); + const jsTokens = await sd.exportPlatform('js'); + expect(stripMeta(cssTokens)).to.eql({ + border: { + color: { + type: 'color', + value: '#000', + }, + style: { + type: 'strokeStyle', + value: 'solid', + }, + width: { + type: 'dimension', + value: '2px', + }, + }, + }); + expect(stripMeta(jsTokens)).to.eql(input); + }); + + it('should allow combining global expand with per platform expand', async () => { + const input = { + border: { + type: 'border', + value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + borderTwo: { + type: 'border', + value: { + width: '1px', + style: 'dashed', + color: '#ccc', + }, + }, + }; + const sd = new StyleDictionary({ + tokens: input, + expand: { + include: (token) => { + return token.value.width === '2px'; + }, + }, + platforms: { + css: {}, + js: { + expand: { + typesMap: true, + }, + }, + }, + }); + await sd.hasInitialized; + const cssTokens = await sd.exportPlatform('css'); + const jsTokens = await sd.exportPlatform('js'); + + expect(stripMeta(cssTokens)).to.eql({ + border: { + color: { + type: 'color', + value: '#000', + }, + style: { + type: 'strokeStyle', + value: 'solid', + }, + width: { + type: 'dimension', + value: '2px', + }, + }, + borderTwo: input.borderTwo, + }); + expect(stripMeta(jsTokens)).to.eql({ + border: { + color: { + type: 'color', + value: '#000', + }, + style: { + type: 'strokeStyle', + value: 'solid', + }, + width: { + type: 'dimension', + value: '2px', + }, + }, + borderTwo: { + color: { + type: 'color', + value: '#ccc', + }, + style: { + type: 'strokeStyle', + value: 'dashed', + }, + width: { + type: 'dimension', + value: '1px', + }, + }, + }); + }); + }); + + describe('DTCG integration', () => { + it('should allow using $type value on a token group, children inherit, local overrides take precedence', async () => { + const sd = new StyleDictionary({ + tokens: { + dimensions: { + $type: 'dimension', + sm: { + $value: '5', + }, + md: { + $value: '10', + }, + nested: { + deep: { + lg: { + $value: '15', + }, + }, + }, + nope: { + $value: '20', + $type: 'spacing', + }, + }, + }, + platforms: { + css: { + transformGroup: 'css', + }, + }, + }); + await sd.hasInitialized; + + expect(sd.tokens.dimensions.sm.$type).to.equal('dimension'); + expect(sd.tokens.dimensions.md.$type).to.equal('dimension'); + expect(sd.tokens.dimensions.nested.deep.lg.$type).to.equal('dimension'); + expect(sd.tokens.dimensions.nope.$type).to.equal('spacing'); + }); + + it('should detect usage of DTCG draft spec tokens', async () => { + const sd = new StyleDictionary({ + tokens: { + datalist: { + key: { color: { $value: '#222' } }, + value: { color: { $value: '#000' } }, + }, + }, + }); + await sd.hasInitialized; + expect(sd.usesDtcg).to.be.true; + }); + }); + + describe('buildPlatform', () => { + const dictionary = { + tokens: { + foo: { value: 'bar' }, + bingo: { value: 'bango' }, + }, + }; + + const hooks = { + formats: { + foo: (dictionary) => JSON.stringify(dictionary.tokens), + }, + }; + + const platform = { + files: [ + { + destination: '__tests__/__output/test.json', + format: 'foo', + }, + ], + }; + + const platformWithBuildPath = { + buildPath: '__tests__/__output/', + files: [ + { + destination: 'test.json', + format: 'foo', + }, + ], + }; + + const platformWithFilter = { + buildPath: '__tests__/__output/', + files: [ + { + destination: 'test.json', + filter: function (property) { + return property.value === 'bango'; + }, + format: 'foo', + }, + ], + }; + + const platformWithoutFormat = { + buildPath: '__tests__/__output/', + files: [ + { + destination: 'test.json', + }, + ], + }; + + const platformWithBadBuildPath = { + buildPath: '__tests__/__output', + files: [ + { + destination: 'test.json', + format: 'foo', + }, + ], + }; + + const platformWithoutFiles = { + buildPath: '__tests__/__output/', + }; + + it("should throw if build path doesn't have a trailing slash", async () => { + const sd = new StyleDictionary({ + ...dictionary, + hooks, + platforms: { + foo: platformWithBadBuildPath, + }, + }); + await expect(sd.buildPlatform('foo')).to.eventually.rejectedWith( + 'Build path must end in a trailing slash or you will get weird file names.', + ); + }); + + it('should throw if there is no files property', async () => { + const sd = new StyleDictionary({ + ...dictionary, + hooks, + platforms: { + foo: platformWithoutFiles, + }, + }); + await expect(sd.buildPlatform('foo')).to.eventually.rejectedWith( + 'Cannot format platform foo due to missing "files" property', + ); + }); + + it('should throw if missing a format', async () => { + const sd = new StyleDictionary({ + ...dictionary, + hooks, + platforms: { + foo: platformWithoutFormat, + }, + }); + await expect(sd.buildPlatform('foo')).to.eventually.rejectedWith('Please supply a format'); + }); + + it('should work without buildPath', async () => { + const sd = new StyleDictionary({ + ...dictionary, + hooks, + platforms: { + foo: platform, + }, + }); + await sd.buildPlatform('foo'); + expect(fileExists('__tests__/__output/test.json')).to.be.true; + }); + + it('should work with buildPath', async () => { + const sd = new StyleDictionary({ + ...dictionary, + hooks, + platforms: { + foo: platformWithBuildPath, + }, + }); + await sd.buildPlatform('foo'); + expect(fileExists('__tests__/__output/test.json')).to.be.true; + }); + + it('should work with a filter', async () => { + const sd = new StyleDictionary({ + ...dictionary, + hooks, + platforms: { + foo: platformWithFilter, + }, + }); + await sd.buildPlatform('foo'); + expect(fileExists('__tests__/__output/test.json')).to.be.true; + const output = JSON.parse(fs.readFileSync(resolve('__tests__/__output/test.json'))); + expect(output).to.have.property('bingo'); + expect(output).to.not.have.property('foo'); + Object.values(output).forEach((property) => { + expect(property.value).to.equal('bango'); + }); + }); + }); + + describe('formatFile', () => { + function format() { + return 'hi'; + } + + function nestedFormat() { + return 'hi'; + } + + nestedFormat.nested = true; + + it('should error if format doesnt exist or isnt a function', async () => { + const sd = new StyleDictionary({ + platforms: { + foo: {}, + }, + }); + await expect( + sd.formatFile({ destination: '__tests__output/test.txt' }, {}, {}), + ).to.eventually.rejectedWith('Please enter a valid file format'); + await expect( + sd.formatFile({ destination: '__tests__output/test.txt', format: {} }, {}, {}), + ).to.eventually.rejectedWith('Please enter a valid file format'); + await expect( + sd.formatFile({ destination: '__tests__/__output/test.txt', format: [] }, {}, {}), + ).to.eventually.rejectedWith('Please enter a valid file format'); + }); + + it('should error if destination isnt a string', async () => { + const sd = new StyleDictionary({ + platforms: { + foo: {}, + }, + }); + await expect(sd.formatFile({ format, destination: [] }, {}, {})).to.eventually.rejectedWith( + 'Please enter a valid destination', + ); + await expect(sd.formatFile({ format, destination: {} }, {}, {})).to.eventually.rejectedWith( + 'Please enter a valid destination', + ); + }); + + describe('name collisions', () => { + const destination = '__tests__/__output/test.collisions'; + const PROPERTY_NAME_COLLISION_WARNINGS = `${GroupMessages.GROUP.PropertyNameCollisionWarnings}:${destination}`; + const name = 'someName'; + const dictionary = { + allTokens: [ + { + name: name, + path: ['some', 'name', 'path1'], + value: 'value1', + }, + { + name: name, + path: ['some', 'name', 'path2'], + value: 'value2', + }, + ], + }; + + it('should generate warning messages for output name collisions', async () => { + GroupMessages.clear(PROPERTY_NAME_COLLISION_WARNINGS); + const sd = new StyleDictionary(); + const { logs } = await sd.formatFile( + { destination, format }, + { log: { verbosity: 'verbose' } }, + dictionary, + ); + + expect(logs.warning.length).to.equal(1); + expect(logs.warning[0]).to.matchSnapshot(); + }); + + it('should not warn users if the format is a nested format', async () => { + const sd = new StyleDictionary(); + const { logs } = await sd.formatFile({ destination, format: nestedFormat }, {}, dictionary); + expect(logs.success[0]).to.equal(chalk.bold.green(`✔︎ ${destination}`)); + }); + }); + + const destEmptyTokens = '__tests__/__output/test.emptyTokens'; + it('should warn when a file is not created because of empty tokens', async () => { + const dictionary = { + allTokens: [ + { + name: 'someName', + type: 'color', + path: ['some', 'name', 'path1'], + value: 'value1', + }, + ], + }; + + const filter = function (token) { + return token.type === 'color2'; + }; + + const sd = new StyleDictionary(); + const { logs, output } = await sd.formatFile( + { + destination: destEmptyTokens, + format, + filter, + }, + {}, + dictionary, + ); + + expect(output).to.be.undefined; + + const warn = chalk.rgb(255, 140, 0)(`No tokens for ${destEmptyTokens}. File not created.`); + expect(logs.warning[0]).to.equal(warn); + }); + + it('should warn when a file is not created because of empty tokens using async filters', async () => { + const dictionary = { + allTokens: [ + { + name: 'someName', + type: 'color', + path: ['some', 'name', 'path1'], + value: 'value1', + }, + ], + }; + + const filter = async (token) => { + await new Promise((resolve) => setTimeout(resolve, 100)); + return token.type === 'color2'; + }; + + const sd = new StyleDictionary(); + const { logs, output } = await sd.formatFile( + { + destination: destEmptyTokens, + format, + filter, + }, + {}, + dictionary, + ); + expect(output).to.be.undefined; + + const warn = chalk.rgb(255, 140, 0)(`No tokens for ${destEmptyTokens}. File not created.`); + expect(logs.warning[0]).to.equal(warn); + }); + + it('should create file output properly', async () => { + const sd = new StyleDictionary(); + const { output } = await sd.formatFile( + { + destination: 'test.txt', + format, + }, + { + buildPath: '__tests__/__output/', + }, + {}, + ); + expect(output).to.equal('hi'); + }); + + it('should support asynchronous formats', async () => { + const tokens = { + size: { + font: { + small: { + value: '12rem', + original: { + value: '12px', + }, + name: 'size-font-small', + path: ['size', 'font', 'small'], + }, + large: { + value: '18rem', + original: { + value: '18px', + }, + name: 'size-font-large', + path: ['size', 'font', 'large'], + }, + }, + }, + color: { + base: { + red: { + value: '#ff0000', + comment: 'comment', + original: { + value: '#FF0000', + comment: 'comment', + }, + name: 'color-base-red', + path: ['color', 'base', 'red'], + }, + }, + white: { + value: '#ffffff', + original: { + value: '#ffffff', + }, + name: 'color-white', + path: ['color', 'white'], + }, + }, + }; + + const customCSSFormat = async ({ dictionary }) => { + return `:root { +${dictionary.allTokens.map((tok) => ` ${tok.name}: "${tok.value}";`).join('\n')} +}\n`; + }; + + const sd = new StyleDictionary(); + const { output } = await sd.formatFile( + { + destination: 'test.css', + format: customCSSFormat, + }, + { + buildPath: '__tests__/__output/', + }, + { + tokens: tokens, + allTokens: flattenTokens(tokens), + }, + ); + await expect(output).to.matchSnapshot(); + }); + + it('should support asynchronous fileHeader', async () => { + const dictionary = { + allTokens: [ + { + name: 'someName', + type: 'color', + path: ['some', 'name', 'path1'], + original: { value: 'value1' }, + value: 'value1', + }, + ], + }; + + const sd = new StyleDictionary(); + const { output } = await sd.formatFile( + { + destination: 'test.css', + format: formats['css/variables'], + options: { + fileHeader: async () => { + await new Promise((resolve) => setTimeout(resolve, 100)); + return ['foo', 'bar']; + }, + }, + }, + { + buildPath: '__tests__/__output/', + }, + dictionary, + ); + await expect(output).to.matchSnapshot(); + }); + }); + + // most of the functionality in this method is tested already with buildPlatform tests + // here we just need to check if it works without outputting to files + describe('formatPlatform', () => { + const cfg = { + tokens: { + colors: { + red: { + type: 'color', + value: '#ff0000', + }, + blue: { + type: 'color', + value: '#0000ff', + }, + }, + }, + hooks: { + formats: { + foo: ({ dictionary }) => dictionary.allTokens.map(({ value, name }) => ({ value, name })), + }, + }, + platforms: { + foo: { + files: [ + { + format: 'foo', + }, + ], + }, + }, + }; + + it('should allow outputting JS data with no file destination', async () => { + const sd = new StyleDictionary(cfg); + const output = await sd.formatPlatform('foo'); + expect(output).to.eql([ + { + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + destination: '', + }, + ]); + }); + + it('should allow outputting JS for multiple files, and annotate by destination', async () => { + const sd = new StyleDictionary({ + ...cfg, + platforms: { + ...cfg.platforms, + foo: { + ...cfg.platforms.foo, + files: [ + { ...cfg.platforms.foo.files[0], destination: 'output1' }, + { ...cfg.platforms.foo.files[0], destination: 'output2' }, + ], + }, + }, + }); + const output = await sd.formatPlatform('foo'); + expect(output).to.eql([ + { + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + destination: 'output1', + }, + { + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + destination: 'output2', + }, + ]); + }); + }); + + describe('formatAllPlatforms', () => { + it('should allow formatting multiple platforms, giving output as JS data', async () => { + const cfg = { + tokens: { + colors: { + red: { + type: 'color', + value: '#ff0000', + }, + blue: { + type: 'color', + value: '#0000ff', + }, + }, + }, + hooks: { + formats: { + qux: ({ dictionary }) => + dictionary.allTokens.map(({ value, name }) => ({ value, name })), + }, + }, + platforms: { + foo: { + files: [ + { + format: 'qux', + destination: 'foo/output1', + }, + { + format: 'qux', + destination: 'foo/output2', + }, + ], + }, + bar: { + files: [ + { + format: 'qux', + destination: 'bar/output1', + }, + { + format: 'qux', + destination: 'bar/output2', + }, + ], + }, + }, + }; + const sd = new StyleDictionary(cfg); + const output = await sd.formatAllPlatforms(); + + expect(output).to.eql({ + foo: [ + { + destination: 'foo/output1', + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + }, + { + destination: 'foo/output2', + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + }, + ], + bar: [ + { + destination: 'bar/output1', + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + }, + { + destination: 'bar/output2', + output: [ + { + value: '#ff0000', + name: 'red', + }, + { + value: '#0000ff', + name: 'blue', + }, + ], + }, + ], + }); + }); + }); +}); diff --git a/__tests__/__configs/test.js b/__tests__/__configs/test.js index e132ec8dd..a2f1a357f 100644 --- a/__tests__/__configs/test.js +++ b/__tests__/__configs/test.js @@ -1 +1,97 @@ -module.exports = require("./test.json") \ No newline at end of file +export default { + source: ['__tests__/__tokens/**/*.json'], + platforms: { + web: { + transformGroup: 'web', + prefix: 'smop', + buildPath: '__tests__/__output/web/', + files: [ + { + destination: '_icons.css', + format: 'scss/icons', + }, + { + destination: '_variables.css', + format: 'scss/variables', + }, + { + destination: '_styles.js', + format: 'javascript/module', + }, + ], + }, + scss: { + transformGroup: 'scss', + prefix: 'smop', + buildPath: '__tests__/__output/scss/', + files: [ + { + destination: '_icons.scss', + format: 'scss/icons', + }, + { + destination: '_variables.scss', + format: 'scss/variables', + }, + ], + }, + less: { + transformGroup: 'less', + prefix: 'smop', + buildPath: '__tests__/__output/less/', + files: [ + { + destination: '_icons.less', + format: 'less/icons', + }, + { + destination: '_variables.less', + format: 'less/variables', + }, + ], + }, + android: { + transformGroup: 'android', + buildPath: '__tests__/__output/', + files: [ + { + destination: 'android/colors.xml', + format: 'android/colors', + }, + { + destination: 'android/font_dimen.xml', + format: 'android/fontDimens', + }, + { + destination: 'android/dimens.xml', + format: 'android/dimens', + }, + ], + actions: ['android/copyImages'], + }, + ios: { + transformGroup: 'ios', + buildPath: '__tests__/__output/ios/', + files: [ + { + destination: 'style_dictionary.plist', + format: 'ios/plist', + }, + { + destination: 'style_dictionary.h', + format: 'ios/macros', + }, + ], + }, + 'react-native': { + transformGroup: 'react-native', + buildPath: '__tests__/__output/react-native/', + files: [ + { + destination: 'style_dictionary.js', + format: 'javascript/es6', + }, + ], + }, + }, +}; diff --git a/__tests__/__configs/test.json b/__tests__/__configs/test.json index b5240d53c..eeb2ed61f 100644 --- a/__tests__/__configs/test.json +++ b/__tests__/__configs/test.json @@ -1,5 +1,5 @@ { - "source": ["__tests__/__properties/**/*.json"], + "source": ["__tests__/__tokens/**/*.json"], "platforms": { "web": { "transformGroup": "web", @@ -9,10 +9,12 @@ { "destination": "_icons.css", "format": "scss/icons" - },{ + }, + { "destination": "_variables.css", "format": "scss/variables" - },{ + }, + { "destination": "_styles.js", "format": "javascript/module" } @@ -26,7 +28,8 @@ { "destination": "_icons.scss", "format": "scss/icons" - },{ + }, + { "destination": "_variables.scss", "format": "scss/variables" } @@ -40,7 +43,8 @@ { "destination": "_icons.less", "format": "less/icons" - },{ + }, + { "destination": "_variables.less", "format": "less/variables" } @@ -53,17 +57,17 @@ { "destination": "android/colors.xml", "format": "android/colors" - },{ + }, + { "destination": "android/font_dimen.xml", "format": "android/fontDimens" - },{ + }, + { "destination": "android/dimens.xml", "format": "android/dimens" } ], - "actions": [ - "android/copyImages" - ] + "actions": ["android/copyImages"] }, "ios": { "transformGroup": "ios", @@ -72,7 +76,8 @@ { "destination": "style_dictionary.plist", "format": "ios/plist" - },{ + }, + { "destination": "style_dictionary.h", "format": "ios/macros" } diff --git a/__tests__/__configs/test.json5 b/__tests__/__configs/test.json5 index 062efc323..d352b5dc6 100644 --- a/__tests__/__configs/test.json5 +++ b/__tests__/__configs/test.json5 @@ -1,11 +1,11 @@ { // some comment - source: ['test/properties/**/*.json'], + source: ['__tests__/__tokens/**/*.json'], platforms: { web: { transformGroup: 'web', prefix: 'smop', - buildPath: 'test/output/web/', + buildPath: '__tests__/output/web/', files: [ { destination: '_icons.css', @@ -24,7 +24,7 @@ scss: { transformGroup: 'scss', prefix: 'smop', - buildPath: 'test/output/scss/', + buildPath: '__tests__/output/scss/', files: [ { destination: '_icons.scss', @@ -39,7 +39,7 @@ less: { transformGroup: 'less', prefix: 'smop', - buildPath: 'test/output/less/', + buildPath: '__tests__/output/less/', files: [ { destination: '_icons.less', @@ -53,7 +53,7 @@ }, android: { transformGroup: 'android', - buildPath: 'test/output/', + buildPath: '__tests__/output/', files: [ { destination: 'android/colors.xml', @@ -72,7 +72,7 @@ }, ios: { transformGroup: 'ios', - buildPath: 'test/output/ios/', + buildPath: '__tests__/output/ios/', files: [ { destination: 'style_dictionary.plist', @@ -90,9 +90,9 @@ files: [ { destination: 'style_dictionary.js', - format: 'javascript/es6' - } - ] - } + format: 'javascript/es6', + }, + ], + }, }, } diff --git a/__tests__/__configs/test.jsonc b/__tests__/__configs/test.jsonc index 4dea5a66a..fce1aec79 100644 --- a/__tests__/__configs/test.jsonc +++ b/__tests__/__configs/test.jsonc @@ -1,11 +1,11 @@ { // some comment - "source": ["test/properties/**/*.json"], + "source": ["__tests__/__tokens/**/*.json"], "platforms": { "web": { "transformGroup": "web", "prefix": "smop", - "buildPath": "test/output/web/", + "buildPath": "__tests__/output/web/", "files": [ { "destination": "_icons.css", @@ -24,7 +24,7 @@ "scss": { "transformGroup": "scss", "prefix": "smop", - "buildPath": "test/output/scss/", + "buildPath": "__tests__/output/scss/", "files": [ { "destination": "_icons.scss", @@ -39,7 +39,7 @@ "less": { "transformGroup": "less", "prefix": "smop", - "buildPath": "test/output/less/", + "buildPath": "__tests__/output/less/", "files": [ { "destination": "_icons.less", @@ -53,7 +53,7 @@ }, "android": { "transformGroup": "android", - "buildPath": "test/output/", + "buildPath": "__tests__/output/", "files": [ { "destination": "android/colors.xml", @@ -72,7 +72,7 @@ }, "ios": { "transformGroup": "ios", - "buildPath": "test/output/ios/", + "buildPath": "__tests__/output/ios/", "files": [ { "destination": "style_dictionary.plist", diff --git a/__tests__/__configs/tokenCollisions.json b/__tests__/__configs/tokenCollisions.json new file mode 100644 index 000000000..d718eb949 --- /dev/null +++ b/__tests__/__configs/tokenCollisions.json @@ -0,0 +1,21 @@ +{ + "tokens": { + "color": { + "red": { "value": "#f00" }, + "background": { + "red": { "value": "{color.red.value}" } + } + } + }, + "platforms": { + "css": { + "buildPath": "__tests__/__output/css/", + "files": [ + { + "format": "css/variables", + "destination": "vars.css" + } + ] + } + } +} diff --git a/__tests__/__helpers.js b/__tests__/__helpers.js index 8b3f6a12f..b60bcc19a 100644 --- a/__tests__/__helpers.js +++ b/__tests__/__helpers.js @@ -11,39 +11,92 @@ * and limitations under the License. */ -var fs = require('fs-extra'); - -module.exports = { - clearOutput: function() { - fs.emptyDirSync('__tests__/__output'); - }, - - fileToJSON: function(path) { - return fs.readJsonSync(path); - }, - - fileExists: function(filePath) { - try { - return fs.statSync(filePath).isFile(); - } catch (err) { - return false; - } - }, +import { expect } from 'chai'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from 'style-dictionary'; +import isPlainObject from 'is-plain-obj'; - pathDoesNotExist: function(path) { - try { - return !fs.existsSync(path); - } catch (err) { - return false; - } - }, +export const cleanConsoleOutput = (str) => { + const arr = str + .split(`\n`) + // Remove ANSI stuff from the console output so we get human-readable strings + // https://github.com/chalk/ansi-regex/blob/main/index.js#L3 + .map((s) => + s + // eslint-disable-next-line no-control-regex + .replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '') + .trim(), + ); + return arr.join(`\n`); +}; - dirDoesNotExist: function(dirPath) { - return this.pathDoesNotExist(dirPath); - }, +export const expectThrowsAsync = async (method, errorMessage) => { + let error = null; + try { + await method(); + } catch (err) { + error = err; + } + expect(error).to.be.an('Error'); + if (errorMessage) { + expect(error.message).to.equal(errorMessage); + } +}; - fileDoesNotExist: function(filePath) { - return this.pathDoesNotExist(filePath); +export const fileToJSON = (_path, _fs = fs) => { + return JSON.parse(_fs.readFileSync(resolve(_path), 'utf-8')); +}; +export const clearOutput = (outputFolder = '__tests__/__output', _fs = fs) => { + try { + _fs.rmdirSync(outputFolder); + } catch (e) { + // } }; + +export const fileExists = (filePath, _fs = fs) => { + try { + return _fs.statSync(filePath).isFile(); + } catch (err) { + return false; + } +}; + +export const dirExists = (dirPath, _fs = fs) => { + return _fs.existsSync(dirPath); +}; + +export function fixDate() { + const constantDate = new Date('2000-01-01'); + // eslint-disable-next-line no-undef + const __global = typeof window === 'object' ? window : globalThis; + + // eslint-disable-next-line no-undef + __global.Date = function () { + return constantDate; + }; + // eslint-disable-next-line no-undef + __global.Date.now = function () { + return constantDate; + }; +} + +export function clearSDMeta(tokens) { + const copy = structuredClone(tokens); + function recurse(slice) { + if (isPlainObject(slice)) { + if (Object.hasOwn(slice, 'value')) { + ['path', 'original', 'name', 'attributes', 'filePath', 'isSource'].forEach((prop) => { + delete slice[prop]; + }); + } else { + Object.values(slice).forEach((prop) => { + recurse(prop); + }); + } + } + } + recurse(copy); + return copy; +} diff --git a/__tests__/__json_files/broken/broken.json b/__tests__/__json_files/broken/broken.json index 89d342f63..ddda1a212 100644 --- a/__tests__/__json_files/broken/broken.json +++ b/__tests__/__json_files/broken/broken.json @@ -1,3 +1,3 @@ { - invalid: "json", + invalid: "json"!!, } diff --git a/__tests__/__json_files/module_exports_object.js b/__tests__/__json_files/module_exports_object.js index a3460fb9a..d44eaa66b 100644 --- a/__tests__/__json_files/module_exports_object.js +++ b/__tests__/__json_files/module_exports_object.js @@ -1,4 +1,4 @@ -module.exports = { - "foo": "bar", - "bar": "{foo}" -} +export default { + foo: 'bar', + bar: '{foo}', +}; diff --git a/__tests__/__json_files/token-collision-1.json b/__tests__/__json_files/token-collision-1.json new file mode 100644 index 000000000..e19fa0b1f --- /dev/null +++ b/__tests__/__json_files/token-collision-1.json @@ -0,0 +1,15 @@ +{ + "test": { + "value": "#ffffff", + "type": "color", + "$extensions": { + "studio.tokens": { + "modify": { + "type": "darken", + "value": ".25", + "space": "srgb" + } + } + } + } +} diff --git a/__tests__/__json_files/token-collision-2.json b/__tests__/__json_files/token-collision-2.json new file mode 100644 index 000000000..988de4612 --- /dev/null +++ b/__tests__/__json_files/token-collision-2.json @@ -0,0 +1,6 @@ +{ + "test": { + "value": "#ff0000", + "type": "color" + } +} diff --git a/__tests__/__properties/colors.json b/__tests__/__properties/colors.json deleted file mode 100644 index 733922b05..000000000 --- a/__tests__/__properties/colors.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "color" : { - "base" : { - "red": { - "150" : { "value" : "#611D1C" }, - "130" : { "value" : "#922C2A" }, - "100" : { "value" : "#C43B39" }, - "60" : { "value" : "#E19D9C" }, - "30" : { "value" : "#F0CCCC" }, - "5" : { "value" : "#FAF3F2" } - }, - - "orange": { - "150" : { "value" : "#804C00" }, - "130" : { "value" : "#B56D00" }, - "100" : { "value" : "#FF9900" }, - "60" : { "value" : "#FFCC80" }, - "30" : { "value" : "#FFE5BF" }, - "5" : { "value" : "#FFFAF2" } - }, - - "yellow": { - "150" : { "value" : "#7D6400" }, - "130" : { "value" : "#BD9700" }, - "100" : { "value" : "#FBD12D" }, - "60" : { "value" : "#FCE279" }, - "30" : { "value" : "#FDF3CA" }, - "5" : { "value" : "#FEFCF4" } - }, - - "lime": { - "150" : { "value" : "#5E6C24" }, - "130" : { "value" : "#8DA13E" }, - "100" : { "value" : "#BDD948" }, - "60" : { "value" : "#D7E893" }, - "30" : { "value" : "#EEF5D2" }, - "5" : { "value" : "#FBFCF7" } - }, - - "green" : { - "150" : { "value" : "#14421C" }, - "130" : { "value" : "#1F662A" }, - "100" : { "value" : "#298738" }, - "60" : { "value" : "#93C29B" }, - "30" : { "value" : "#C9E0CD" }, - "5" : { "value" : "#F2F7F3" } - }, - - "teal": { - "150" : { "value" : "#005B62" }, - "130" : { "value" : "#008994" }, - "100" : { "value" : "#00ADBB" }, - "60" : { "value" : "#80DBE2" }, - "30" : { "value" : "#C0EDF0" }, - "5" : { "value" : "#F2FBFC" } - }, - - "blue": { - "150" : { "value" : "#003B65" }, - "130" : { "value" : "#005998" }, - "100" : { "value" : "#0077CC" }, - "60" : { "value" : "#80BBE5" }, - "30" : { "value" : "#BFDDF2" }, - "5" : { "value" : "#F2F8FC" } - }, - - "squidink": { - "140" : { "value" : "#192026" }, - "100" : { "value" : "#303942" }, - "80" : { "value" : "#63676B" }, - "60" : { "value" : "#8C8F92" }, - "40" : { "value" : "#ADB0B3" }, - "20" : { "value" : "#D1D2D3" }, - "10" : { "value" : "#EAEBEC" }, - "5" : { "value" : "#F2F4F5" } - } - }, - - "border": { - "light": { "value": "{color.base.squidink.10.value}" }, - "base" : { "value": "{color.base.squidink.20.value}" }, - "dark" : { "value": "{color.base.squidink.40.value}" }, - "focus": { "value": "{color.base.orange.100.value}" } - }, - - "font": { - "link": { "value": "{color.base.blue.100.value}" } - }, - - "button": { - "base": { "value": "{color.base.blue.100.value}" }, - "active": { "value": "{color.button.base.value}", "transformColor": { - "darken": 0.5 - } }, - "hover": { "value": "{color.button.active.value}", "transformColor": { - "darken": 0.2 - } } - } - } -} diff --git a/__tests__/__properties/comment.json b/__tests__/__properties/comment.json deleted file mode 100644 index 2223e75e4..000000000 --- a/__tests__/__properties/comment.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "size": { - "large": { - "value": 20, - "comment": "this is a comment" - } - } -} diff --git a/__tests__/__properties/font.json b/__tests__/__properties/font.json deleted file mode 100644 index 3a961ac39..000000000 --- a/__tests__/__properties/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "asset": { - "font": { - "icon": { - "value": "./test/__assets/fonts/scapp_icons-regular.ttf" - } - } - } -} \ No newline at end of file diff --git a/__tests__/__properties/font_sizes.json b/__tests__/__properties/font_sizes.json deleted file mode 100644 index 43de0577f..000000000 --- a/__tests__/__properties/font_sizes.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "size": { - "font": { - "tiny": { - "value": "11px" - }, - "small": { - "value": "13px" - }, - "medium": { - "value": "15px" - }, - "large": { - "value": "17px" - }, - "xl": { - "value": "21px" - }, - "xxl": { - "value": "25px" - }, - "xxxl": { - "value": "30px" - }, - "base": { - "value": "{size.font.medium.value}" - } - } - } -} \ No newline at end of file diff --git a/__tests__/__properties/icons.json b/__tests__/__properties/icons.json deleted file mode 100644 index da8447fb1..000000000 --- a/__tests__/__properties/icons.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "content": { - "icon": { - "email": { "value":""}, - "chevron-down": { "value":""}, - "chevron-up": { "value":""}, - "chevron-left": { "value":""}, - "chevron-right": { "value":""}, - "checkmark": { "value":""}, - "price-tag": { "value":""}, - "barcode": { "value":""}, - "x": { "value":""}, - "star": { "value":""}, - "no-reply": { "value":""}, - "reply": { "value":""}, - "alert": { "value":""}, - "alert-fill": { "value":""}, - "checkmark-circle": { "value":""}, - "checkmark-circle-fill": { "value":""}, - "x-circle": { "value":""}, - "x-circle-fill": { "value":""}, - "star-fill": { "value":""}, - "plus": { "value":""}, - "plus-circle": { "value":""}, - "plus-circle-fill": { "value":""}, - "clock": { "value":""}, - "clock-fill": { "value":""}, - "box": { "value":""}, - "emails": { "value":""}, - "shipment": { "value":""}, - "globe": { "value":""}, - "money": { "value":""}, - "sort": { "value":""}, - "sort-alt": { "value":""}, - "arrow-up": { "value":""}, - "camera": { "value":""}, - "camera-fill": { "value":""}, - "minus-circle": { "value":""}, - "minus-circle-fill": { "value":""}, - "minus": { "value":""}, - "calendar-alt": { "value":""}, - "horn": { "value":""}, - "graph": { "value":""}, - "chat-bubbles": { "value":""}, - "filter": { "value":""}, - "search": { "value":""}, - "truck": { "value":""}, - "arrow-down": { "value":""}, - "paper-airplane": { "value":""}, - "paper": { "value":""}, - "price-tag-fill": { "value":""}, - "return": { "value":""}, - "play": { "value":""}, - "vertical-dots": { "value":""}, - "play-fill": { "value":""}, - "alert-circle-fill": { "value":""}, - "alert-circle": { "value":""}, - "lightning": { "value":""}, - "calendar": { "value":""}, - "hamburger": { "value":""}, - "lightning-fill": { "value":""}, - "chevron-right-bold": { "value":""}, - "paperclip": { "value":""}, - "gear": { "value":""}, - "pencil": { "value":""}, - "info": { "value":""}, - "info-circle": { "value":""}, - "arrow-right": { "value":""}, - "info-circle-fill": { "value":""}, - "pencil-circle": { "value":""}, - "pencil-circle-fill": { "value":""}, - "arrow-left": { "value":""}, - "microphone": { "value":""}, - "star-half": { "value":""}, - "list": { "value":""}, - "print-default": { "value":""}, - "print-left": { "value":""}, - "print-right": { "value":""}, - "print-with-receipt": { "value":""}, - "trash": { "value":""}, - "spinner": { "value":""}, - "price-tag-plus": { "value":""}, - "search-amazon": { "value":""}, - "drag-and-drop": { "value":""}, - "picture": { "value":""}, - "number-one": { "value":""}, - "number-two": { "value":""}, - "number-three": { "value":""}, - "number-four": { "value":""}, - "number-five": { "value":""}, - "number-six": { "value":""}, - "number-seven": { "value":""}, - "number-eight": { "value":""}, - "number-nine": { "value":""} - } - } -} \ No newline at end of file diff --git a/__tests__/__properties/paddings.1.json b/__tests__/__properties/paddings.1.json deleted file mode 100644 index 4ca03cfcc..000000000 --- a/__tests__/__properties/paddings.1.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "size": { - "padding": { - "tiny": { - "value": "3" - }, - "small": { - "value": "5" - }, - "base": { - "value": "10" - }, - "large": { - "value": "15" - }, - "xl": { - "value": "20" - }, - "xxl": { - "value": "30" - } - } - } -} \ No newline at end of file diff --git a/__tests__/__properties/paddings.json b/__tests__/__properties/paddings.json deleted file mode 100644 index 0ba5cc545..000000000 --- a/__tests__/__properties/paddings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "size": { - "padding": { - "zero": { - "value": 0 - }, - "tiny": { - "value": "3" - }, - "small": { - "value": "5" - }, - "base": { - "value": "10" - }, - "large": { - "value": "15" - }, - "xl": { - "value": "20" - }, - "xxl": { - "value": "30" - } - } - } -} \ No newline at end of file diff --git a/__tests__/__setup.js b/__tests__/__setup.js index 0d5db7dc2..a434c69fc 100644 --- a/__tests__/__setup.js +++ b/__tests__/__setup.js @@ -1,3 +1,63 @@ -const constantDate = new Date('2000-01-01'); -global.Date = function() { return constantDate }; -global.Date.now = function() { return constantDate }; \ No newline at end of file +import { use } from 'chai'; +import chaiAsPromised from '@esm-bundle/chai-as-promised'; +import { dirname } from 'path-unified'; +import { fs } from 'style-dictionary/fs'; +import { chaiWtrSnapshot } from '../snapshot-plugin/chai-wtr-snapshot.js'; +import { fixDate } from './__helpers.js'; +import { writeZIP } from '../dist/esm/utils/convertToDTCG.mjs'; + +/** + * We have a bunch of files that we use a mock data for our tests + * Since we run tests in the browser, we will have to mirror these mock files + * to the browser-filesystem which uses memfs by default. + * This will allow the tests to run with the mock files. + * + * We also use a custom WTR + Chai snapshot plugin for snapshot testing, + * which needs to be initialized client-side + */ + +fixDate(); + +let hasInitializedResolve; +export const hasInitialized = new Promise((resolve) => { + hasInitializedResolve = resolve; +}); +// in case of Node env, we can resolve it immediately since we don't do this setup stuff +if (typeof window !== 'object') { + hasInitializedResolve(); +} + +/** + * @param {string} filePath + */ +function ensureDirectoryExists(filePath) { + const dir = dirname(filePath); + if (fs.existsSync(dir)) { + return true; + } + fs.mkdirSync(dir, { recursive: true }); +} + +/** + * @param {string} file + * @param {string | Record} contents + */ +async function mirrorFile(file, contents) { + ensureDirectoryExists(file); + // zip files cannot just be written to FS using utf-8 encoding.. + if (file.endsWith('.zip')) { + const zipResult = await writeZIP(contents); + contents = new Uint8Array(await zipResult.arrayBuffer()); + } + await fs.promises.writeFile(file, contents); +} + +/** + * @param {[string, string | Record][]} filesToMirror + */ +export async function setup(filesToMirror) { + use(chaiAsPromised); + use(chaiWtrSnapshot); + await Promise.all(filesToMirror.map(([file, contents]) => mirrorFile(file, contents))); + hasInitializedResolve(); +} diff --git a/__tests__/__snapshots__/StyleDictionary.test.snap.js b/__tests__/__snapshots__/StyleDictionary.test.snap.js new file mode 100644 index 000000000..cdb07fd0e --- /dev/null +++ b/__tests__/__snapshots__/StyleDictionary.test.snap.js @@ -0,0 +1,78 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; +snapshots["StyleDictionary class + extend method collisions should throw an error if the collision is in source files and log is set to error"] = +` +Token collisions detected (7): + +Collision detected at: size.padding.zero! Original value: 0, New value: 0 +Collision detected at: size.padding.tiny! Original value: 3, New value: 3 +Collision detected at: size.padding.small! Original value: 5, New value: 5 +Collision detected at: size.padding.base! Original value: 10, New value: 10 +Collision detected at: size.padding.large! Original value: 15, New value: 15 +Collision detected at: size.padding.xl! Original value: 20, New value: 20 +Collision detected at: size.padding.xxl! Original value: 30, New value: 30 + +`; +/* end snapshot StyleDictionary class + extend method collisions should throw an error if the collision is in source files and log is set to error */ + +snapshots["StyleDictionary class + extend method collisions should throw a brief error if the collision is in source files and log is set to error and verbosity default"] = +` +Token collisions detected (7): +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot StyleDictionary class + extend method collisions should throw a brief error if the collision is in source files and log is set to error and verbosity default */ + +snapshots["StyleDictionary class collisions should throw an error if the collision is in source files and log is set to error"] = +` +Token collisions detected (7): + +Collision detected at: size.padding.zero! Original value: 0, New value: 0 +Collision detected at: size.padding.tiny! Original value: 3, New value: 3 +Collision detected at: size.padding.small! Original value: 5, New value: 5 +Collision detected at: size.padding.base! Original value: 10, New value: 10 +Collision detected at: size.padding.large! Original value: 15, New value: 15 +Collision detected at: size.padding.xl! Original value: 20, New value: 20 +Collision detected at: size.padding.xxl! Original value: 30, New value: 30 + +`; +/* end snapshot StyleDictionary class collisions should throw an error if the collision is in source files and log is set to error */ + +snapshots["StyleDictionary class collisions should throw a brief error if the collision is in source files and log is set to error and verbosity default"] = +` +Token collisions detected (7): +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot StyleDictionary class collisions should throw a brief error if the collision is in source files and log is set to error and verbosity default */ + +snapshots["StyleDictionary class formatFile should support asynchronous formats"] = +`:root { + size-font-small: "12rem"; + size-font-large: "18rem"; + color-base-red: "#ff0000"; + color-white: "#ffffff"; +} +`; +/* end snapshot StyleDictionary class formatFile should support asynchronous formats */ + +snapshots["StyleDictionary class formatFile should support asynchronous fileHeader"] = +`/** + * foo + * bar + */ + +:root { + --someName: value1; +} +`; +/* end snapshot StyleDictionary class formatFile should support asynchronous fileHeader */ + +snapshots["StyleDictionary class formatFile name collisions should generate warning messages for output name collisions"] = +`⚠️ __tests__/__output/test.collisions +While building __tests__/__output/test.collisions, token collisions were found; output may be unexpected. Ignore this warning if intentional. + Output name someName was generated by: + some.name.path1 value1 + some.name.path2 value2 +This many-to-one issue is usually caused by some combination of: + * conflicting or similar paths/names in token definitions + * platform transforms/transformGroups affecting names, especially when removing specificity + * overly inclusive file filters`; +/* end snapshot StyleDictionary class formatFile name collisions should generate warning messages for output name collisions */ + diff --git a/__tests__/__snapshots__/buildFile.test.snap.js b/__tests__/__snapshots__/buildFile.test.snap.js new file mode 100644 index 000000000..062fb46ab --- /dev/null +++ b/__tests__/__snapshots__/buildFile.test.snap.js @@ -0,0 +1,25 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["buildFile should support asynchronous formats"] = +`:root { + size-font-small: "12rem"; + size-font-large: "18rem"; + color-base-red: "#ff0000"; + color-white: "#ffffff"; +} +`; +/* end snapshot buildFile should support asynchronous formats */ + +snapshots["buildFile should support asynchronous fileHeader"] = +`/** + * foo + * bar + */ + +:root { + --someName: value1; +} +`; +/* end snapshot buildFile should support asynchronous fileHeader */ + diff --git a/__tests__/__tokens/_paddings.json b/__tests__/__tokens/_paddings.json new file mode 100644 index 000000000..89324df65 --- /dev/null +++ b/__tests__/__tokens/_paddings.json @@ -0,0 +1,34 @@ +{ + "size": { + "padding": { + "zero": { + "value": 0, + "type": "dimension" + }, + "tiny": { + "value": "3", + "type": "dimension" + }, + "small": { + "value": "5", + "type": "dimension" + }, + "base": { + "value": "10", + "type": "dimension" + }, + "large": { + "value": "15", + "type": "dimension" + }, + "xl": { + "value": "20", + "type": "dimension" + }, + "xxl": { + "value": "30", + "type": "dimension" + } + } + } +} diff --git a/__tests__/__properties/borders.json b/__tests__/__tokens/borders.json similarity index 81% rename from __tests__/__properties/borders.json rename to __tests__/__tokens/borders.json index 9661b7b4e..9e591bb6f 100644 --- a/__tests__/__properties/borders.json +++ b/__tests__/__tokens/borders.json @@ -3,14 +3,17 @@ "layout": { "light": { "value": "1px solid {color.border.light.value}", + "type": "border", "comment": "" }, "dark": { "value": "1px solid {color.border.dark.value}", + "type": "border", "comment": "" }, "base": { "value": "1px solid {color.border.base.value}", + "type": "border", "comment": "" } }, @@ -18,18 +21,22 @@ "input": { "base": { "value": "1px solid {color.border.base.value}", + "type": "border", "comment": "" }, "focus": { "value": "1px solid {color.border.focus.value}", + "type": "border", "comment": "" }, "error": { "value": "1px solid {color.border.base.value}", + "type": "border", "comment": "" }, "button": { "value": "1px solid {color.font.link.value}", + "type": "border", "comment": "" } } diff --git a/__tests__/__tokens/colors.json b/__tests__/__tokens/colors.json new file mode 100644 index 000000000..7157016f9 --- /dev/null +++ b/__tests__/__tokens/colors.json @@ -0,0 +1,108 @@ +{ + "color": { + "base": { + "red": { + "150": { "value": "#611D1C", "type": "color" }, + "130": { "value": "#922C2A", "type": "color" }, + "100": { "value": "#C43B39", "type": "color" }, + "60": { "value": "#E19D9C", "type": "color" }, + "30": { "value": "#F0CCCC", "type": "color" }, + "5": { "value": "#FAF3F2", "type": "color" } + }, + + "orange": { + "150": { "value": "#804C00", "type": "color" }, + "130": { "value": "#B56D00", "type": "color" }, + "100": { "value": "#FF9900", "type": "color" }, + "60": { "value": "#FFCC80", "type": "color" }, + "30": { "value": "#FFE5BF", "type": "color" }, + "5": { "value": "#FFFAF2", "type": "color" } + }, + + "yellow": { + "150": { "value": "#7D6400", "type": "color" }, + "130": { "value": "#BD9700", "type": "color" }, + "100": { "value": "#FBD12D", "type": "color" }, + "60": { "value": "#FCE279", "type": "color" }, + "30": { "value": "#FDF3CA", "type": "color" }, + "5": { "value": "#FEFCF4", "type": "color" } + }, + + "lime": { + "150": { "value": "#5E6C24", "type": "color" }, + "130": { "value": "#8DA13E", "type": "color" }, + "100": { "value": "#BDD948", "type": "color" }, + "60": { "value": "#D7E893", "type": "color" }, + "30": { "value": "#EEF5D2", "type": "color" }, + "5": { "value": "#FBFCF7", "type": "color" } + }, + + "green": { + "150": { "value": "#14421C", "type": "color" }, + "130": { "value": "#1F662A", "type": "color" }, + "100": { "value": "#298738", "type": "color" }, + "60": { "value": "#93C29B", "type": "color" }, + "30": { "value": "#C9E0CD", "type": "color" }, + "5": { "value": "#F2F7F3", "type": "color" } + }, + + "teal": { + "150": { "value": "#005B62", "type": "color" }, + "130": { "value": "#008994", "type": "color" }, + "100": { "value": "#00ADBB", "type": "color" }, + "60": { "value": "#80DBE2", "type": "color" }, + "30": { "value": "#C0EDF0", "type": "color" }, + "5": { "value": "#F2FBFC", "type": "color" } + }, + + "blue": { + "150": { "value": "#003B65", "type": "color" }, + "130": { "value": "#005998", "type": "color" }, + "100": { "value": "#0077CC", "type": "color" }, + "60": { "value": "#80BBE5", "type": "color" }, + "30": { "value": "#BFDDF2", "type": "color" }, + "5": { "value": "#F2F8FC", "type": "color" } + }, + + "squidink": { + "140": { "value": "#192026", "type": "color" }, + "100": { "value": "#303942", "type": "color" }, + "80": { "value": "#63676B", "type": "color" }, + "60": { "value": "#8C8F92", "type": "color" }, + "40": { "value": "#ADB0B3", "type": "color" }, + "20": { "value": "#D1D2D3", "type": "color" }, + "10": { "value": "#EAEBEC", "type": "color" }, + "5": { "value": "#F2F4F5", "type": "color" } + } + }, + + "border": { + "light": { "value": "{color.base.squidink.10.value}", "type": "color" }, + "base": { "value": "{color.base.squidink.20.value}", "type": "color" }, + "dark": { "value": "{color.base.squidink.40.value}", "type": "color" }, + "focus": { "value": "{color.base.orange.100.value}", "type": "color" } + }, + + "font": { + "link": { "value": "{color.base.blue.100.value}", "type": "color" } + }, + + "button": { + "base": { "value": "{color.base.blue.100.value}", "type": "color" }, + "active": { + "value": "{color.button.base.value}", + "type": "color", + "transformColor": { + "darken": 0.5 + } + }, + "hover": { + "value": "{color.button.active.value}", + "type": "color", + "transformColor": { + "darken": 0.2 + } + } + } + } +} diff --git a/__tests__/__tokens/comment.json b/__tests__/__tokens/comment.json new file mode 100644 index 000000000..916b0551f --- /dev/null +++ b/__tests__/__tokens/comment.json @@ -0,0 +1,9 @@ +{ + "size": { + "large": { + "value": 20, + "comment": "this is a comment", + "type": "dimension" + } + } +} diff --git a/__tests__/__tokens/font_sizes.json b/__tests__/__tokens/font_sizes.json new file mode 100644 index 000000000..4bb2ad03d --- /dev/null +++ b/__tests__/__tokens/font_sizes.json @@ -0,0 +1,38 @@ +{ + "size": { + "font": { + "tiny": { + "value": "11px", + "type": "fontSize" + }, + "small": { + "value": "13px", + "type": "fontSize" + }, + "medium": { + "value": "15px", + "type": "fontSize" + }, + "large": { + "value": "17px", + "type": "fontSize" + }, + "xl": { + "value": "21px", + "type": "fontSize" + }, + "xxl": { + "value": "25px", + "type": "fontSize" + }, + "xxxl": { + "value": "30px", + "type": "fontSize" + }, + "base": { + "value": "{size.font.medium.value}", + "type": "fontSize" + } + } + } +} diff --git a/__tests__/__tokens/icons.json b/__tests__/__tokens/icons.json new file mode 100644 index 000000000..8e8aae4b1 --- /dev/null +++ b/__tests__/__tokens/icons.json @@ -0,0 +1,97 @@ +{ + "content": { + "icon": { + "email": { "value": "", "type": "html" }, + "chevron-down": { "value": "", "type": "html" }, + "chevron-up": { "value": "", "type": "html" }, + "chevron-left": { "value": "", "type": "html" }, + "chevron-right": { "value": "", "type": "html" }, + "checkmark": { "value": "", "type": "html" }, + "price-tag": { "value": "", "type": "html" }, + "barcode": { "value": "", "type": "html" }, + "x": { "value": "", "type": "html" }, + "star": { "value": "", "type": "html" }, + "no-reply": { "value": "", "type": "html" }, + "reply": { "value": "", "type": "html" }, + "alert": { "value": "", "type": "html" }, + "alert-fill": { "value": "", "type": "html" }, + "checkmark-circle": { "value": "", "type": "html" }, + "checkmark-circle-fill": { "value": "", "type": "html" }, + "x-circle": { "value": "", "type": "html" }, + "x-circle-fill": { "value": "", "type": "html" }, + "star-fill": { "value": "", "type": "html" }, + "plus": { "value": "", "type": "html" }, + "plus-circle": { "value": "", "type": "html" }, + "plus-circle-fill": { "value": "", "type": "html" }, + "clock": { "value": "", "type": "html" }, + "clock-fill": { "value": "", "type": "html" }, + "box": { "value": "", "type": "html" }, + "emails": { "value": "", "type": "html" }, + "shipment": { "value": "", "type": "html" }, + "globe": { "value": "", "type": "html" }, + "money": { "value": "", "type": "html" }, + "sort": { "value": "", "type": "html" }, + "sort-alt": { "value": "", "type": "html" }, + "arrow-up": { "value": "", "type": "html" }, + "camera": { "value": "", "type": "html" }, + "camera-fill": { "value": "", "type": "html" }, + "minus-circle": { "value": "", "type": "html" }, + "minus-circle-fill": { "value": "", "type": "html" }, + "minus": { "value": "", "type": "html" }, + "calendar-alt": { "value": "", "type": "html" }, + "horn": { "value": "", "type": "html" }, + "graph": { "value": "", "type": "html" }, + "chat-bubbles": { "value": "", "type": "html" }, + "filter": { "value": "", "type": "html" }, + "search": { "value": "", "type": "html" }, + "truck": { "value": "", "type": "html" }, + "arrow-down": { "value": "", "type": "html" }, + "paper-airplane": { "value": "", "type": "html" }, + "paper": { "value": "", "type": "html" }, + "price-tag-fill": { "value": "", "type": "html" }, + "return": { "value": "", "type": "html" }, + "play": { "value": "", "type": "html" }, + "vertical-dots": { "value": "", "type": "html" }, + "play-fill": { "value": "", "type": "html" }, + "alert-circle-fill": { "value": "", "type": "html" }, + "alert-circle": { "value": "", "type": "html" }, + "lightning": { "value": "", "type": "html" }, + "calendar": { "value": "", "type": "html" }, + "hamburger": { "value": "", "type": "html" }, + "lightning-fill": { "value": "", "type": "html" }, + "chevron-right-bold": { "value": "", "type": "html" }, + "paperclip": { "value": "", "type": "html" }, + "gear": { "value": "", "type": "html" }, + "pencil": { "value": "", "type": "html" }, + "info": { "value": "", "type": "html" }, + "info-circle": { "value": "", "type": "html" }, + "arrow-right": { "value": "", "type": "html" }, + "info-circle-fill": { "value": "", "type": "html" }, + "pencil-circle": { "value": "", "type": "html" }, + "pencil-circle-fill": { "value": "", "type": "html" }, + "arrow-left": { "value": "", "type": "html" }, + "microphone": { "value": "", "type": "html" }, + "star-half": { "value": "", "type": "html" }, + "list": { "value": "", "type": "html" }, + "print-default": { "value": "", "type": "html" }, + "print-left": { "value": "", "type": "html" }, + "print-right": { "value": "", "type": "html" }, + "print-with-receipt": { "value": "", "type": "html" }, + "trash": { "value": "", "type": "html" }, + "spinner": { "value": "", "type": "html" }, + "price-tag-plus": { "value": "", "type": "html" }, + "search-amazon": { "value": "", "type": "html" }, + "drag-and-drop": { "value": "", "type": "html" }, + "picture": { "value": "", "type": "html" }, + "number-one": { "value": "", "type": "html" }, + "number-two": { "value": "", "type": "html" }, + "number-three": { "value": "", "type": "html" }, + "number-four": { "value": "", "type": "html" }, + "number-five": { "value": "", "type": "html" }, + "number-six": { "value": "", "type": "html" }, + "number-seven": { "value": "", "type": "html" }, + "number-eight": { "value": "", "type": "html" }, + "number-nine": { "value": "", "type": "html" } + } + } +} diff --git a/__tests__/__properties/images/flags/us.json b/__tests__/__tokens/images/flags/us.json similarity index 76% rename from __tests__/__properties/images/flags/us.json rename to __tests__/__tokens/images/flags/us.json index b6fa75b75..9e24945d9 100644 --- a/__tests__/__properties/images/flags/us.json +++ b/__tests__/__tokens/images/flags/us.json @@ -4,19 +4,23 @@ "flag": { "us": { "mdpi": { - "value": "__tests__/__assets/images/mdpi/flag_us_base.png" + "value": "__tests__/__assets/images/mdpi/flag_us_base.png", + "type": "asset" }, "hdpi": { - "value": "__tests__/__assets/images/hdpi/flag_us_base.png" + "value": "__tests__/__assets/images/hdpi/flag_us_base.png", + "type": "asset" }, "xhdpi": { - "value": "__tests__/__assets/images/xhdpi/flag_us_base.png" + "value": "__tests__/__assets/images/xhdpi/flag_us_base.png", + "type": "asset" }, "xxhdpi": { - "value": "__tests__/__assets/images/xxhdpi/flag_us_base.png" + "value": "__tests__/__assets/images/xxhdpi/flag_us_base.png", + "type": "asset" } } } } } -} \ No newline at end of file +} diff --git a/__tests__/__properties/nonPropertyNode.json b/__tests__/__tokens/nonPropertyNode.json similarity index 89% rename from __tests__/__properties/nonPropertyNode.json rename to __tests__/__tokens/nonPropertyNode.json index 6bedccbd4..1853d1a4b 100644 --- a/__tests__/__properties/nonPropertyNode.json +++ b/__tests__/__tokens/nonPropertyNode.json @@ -4,6 +4,7 @@ "base": { "red": { "value": "#f00", + "type": "color", "key2": "also testing" }, "attributes": { diff --git a/__tests__/__properties/nonString.json b/__tests__/__tokens/nonString.json similarity index 58% rename from __tests__/__properties/nonString.json rename to __tests__/__tokens/nonString.json index a40e42eb4..21872545f 100644 --- a/__tests__/__properties/nonString.json +++ b/__tests__/__tokens/nonString.json @@ -6,29 +6,33 @@ "g": 0, "b": 0, "a": 1 - } + }, + "type": "color" }, "otherRed": { - "value": "{color.red.value}" + "value": "{color.red.value}", + "type": "color" } }, "size": { "large": { - "value": 20 + "value": 20, + "type": "dimension" }, "otherLarge": { - "value": "{size.large.value}" + "value": "{size.large.value}", + "type": "dimension" } }, "number": { - "test": { "value": 20 }, - "otherTest": { "value": "{number.test.value}" } + "test": { "value": 20, "type": "number" }, + "otherTest": { "value": "{number.test.value}", "type": "number" } }, "array": { - "test": { "value": ["foo","bar"] }, + "test": { "value": ["foo", "bar"] }, "otherTest": { "value": "{array.test.value}" } }, diff --git a/__tests__/__tokens/paddings.json b/__tests__/__tokens/paddings.json new file mode 100644 index 000000000..89324df65 --- /dev/null +++ b/__tests__/__tokens/paddings.json @@ -0,0 +1,34 @@ +{ + "size": { + "padding": { + "zero": { + "value": 0, + "type": "dimension" + }, + "tiny": { + "value": "3", + "type": "dimension" + }, + "small": { + "value": "5", + "type": "dimension" + }, + "base": { + "value": "10", + "type": "dimension" + }, + "large": { + "value": "15", + "type": "dimension" + }, + "xl": { + "value": "20", + "type": "dimension" + }, + "xxl": { + "value": "30", + "type": "dimension" + } + } + } +} diff --git a/__tests__/__tokens/tokens.zip b/__tests__/__tokens/tokens.zip new file mode 100644 index 000000000..0b7885673 Binary files /dev/null and b/__tests__/__tokens/tokens.zip differ diff --git a/__tests__/buildAllPlatforms.test.js b/__tests__/buildAllPlatforms.test.js index 81f53d7c3..c2b2e3f73 100644 --- a/__tests__/buildAllPlatforms.test.js +++ b/__tests__/buildAllPlatforms.test.js @@ -10,31 +10,92 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var helpers = require('./__helpers'); -var StyleDictionary = require('../index'); +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { clearOutput, fileExists } from './__helpers.js'; +import memfs from '@bundled-es-modules/memfs'; describe('buildAllPlatforms', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should work with json config', () => { - var StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/__configs/test.json'); - StyleDictionaryExtended.buildAllPlatforms(); - expect(helpers.fileExists('./__tests__/__output/web/_icons.css')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/colors.xml')).toBeTruthy(); + it('should work with json config', async () => { + const StyleDictionaryExtended = new StyleDictionary('__tests__/__configs/test.json'); + await StyleDictionaryExtended.buildAllPlatforms(); + expect(fileExists('__tests__/__output/web/_icons.css')).to.be.true; + expect(fileExists('__tests__/__output/android/colors.xml')).to.be.true; }); - it('should work with js config', () => { - var StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/__configs/test.js'); - StyleDictionaryExtended.buildAllPlatforms(); - expect(helpers.fileExists('./__tests__/__output/web/_icons.css')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/colors.xml')).toBeTruthy(); + it('should work with js config', async () => { + const StyleDictionaryExtended = new StyleDictionary('__tests__/__configs/test.js'); + await StyleDictionaryExtended.buildAllPlatforms(); + expect(fileExists('__tests__/__output/web/_icons.css')).to.be.true; + expect(fileExists('__tests__/__output/android/colors.xml')).to.be.true; + }); + + it('should work with volume override', async () => { + const vol1 = new memfs.Volume(); + vol1.mkdirSync('__tests__/__tokens', { recursive: true }); + vol1.writeFileSync( + '__tests__/__tokens/colors.json', + fs.readFileSync('__tests__/__tokens/colors.json', 'utf-8'), + 'utf-8', + ); + const sd1 = new StyleDictionary( + { + source: ['__tests__/__tokens/colors.json'], + platforms: { + web: { + transformGroup: 'css', + buildPath: '__tests__/__output/css/', + files: [ + { + destination: 'vars1.css', + format: 'css/variables', + }, + ], + }, + }, + }, + { volume: vol1 }, + ); + await sd1.buildAllPlatforms(); + + const vol2 = new memfs.Volume(); + vol2.mkdirSync('__tests__/__tokens', { recursive: true }); + vol2.writeFileSync( + '__tests__/__tokens/colors.json', + fs.readFileSync('__tests__/__tokens/colors.json', 'utf-8'), + 'utf-8', + ); + const sd2 = new StyleDictionary( + { + source: ['__tests__/__tokens/colors.json'], + platforms: { + web: { + transformGroup: 'css', + buildPath: '__tests__/__output/css/', + files: [ + { + destination: 'vars2.css', + format: 'css/variables', + }, + ], + }, + }, + }, + { volume: vol2 }, + ); + await sd2.buildAllPlatforms(); + expect(fileExists('__tests__/__output/css/vars1.css', vol1)).to.be.true; + expect(fileExists('__tests__/__output/css/vars2.css', vol1)).to.be.false; + expect(fileExists('__tests__/__output/css/vars1.css', vol2)).to.be.false; + expect(fileExists('__tests__/__output/css/vars2.css', vol2)).to.be.true; }); }); diff --git a/__tests__/buildFile.test.js b/__tests__/buildFile.test.js deleted file mode 100644 index fb770ac31..000000000 --- a/__tests__/buildFile.test.js +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var buildFile = require('../lib/buildFile'); -var helpers = require('./__helpers'); -var GroupMessages = require('../lib/utils/groupMessages'); -var chalk = require('chalk'); - -function format() { - return "hi"; -} - -function nestedFormat() { - return "hi"; -} - -nestedFormat.nested = true; - -describe('buildFile', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should error if format doesnt exist or isnt a function', () => { - expect( - buildFile.bind(null, {destination: '__tests__/__output/test.txt'}, {}, {}) - ).toThrow('Please enter a valid file format'); - expect( - buildFile.bind(null, {destination: '__tests__/__output/test.txt', format: {}}, {}, {}) - ).toThrow('Please enter a valid file format'); - expect( - buildFile.bind(null, {destination: '__tests__/__output/test.txt', format: []}, {}, {}) - ).toThrow('Please enter a valid file format'); - }); - - it('should error if destination doesnt exist or isnt a string', () => { - expect( - buildFile.bind(null, {format}, {}, {}) - ).toThrow('Please enter a valid destination'); - expect( - buildFile.bind(null, {format, destination: []}, {}, {}) - ).toThrow('Please enter a valid destination'); - expect( - buildFile.bind(null, {format, destination: {}}, {}, {}) - ).toThrow('Please enter a valid destination'); - }); - - describe('name collisions', () => { - let destination = './__tests__/__output/test.collisions'; - let PROPERTY_NAME_COLLISION_WARNINGS = GroupMessages.GROUP.PropertyNameCollisionWarnings + ":" + destination; - let name = 'someName'; - let properties = { - allProperties: [{ - name: name, - path: ['some', 'name', 'path1'], - value: 'value1' - }, { - name: name, - path: ['some', 'name', 'path2'], - value: 'value2' - }] - }; - it('should generate warning messages for output name collisions', () => { - GroupMessages.clear(PROPERTY_NAME_COLLISION_WARNINGS); - buildFile({destination, format}, {}, properties); - - let collisions = properties.allProperties.map((properties) => { - let propertyPathText = chalk.keyword('orangered')(properties.path.join('.')); - let valueText = chalk.keyword('darkorange')(properties.value); - return propertyPathText + ' ' + valueText; - }).join('\n '); - let output = `Output name ${chalk.keyword('orangered').bold(name)} was generated by:\n ${collisions}`; - let expectJSON = JSON.stringify([output]); - - expect(GroupMessages.count(PROPERTY_NAME_COLLISION_WARNINGS)).toBe(1); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_NAME_COLLISION_WARNINGS))).toBe(expectJSON); - }); - - it('should not warn users if the format is a nested format', () => { - console.log = jest.fn(); - buildFile({destination, format: nestedFormat}, {}, properties); - expect(console.log).toHaveBeenCalledWith(chalk.bold.green(`✔︎ ${destination}`)); - }); - }); - - - let destEmptyProperties = './__tests__/__output/test.emptyProperties'; - it('should warn when a file is not created because of empty properties', () => { - let dictionary = { - allProperties: [{ - name: 'someName', - attributes: { category: 'category1' }, - path: ['some', 'name', 'path1'], - value: 'value1' - }] - }; - - let filter = function(prop) { - return prop.attributes.category === 'category2'; - } - - buildFile({ - destination: destEmptyProperties, - format, - filter - }, {}, dictionary); - expect(helpers.fileExists('./__tests__/__output/test.emptyProperties')).toBeFalsy(); - }); - - it('should write to a file properly', () => { - buildFile({ - destination: 'test.txt', - format - },{ - buildPath: '__tests__/__output/' - },{} - ); - expect(helpers.fileExists('./__tests__/__output/test.txt')).toBeTruthy(); - }); -}); diff --git a/__tests__/buildFiles.test.js b/__tests__/buildFiles.test.js deleted file mode 100644 index fdd7b4e9e..000000000 --- a/__tests__/buildFiles.test.js +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var buildFiles = require('../lib/buildFiles'); -var helpers = require('./__helpers'); -var _ = require('../lib/utils/es6_'); - -var dictionary = { - properties: { - foo: { value: 'bar' }, - bingo: { value: 'bango' } - } -}; - -var platform = { - files: [ - { - destination: '__tests__/__output/test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] -}; - -var platformWithBuildPath = { - buildPath: '__tests__/__output/', - files: [ - { - destination: 'test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] -}; - -var platformWithFilter = { - buildPath: '__tests__/__output/', - files: [ - { - destination: 'test.json', - filter: function(property) { - return property.value === "bango" - }, - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - }, - } - ] -}; - -var platformWithoutFormatter = { - buildPath: '__tests__/__output/', - files: [ - { - destination: 'test.json', - } - ] -}; - -var platformWithBadBuildPath = { - buildPath: '__tests__/__output', - files: [ - { - destination: 'test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] -}; - -describe('buildFiles', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should throw if build path doesn\'t have a trailing slash', () => { - expect( - buildFiles.bind(null, dictionary, platformWithBadBuildPath) - ).toThrow('Build path must end in a trailing slash or you will get weird file names.'); - }); - - it('should throw if missing a format', () => { - expect( - buildFiles.bind(null, dictionary, platformWithoutFormatter) - ).toThrow('Please supply a format'); - }); - - it('should work without buildPath', () => { - buildFiles( dictionary, platform ); - expect(helpers.fileExists('./__tests__/__output/test.json')).toBeTruthy(); - }); - - it('should work with buildPath', () => { - buildFiles( dictionary, platformWithBuildPath ); - expect(helpers.fileExists('./__tests__/__output/test.json')).toBeTruthy(); - }); - - it('should work with a filter', () => { - buildFiles(dictionary, platformWithFilter); - expect(helpers.fileExists('./__tests__/__output/test.json')).toBeTruthy(); - var output = require("./__output/test.json") - expect(output).toHaveProperty('bingo'); - expect(output).not.toHaveProperty('foo'); - _.each(output, function(property) { - expect(property.value).toBe('bango'); - }); - }); - -}); diff --git a/__tests__/buildPlatform.test.js b/__tests__/buildPlatform.test.js index 065665df4..8876e4d0e 100644 --- a/__tests__/buildPlatform.test.js +++ b/__tests__/buildPlatform.test.js @@ -10,159 +10,156 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fileToJSON, clearOutput, fileExists } from './__helpers.js'; -var helpers = require('./__helpers'); -var config = helpers.fileToJSON(__dirname + '/__configs/test.json'); -var StyleDictionary = require('../index'); -var StyleDictionaryExtended = StyleDictionary.extend(config); +const config = fileToJSON('__tests__/__configs/test.json'); +const StyleDictionaryExtended = new StyleDictionary(config); describe('buildPlatform', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should throw if passed a platform that doesn\'t exist', () => { - expect( - StyleDictionaryExtended.buildPlatform.bind(test, 'foobar') - ).toThrow('Platform "foobar" does not exist'); + it("should throw if passed a platform that doesn't exist", async () => { + await expect(StyleDictionaryExtended.buildPlatform('foobar')).to.eventually.rejectedWith( + 'Platform "foobar" does not exist', + ); - expect( - function() { - StyleDictionaryExtended.buildPlatform('web'); - } - ).not.toThrow(); + await expect(StyleDictionaryExtended.buildPlatform('web')).to.eventually.be.fulfilled; }); - it('should build web platform files', () => { - StyleDictionaryExtended.buildPlatform('web'); - expect(helpers.fileExists('./__tests__/__output/web/_icons.css')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/web/_styles.js')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/web/_variables.css')).toBeTruthy(); + it('should build web platform files', async () => { + await StyleDictionaryExtended.buildPlatform('web'); + expect(fileExists('__tests__/__output/web/_icons.css')).to.be.true; + expect(fileExists('__tests__/__output/web/_styles.js')).to.be.true; + expect(fileExists('__tests__/__output/web/_variables.css')).to.be.true; }); - it('should build scss platform files', () => { - StyleDictionaryExtended.buildPlatform('scss'); - expect(helpers.fileExists('./__tests__/__output/scss/_icons.scss')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/scss/_variables.scss')).toBeTruthy(); + it('should build scss platform files', async () => { + await StyleDictionaryExtended.buildPlatform('scss'); + expect(fileExists('__tests__/__output/scss/_icons.scss')).to.be.true; + expect(fileExists('__tests__/__output/scss/_variables.scss')).to.be.true; }); - it('should build less platform files', () => { - StyleDictionaryExtended.buildPlatform('less'); - expect(helpers.fileExists('./__tests__/__output/less/_icons.less')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/less/_variables.less')).toBeTruthy(); + it('should build less platform files', async () => { + await StyleDictionaryExtended.buildPlatform('less'); + expect(fileExists('__tests__/__output/less/_icons.less')).to.be.true; + expect(fileExists('__tests__/__output/less/_variables.less')).to.be.true; }); - it('should do android stuff', () => { - StyleDictionaryExtended.buildPlatform('android'); - expect(helpers.fileExists('./__tests__/__output/android/main/res/drawable-hdpi/flag_us.png')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/main/res/drawable-xhdpi/flag_us.png')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/colors.xml')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/dimens.xml')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/font_dimen.xml')).toBeTruthy(); + it('should do android stuff', async () => { + await StyleDictionaryExtended.buildPlatform('android'); + expect(fileExists('__tests__/__output/android/main/res/drawable-hdpi/flag_us.png')).to.be.true; + expect(fileExists('__tests__/__output/android/main/res/drawable-xhdpi/flag_us.png')).to.be.true; + expect(fileExists('__tests__/__output/android/colors.xml')).to.be.true; + expect(fileExists('__tests__/__output/android/dimens.xml')).to.be.true; + expect(fileExists('__tests__/__output/android/font_dimen.xml')).to.be.true; }); - it('should do ios stuff', () => { - StyleDictionaryExtended.buildPlatform('ios'); - expect(helpers.fileExists('./__tests__/__output/ios/style_dictionary.plist')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/ios/style_dictionary.h')).toBeTruthy(); + it('should do ios stuff', async () => { + await StyleDictionaryExtended.buildPlatform('ios'); + expect(fileExists('__tests__/__output/ios/style_dictionary.plist')).to.be.true; + expect(fileExists('__tests__/__output/ios/style_dictionary.h')).to.be.true; }); - it('should handle non-string values in properties', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - source: ['__tests__/__properties/nonString.json'], + it('should handle non-string values in tokens', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + source: ['__tests__/__tokens/nonString.json'], platforms: { test: { - buildPath: "__tests__/__output/", - transforms: ["attribute/cti","size/px","color/hex"], + buildPath: '__tests__/__output/', + transforms: ['attribute/cti', 'size/px', 'color/hex'], files: [ { - "destination": "output.json", - "format": "json" - } - ] - } - } + destination: 'output.json', + format: 'json', + }, + ], + }, + }, }); - StyleDictionaryExtended.buildPlatform('test'); - expect(helpers.fileExists('./__tests__/__output/output.json')).toBeTruthy(); - // var input = helpers.fileToJSON('./__tests__/__properties/nonString.json'); - var output = helpers.fileToJSON('./__tests__/__output/output.json'); + await StyleDictionaryExtended.buildPlatform('test'); + expect(fileExists('__tests__/__output/output.json')).to.be.true; + const output = fileToJSON('__tests__/__output/output.json'); // Make sure transforms run on non-string values as they normally would - expect(output).toHaveProperty('color.red.value', output.color.otherRed.value); - expect(output).toHaveProperty('color.red.value', "#ff0000"); - expect(output).toHaveProperty('size.large.value', output.size.otherLarge.value); - expect(output).toHaveProperty('size.large.value', "20px"); - - expect(output.number.test.value).toEqual(output.number.otherTest.value); - expect(typeof output.number.otherTest.value).toBe('number'); - expect(output.array.test.value).toEqual(output.array.otherTest.value); - expect(Array.isArray(output.array.otherTest.value)).toBeTruthy(); - expect(output.object.test.value).toMatchObject(output.object.otherTest.value); - expect(typeof output.object.otherTest.value).toBe('object'); + expect(output).to.have.nested.property('color.red.value', output.color.otherRed.value); + expect(output).to.have.nested.property('color.red.value', '#ff0000'); + expect(output).to.have.nested.property('size.large.value', output.size.otherLarge.value); + expect(output).to.have.nested.property('size.large.value', '20px'); + + expect(output.number.test.value).to.eql(output.number.otherTest.value); + expect(typeof output.number.otherTest.value).to.equal('number'); + expect(output.array.test.value).to.eql(output.array.otherTest.value); + expect(Array.isArray(output.array.otherTest.value)).to.be.true; + expect(output.object.test.value).to.eql(output.object.otherTest.value); + expect(typeof output.object.otherTest.value).to.equal('object'); }); - it('should handle non-property nodes', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - source: ['__tests__/__properties/nonPropertyNode.json'], + it('should handle non-property nodes', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + source: ['__tests__/__tokens/nonPropertyNode.json'], platforms: { test: { - buildPath: "__tests__/__output/", - transformGroup: "scss", + buildPath: '__tests__/__output/', + transformGroup: 'scss', files: [ { - "destination": "output.json", - "format": "json" - } - ] - } - } + destination: 'output.json', + format: 'json', + }, + ], + }, + }, }); - StyleDictionaryExtended.buildPlatform('test'); - expect(helpers.fileExists('./__tests__/__output/output.json')).toBeTruthy(); - var input = helpers.fileToJSON('./__tests__/__properties/nonPropertyNode.json'); - var output = helpers.fileToJSON('./__tests__/__output/output.json'); - expect(output.color.key1).toEqual(input.color.key1); - expect(output.color.base.red.key2).toEqual(input.color.base.red.key2); - expect(output.color.base.attributes.key3).toEqual(input.color.base.attributes.key3); + await StyleDictionaryExtended.buildPlatform('test'); + expect(fileExists('__tests__/__output/output.json')).to.be.true; + const input = fileToJSON('__tests__/__tokens/nonPropertyNode.json'); + const output = fileToJSON('__tests__/__output/output.json'); + expect(output.color.key1).to.eql(input.color.key1); + expect(output.color.base.red.key2).to.eql(input.color.base.red.key2); + expect(output.color.base.attributes.key3).to.eql(input.color.base.attributes.key3); }); - it('should handle comments', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - source: ['__tests__/__properties/comment.json'], + it('should handle comments', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + source: ['__tests__/__tokens/comment.json'], platforms: { test: { - buildPath: "__tests__/__output/", - transformGroup: "scss", + buildPath: '__tests__/__output/', + transformGroup: 'scss', files: [ { - "destination": "output.json", - "format": "json" - } - ] - } - } + destination: 'output.json', + format: 'json', + }, + ], + }, + }, }); - StyleDictionaryExtended.buildPlatform('test'); - expect(helpers.fileExists('./__tests__/__output/output.json')).toBeTruthy(); - var input = helpers.fileToJSON('./__tests__/__properties/comment.json'); - var output = helpers.fileToJSON('./__tests__/__output/output.json'); - expect(output.size.large.comment).toEqual(input.size.large.comment); + await StyleDictionaryExtended.buildPlatform('test'); + expect(fileExists('__tests__/__output/output.json')).to.be.true; + const input = fileToJSON('__tests__/__tokens/comment.json'); + const output = fileToJSON('__tests__/__output/output.json'); + expect(output.size.large.comment).to.eql(input.size.large.comment); }); - it('should throw an error if given a transformGroup that doesn\'t exist', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - source: ['__properties/**/*.json'], + it("should throw an error if given a transformGroup that doesn't exist", async () => { + const StyleDictionaryExtended = new StyleDictionary({ + source: ['__tokens/**/*.json'], platforms: { foo: { transformGroup: 'bar', - files: [{ - destination: '__tests__/__output/test.css', - format: 'css/variables' - }] - } - } + files: [ + { + destination: '__tests__/__output/test.css', + format: 'css/variables', + }, + ], + }, + }, }); let err = ` @@ -170,9 +167,6 @@ Unknown transformGroup "bar" found in platform "foo": "bar" does not match the name of a registered transformGroup. `; - expect( - StyleDictionaryExtended.buildPlatform.bind(StyleDictionaryExtended, 'foo') - ).toThrow(err); + await expect(StyleDictionaryExtended.buildPlatform('foo')).to.eventually.rejectedWith(err); }); - }); diff --git a/__tests__/cleanAction.test.js b/__tests__/cleanAction.test.js index b6eea86c4..0c585df35 100644 --- a/__tests__/cleanAction.test.js +++ b/__tests__/cleanAction.test.js @@ -10,45 +10,45 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var helpers = require('./__helpers'); -var fs = require('fs-extra'); -var StyleDictionary = require('../index'); -var StyleDictionaryExtended = StyleDictionary.extend({ - "platforms": { - "android": { - "actions": ["test"] - } - } +import { expect } from 'chai'; +import { fs } from 'style-dictionary/fs'; +import StyleDictionary from 'style-dictionary'; +import { fileExists, clearOutput } from './__helpers.js'; + +const StyleDictionaryExtended = new StyleDictionary({ + platforms: { + android: { + actions: ['cleanAction.test.js'], + files: [], + }, + }, }); StyleDictionaryExtended.registerAction({ - name: 'test', - do: function() { - fs.writeFileSync('./__tests__/__output/action.txt', 'hi') + name: 'cleanAction.test.js', + do: function () { + fs.mkdirSync('__tests__/__output', { recursive: true }); + fs.writeFileSync('__tests__/__output/action.txt', 'hi'); + }, + undo: function () { + fs.unlinkSync('__tests__/__output/action.txt'); }, - undo: function() { - fs.removeSync('./__tests__/__output/action.txt') - } }); describe('cleanAction', () => { - describe('clean actions', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should delete a file properly', () => { - StyleDictionaryExtended.buildPlatform('android'); - StyleDictionaryExtended.cleanPlatform('android'); - expect(helpers.fileDoesNotExist('./__tests__/__output/action.txt')).toBeTruthy(); + it('should delete a file properly', async () => { + await StyleDictionaryExtended.buildPlatform('android'); + await StyleDictionaryExtended.cleanPlatform('android'); + expect(fileExists('__tests__/__output/action.txt')).to.be.false; }); }); - }); diff --git a/__tests__/cleanAllPlatforms.test.js b/__tests__/cleanAllPlatforms.test.js index 27436eefb..d91e06e7d 100644 --- a/__tests__/cleanAllPlatforms.test.js +++ b/__tests__/cleanAllPlatforms.test.js @@ -10,27 +10,26 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fileToJSON, clearOutput, fileExists } from './__helpers.js'; -var helpers = require('./__helpers'); -var config = helpers.fileToJSON(__dirname + '/__configs/test.json'); -var StyleDictionary = require('../index'); -var StyleDictionaryExtended = StyleDictionary.extend(config); +const config = fileToJSON('__tests__/__configs/test.json'); +const StyleDictionaryExtended = new StyleDictionary(config); describe('cleanAllPlatforms', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should work', () => { - StyleDictionaryExtended.buildAllPlatforms(); - StyleDictionaryExtended.cleanAllPlatforms(); - expect(helpers.fileDoesNotExist('./__tests__/__output/web/_icons.scss')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/android/colors.xml')).toBeTruthy(); + it('should work', async () => { + await StyleDictionaryExtended.buildAllPlatforms(); + await StyleDictionaryExtended.cleanAllPlatforms(); + expect(fileExists('__tests__/__output/web/_icons.css')).to.be.false; + expect(fileExists('__tests__/__output/android/colors.xml')).to.be.false; }); - }); diff --git a/__tests__/cleanDir.test.js b/__tests__/cleanDir.test.js index 180c6a95a..3a3aefb94 100644 --- a/__tests__/cleanDir.test.js +++ b/__tests__/cleanDir.test.js @@ -10,32 +10,41 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var helpers = require('./__helpers'); -var buildFile = require('../lib/buildFile'); -var cleanFile = require('../lib/cleanFile'); -var cleanDir = require('../lib/cleanDir'); - -function format() { - return "hi"; -} +import { expect } from 'chai'; +import { clearOutput, dirExists } from './__helpers.js'; +import StyleDictionary from 'style-dictionary'; +import cleanFile from '../dist/esm/cleanFile.mjs'; +import cleanDir from '../dist/esm/cleanDir.mjs'; describe('cleanDir', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should delete a dir properly', () => { - buildFile({destination:'test.txt', format}, {buildPath: '__tests__/__output/extradir1/extradir2/'}, {}); - cleanFile({destination:'test.txt', format}, {buildPath: '__tests__/__output/extradir1/extradir2/'}, {}); - cleanDir({destination:'test.txt', format}, {buildPath: '__tests__/__output/extradir1/extradir2/'}, {}); - expect(helpers.dirDoesNotExist('./__tests__/__output/extradir1/extradir2')).toBeTruthy(); - expect(helpers.dirDoesNotExist('./__tests__/__output/extradir1')).toBeTruthy(); + it('should delete a dir properly', async () => { + const file = { destination: 'test.txt', format: 'foo' }; + const buildPath = '__tests__/__output/extradir1/extradir2/'; + const sd = new StyleDictionary({ + hooks: { + formats: { + foo: () => 'foo', + }, + }, + platforms: { + foo: { + buildPath, + files: [file], + }, + }, + }); + await sd.buildPlatform('foo'); + await cleanFile(file, { buildPath }); + await cleanDir(file, { buildPath }); + expect(dirExists(buildPath)).to.be.false; + expect(dirExists('__tests__/__output/extradir1')).to.be.false; }); - }); diff --git a/__tests__/cleanDirs.test.js b/__tests__/cleanDirs.test.js index 3726410f9..582904753 100644 --- a/__tests__/cleanDirs.test.js +++ b/__tests__/cleanDirs.test.js @@ -10,74 +10,87 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { clearOutput, dirExists } from './__helpers.js'; +import cleanFiles from '../dist/esm/cleanFiles.mjs'; +import cleanDirs from '../dist/esm/cleanDirs.mjs'; +import StyleDictionary from 'style-dictionary'; -var helpers = require('./__helpers'); -var buildFiles = require('../lib/buildFiles'); -var cleanFiles = require('../lib/cleanFiles'); -var cleanDirs = require('../lib/cleanDirs'); - -var dictionary = { - properties: { - foo: 'bar' - } +const dictionary = { + tokens: { + foo: 'bar', + }, }; -var platform = { +const platform = { files: [ { destination: '__tests__/__output/extradir1/extradir2/extradir1/extradir2/test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] + format: 'foo', + }, + ], }; -var platformWithBuildPath = { +const platformWithBuildPath = { buildPath: '__tests__/__output/extradir1/extradir2/', files: [ { destination: 'test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] + format: 'foo', + }, + ], }; describe('cleanDirs', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should delete without buildPath', () => { - buildFiles( dictionary, platform ); - cleanFiles( dictionary, platform ); - cleanDirs( dictionary, platform ); - expect(helpers.dirDoesNotExist('./__tests__/__output/extradir1/extradir2')).toBeTruthy(); - expect(helpers.dirDoesNotExist('./__tests__/__output/extradir1')).toBeTruthy(); + it('should delete without buildPath', async () => { + const sd = new StyleDictionary({ + hooks: { + formats: { + foo: (dictionary) => JSON.stringify(dictionary.tokens), + }, + }, + tokens: dictionary.tokens, + platforms: { + bar: platform, + }, + }); + await sd.buildAllPlatforms(); + await cleanFiles(platform); + await cleanDirs(platform); + expect(dirExists('__tests__/__output/extradir1/extradir2')).to.be.false; + expect(dirExists('__tests__/__output/extradir1')).to.be.false; }); - it('should delete with buildPath', () => { - buildFiles( dictionary, platformWithBuildPath ); - cleanFiles( dictionary, platformWithBuildPath ); - cleanDirs( dictionary, platformWithBuildPath ); - expect(helpers.dirDoesNotExist('./__tests__/__output/extradir1/extradir2')).toBeTruthy(); - expect(helpers.dirDoesNotExist('./__tests__/__output/extradir1')).toBeTruthy(); + it('should delete with buildPath', async () => { + const sd = new StyleDictionary({ + hooks: { + formats: { + foo: (dictionary) => JSON.stringify(dictionary.tokens), + }, + }, + tokens: dictionary.tokens, + platforms: { + bar: platformWithBuildPath, + }, + }); + await sd.buildAllPlatforms(); + await cleanFiles(platformWithBuildPath); + await cleanDirs(platformWithBuildPath); + expect(dirExists('__tests__/__output/extradir1/extradir2')).to.be.false; + expect(dirExists('__tests__/t__/__output/extradir1')).to.be.false; }); - it('should throw if buildPath does not end in a trailing slash', () => { - expect( - function() { - cleanDirs( {}, { - buildPath: "foo" - }) - } - ).toThrow('Build path must end in a trailing slash or you will get weird file names.') - }) + it('should throw if buildPath does not end in a trailing slash', async () => { + await expect(cleanDirs({ buildPath: 'foo' })).to.eventually.rejectedWith( + 'Build path must end in a trailing slash or you will get weird file names.', + ); + }); }); diff --git a/__tests__/cleanFile.test.js b/__tests__/cleanFile.test.js index 8f806c79a..ac296b12a 100644 --- a/__tests__/cleanFile.test.js +++ b/__tests__/cleanFile.test.js @@ -10,35 +10,46 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var helpers = require('./__helpers'); -var buildFile = require('../lib/buildFile'); -var cleanFile = require('../lib/cleanFile'); - -function format() { - return "hi"; -} +import { expect } from 'chai'; +import { fileExists, clearOutput } from './__helpers.js'; +import cleanFile from '../dist/esm/cleanFile.mjs'; +import StyleDictionary from 'style-dictionary'; describe('cleanFile', () => { - + const buildPath = '__tests__/__output/'; beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should delete a file properly', () => { - buildFile({destination:'test.txt', format}, {buildPath: '__tests__/__output/'}, {}); - cleanFile({destination:'test.txt', format}, {buildPath: '__tests__/__output/'}, {}); - expect(helpers.fileDoesNotExist('./__tests__/__output/test.txt')).toBeTruthy(); + it('should delete a file properly', async () => { + const file = { destination: 'test.txt', format: 'foo' }; + const sd = new StyleDictionary({ + hooks: { + formats: { + foo: () => 'hi', + }, + }, + platforms: { + bar: { + buildPath, + files: [file], + }, + }, + }); + await sd.buildPlatform('bar'); + cleanFile(file, { buildPath }); + expect(fileExists('__tests__/__output/test.txt')).to.be.false; }); describe('if a file does not exist', () => { it('should not throw', () => { - expect(() => cleanFile({destination: 'non-existent.txt', format}, { buildPath: '__tests__/__output/' }, {})).not.toThrow(); - }) - }) - + expect(() => + cleanFile({ destination: 'non-existent.txt', format: 'foo' }, { buildPath }, {}), + ).to.not.throw(); + }); + }); }); diff --git a/__tests__/cleanFiles.test.js b/__tests__/cleanFiles.test.js index cf9bd1e27..a91d4c632 100644 --- a/__tests__/cleanFiles.test.js +++ b/__tests__/cleanFiles.test.js @@ -10,59 +10,72 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { clearOutput, fileExists } from './__helpers.js'; +import cleanFiles from '../dist/esm/cleanFiles.mjs'; +import StyleDictionary from 'style-dictionary'; -var helpers = require('./__helpers'); -var buildFiles = require('../lib/buildFiles'); -var cleanFiles = require('../lib/cleanFiles'); +const tokens = { + foo: 'bar', +}; -var dictionary = { - properties: { - foo: 'bar' - } +const hooks = { + formats: { + foo: (dictionary) => JSON.stringify(dictionary.tokens), + }, }; -var platform = { +const platform = { files: [ { destination: '__tests__/__output/test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] + format: 'foo', + }, + ], }; -var platformWithBuildPath = { +const platformWithBuildPath = { buildPath: '__tests__/__output/', files: [ { destination: 'test.json', - format: function(dictionary) { - return JSON.stringify(dictionary.properties) - } - } - ] + format: 'foo', + }, + ], }; describe('cleanFiles', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should delete without buildPath', () => { - buildFiles( dictionary, platform ); - cleanFiles( dictionary, platform ); - expect(helpers.fileDoesNotExist('./__tests__/__output/test.json')).toBeTruthy(); + it('should delete without buildPath', async () => { + const sd = new StyleDictionary({ + hooks, + tokens, + platforms: { + bar: platform, + }, + }); + await sd.buildPlatform('bar'); + await cleanFiles(platform); + expect(fileExists('__tests__/__output/test.json')).to.be.false; }); - it('should delete with buildPath', () => { - buildFiles( dictionary, platformWithBuildPath ); - cleanFiles( dictionary, platformWithBuildPath ); - expect(helpers.fileDoesNotExist('./__tests__/__output/test.json')).toBeTruthy(); + it('should delete with buildPath', async () => { + const sd = new StyleDictionary({ + hooks, + tokens, + platforms: { + bar: platformWithBuildPath, + }, + }); + await sd.buildPlatform('bar'); + cleanFiles(platformWithBuildPath); + expect(fileExists('__tests__/t__/__output/test.json')).to.be.false; }); }); diff --git a/__tests__/cleanPlatform.test.js b/__tests__/cleanPlatform.test.js index fbb6e39cf..43a2170d5 100644 --- a/__tests__/cleanPlatform.test.js +++ b/__tests__/cleanPlatform.test.js @@ -10,45 +10,45 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fileToJSON, clearOutput, fileExists } from './__helpers.js'; -var helpers = require('./__helpers'); -var config = helpers.fileToJSON(__dirname + '/__configs/test.json'); -var StyleDictionary = require('../index'); -var StyleDictionaryExtended = StyleDictionary.extend(config); +const config = fileToJSON('__tests__/__configs/test.json'); +const StyleDictionaryExtended = new StyleDictionary(config); describe('cleanPlatform', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); - it('should delete the proper files', () => { - StyleDictionaryExtended.buildPlatform('web'); - StyleDictionaryExtended.cleanPlatform('web'); - expect(helpers.fileDoesNotExist('./__tests__/__output/web/_icons.scss')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/web/_styles.js')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/web/_variables.scss')).toBeTruthy(); + it('should delete the proper files', async () => { + await StyleDictionaryExtended.buildPlatform('web'); + await StyleDictionaryExtended.cleanPlatform('web'); + expect(fileExists('__tests__/__output/web/_icons.scss')).to.be.false; + expect(fileExists('__tests__/__output/web/_styles.js')).to.be.false; + expect(fileExists('__tests__/__output/web/_variables.scss')).to.be.false; }); - it('should delete android stuff', () => { - StyleDictionaryExtended.buildPlatform('android'); - StyleDictionaryExtended.cleanPlatform('android'); - expect(helpers.fileDoesNotExist('./__tests__/__output/android/main/res/drawable-hdpi/flag_us.png')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/android/main/res/drawable-xhdpi/flag_us.png')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/android/colors.xml')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/android/dimens.xml')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/android/font_dimen.xml')).toBeTruthy(); + it('should delete android stuff', async () => { + await StyleDictionaryExtended.buildPlatform('android'); + await StyleDictionaryExtended.cleanPlatform('android'); + expect(fileExists('__tests__/__output/android/main/res/drawable-hdpi/flag_us.png')).to.be.false; + expect(fileExists('__tests__/__output/android/main/res/drawable-xhdpi/flag_us.png')).to.be + .false; + expect(fileExists('__tests__/__output/android/colors.xml')).to.be.false; + expect(fileExists('__tests__/__output/android/dimens.xml')).to.be.false; + expect(fileExists('__tests__/__output/android/font_dimen.xml')).to.be.false; }); - it('should delete ios stuff', () => { - StyleDictionaryExtended.buildPlatform('ios'); - StyleDictionaryExtended.cleanPlatform('ios'); - expect(helpers.fileDoesNotExist('./__tests__/__output/ios/style_dictionary.plist')).toBeTruthy(); - expect(helpers.fileDoesNotExist('./__tests__/__output/ios/style_dictionary.h')).toBeTruthy(); + it('should delete ios stuff', async () => { + await StyleDictionaryExtended.buildPlatform('ios'); + await StyleDictionaryExtended.cleanPlatform('ios'); + expect(fileExists('__tests__/__output/ios/style_dictionary.plist')).to.be.false; + expect(fileExists('__tests__/__output/ios/style_dictionary.h')).to.be.false; }); - }); diff --git a/__tests__/cliBuild.test.js b/__tests__/cliBuild.test.js deleted file mode 100644 index 9062a8afb..000000000 --- a/__tests__/cliBuild.test.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var childProcess = require("child_process"); -var helpers = require('./__helpers'); - -describe('cliBuildWithJsConfig', () => { - - beforeAll(() => { - helpers.clearOutput(); - childProcess.execSync("node ./bin/style-dictionary build --config ./__tests__/__configs/test.js") - }); - - afterAll(() => { - helpers.clearOutput(); - }); - - it('should work with json config', () => { - expect(helpers.fileExists('./__tests__/__output/web/_icons.css')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/colors.xml')).toBeTruthy(); - }); - - it('should work with javascript config', () => { - expect(helpers.fileExists('./__tests__/__output/web/_icons.css')).toBeTruthy(); - expect(helpers.fileExists('./__tests__/__output/android/colors.xml')).toBeTruthy(); - }); - -}); diff --git a/__tests__/common/filters.test.js b/__tests__/common/filters.test.js index 5ea6f24d9..fe13f29f0 100644 --- a/__tests__/common/filters.test.js +++ b/__tests__/common/filters.test.js @@ -10,40 +10,39 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var filters = require('../../lib/common/filters'); +import { expect } from 'chai'; +import filters from '../../dist/esm/common/filters.mjs'; describe('common', () => { describe('filters', () => { describe('removePrivate', () => { it('should keep a regular token in for distribution', () => { - var regularToken = { + const regularToken = { name: 'color-border', - value: '#1a1aed' - } + value: '#1a1aed', + }; - expect(filters["removePrivate"](regularToken)).toEqual(true); + expect(filters['removePrivate'](regularToken)).to.be.true; }); it('should keep an unfiltered token in for distribution', () => { - var unfilteredToken = { + const unfilteredToken = { name: 'color-border', value: '#1a1aed', - private: false - } + private: false, + }; - expect(filters["removePrivate"](unfilteredToken)).toEqual(true); + expect(filters['removePrivate'](unfilteredToken)).to.be.true; }); - it('should remove a filtered token from the distribution output', () => { - var filteredToken = { + const filteredToken = { name: 'color-border', value: '#1a1aed', - private: true - } + private: true, + }; - expect(filters["removePrivate"](filteredToken)).toEqual(false); + expect(filters['removePrivate'](filteredToken)).to.be.false; }); }); }); diff --git a/__tests__/common/formatHelpers/__snapshots__/createPropertyFormatter.test.snap.js b/__tests__/common/formatHelpers/__snapshots__/createPropertyFormatter.test.snap.js new file mode 100644 index 000000000..0214ef827 --- /dev/null +++ b/__tests__/common/formatHelpers/__snapshots__/createPropertyFormatter.test.snap.js @@ -0,0 +1,100 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; +snapshots["common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 1"] = +` --color-red: #FF0000; /* Foo bar qux */`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 1 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 2"] = +` /** + * Foo + * bar + * qux + */ + --color-blue: #0000FF;`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 2 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 3"] = +`$color-red: #FF0000; // Foo bar qux`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 3 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 4"] = +`// Foo +// bar +// qux +$color-blue: #0000FF;`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle should default to putting comment next to the output value 4 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle allows overriding formatting commentStyle 1"] = +` /* Foo bar qux */ + --color-green: #00FF00;`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle allows overriding formatting commentStyle 1 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle allows overriding formatting commentStyle 2"] = +`// Foo bar qux +$color-green: #00FF00;`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle allows overriding formatting commentStyle 2 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle supports DTCG spec $description property for comments 1"] = +` --color-red: #FF0000; /* Foo bar qux red */`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle supports DTCG spec $description property for comments 1 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle supports DTCG spec $description property for comments 2"] = +` --color-green: #00FF00; /* Foo bar qux green */`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle supports DTCG spec $description property for comments 2 */ + +snapshots["common formatHelpers createPropertyFormatter commentStyle supports DTCG spec $description property for comments 3"] = +` /** + * Foo + * bar + * qux + * blue + */ + --color-blue: #0000FF;`; +/* end snapshot common formatHelpers createPropertyFormatter commentStyle supports DTCG spec $description property for comments 3 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $description property for comments 1"] = +` --color-red: #FF0000; /* Foo bar qux red */`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $description property for comments 1 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $description property for comments 2"] = +` --color-green: #00FF00; /* Foo bar qux green */`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $description property for comments 2 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $description property for comments 3"] = +` /** + * Foo + * bar + * qux + * blue + */ + --color-blue: #0000FF;`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $description property for comments 3 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences 1"] = +` --color-red: #FF0000; /* Foo bar qux red */`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences 1 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences 2"] = +` --color-green: #00FF00; /* Foo bar qux green */`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences 2 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences 3"] = +` /** + * Foo + * bar + * qux + * blue + */ + --color-blue: #0000FF;`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences 3 */ + +snapshots["common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences"] = +` /** + * Foo + * bar + * qux + * ref + */ + --color-ref: var(--color-red);`; +/* end snapshot common formatHelpers createPropertyFormatter DTCG supports DTCG spec $value for outputReferences */ + diff --git a/__tests__/common/formatHelpers/createPropertyFormatter.test.js b/__tests__/common/formatHelpers/createPropertyFormatter.test.js index c9cb40bdd..336179265 100644 --- a/__tests__/common/formatHelpers/createPropertyFormatter.test.js +++ b/__tests__/common/formatHelpers/createPropertyFormatter.test.js @@ -10,96 +10,560 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ -const createPropertyFormatter = require('../../../lib/common/formatHelpers/createPropertyFormatter'); -const createDictionary = require('../../../lib/utils/createDictionary'); - -const dictionary = createDictionary({ - properties: { - tokens: { - foo: { - original: { - value: '5px', - type: 'spacing' - }, - attributes: { - category: 'tokens', - type: 'foo' - }, - name: 'tokens-foo', - path: ['tokens', 'foo'], - value: '5px', - type: 'spacing' - }, - bar: { - original: { - value: '{tokens.foo}', - type: 'spacing' - }, - attributes: { - category: 'tokens', - type: 'bar' - }, - name: 'tokens-bar', - path: ['tokens', 'bar'], - value: '5px', - type: 'spacing' - }, - } - } -}); +import { expect } from 'chai'; +import createPropertyFormatter from '../../../dist/esm/common/formatHelpers/createPropertyFormatter.mjs'; +import flattenTokens from '../../../dist/esm/utils/flattenTokens.mjs'; +import { outputReferencesFilter } from '../../../dist/esm/utils/references/outputReferencesFilter.mjs'; -const transformedDictionary = createDictionary({ - properties: { - tokens: { - foo: { - original: { - value: '5px', - type: 'spacing' - }, - attributes: { - category: 'tokens', - type: 'foo' - }, - name: 'tokens-foo', - path: ['tokens', 'foo'], - value: '5px', - type: 'spacing' - }, - bar: { - original: { - value: '{tokens.foo}', - type: 'spacing' - }, - attributes: { - category: 'tokens', - type: 'bar' - }, - name: 'tokens-bar', - path: ['tokens', 'bar'], - value: 'changed by transitive transform', - type: 'spacing' - }, - } - } -}); +const dictionary = { + foo: { + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + value: '5px', + type: 'spacing', + }, + ref: { + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'ref', + path: ['ref'], + value: '5px', + type: 'spacing', + }, +}; + +const transformedDictionary = { + foo: { + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + value: '5px', + type: 'spacing', + }, + ref: { + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'ref', + path: ['ref'], + value: 'changed by transitive transform', + type: 'spacing', + }, +}; +const numberDictionary = { + foo: { + original: { + value: 10, + type: 'dimension', + }, + name: 'foo', + path: ['foo'], + value: 10, + type: 'dimension', + }, + ref: { + original: { + value: '{foo}', + type: 'dimension', + }, + name: 'ref', + path: ['ref'], + value: 10, + type: 'dimension', + }, + zero: { + original: { + value: 0, + type: 'dimension', + }, + name: 'zero', + path: ['zero'], + value: 0, + type: 'dimension', + }, + 'ref-zero': { + original: { + value: '{zero}', + type: 'dimension', + }, + name: 'ref-zero', + path: ['ref-zero'], + value: 0, + type: 'dimension', + }, +}; +const multiDictionary = { + foo: { + original: { + value: '10px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + value: '10px', + type: 'spacing', + }, + bar: { + original: { + value: '15px', + type: 'spacing', + }, + name: 'bar', + path: ['bar'], + value: '15px', + type: 'spacing', + }, + ref: { + original: { + value: '{foo} 5px {bar}', + type: 'spacing', + }, + name: 'ref', + path: ['ref'], + value: '10px 5px 15px', + type: 'spacing', + }, +}; +const objectDictionary = { + foo: { + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + value: '5px', + type: 'spacing', + }, + ref: { + original: { + value: { + width: '{foo}', + style: 'dashed', + color: '#FF00FF', + }, + type: 'border', + }, + name: 'ref', + path: ['ref'], + value: '5px dashed #FF00FF', + type: 'border', + }, +}; describe('common', () => { describe('formatHelpers', () => { describe('createPropertyFormatter', () => { - it('should support outputReferences', () => { - const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary, format: 'css' }) - expect(propFormatter(dictionary.tokens.tokens.foo)).toEqual(' --tokens-foo: 5px;'); - expect(propFormatter(dictionary.tokens.tokens.bar)).toEqual(' --tokens-bar: var(--tokens-foo);'); - }) - - it('should support outputReferences when values are transformed by (transitive) "value" transforms', () => { - const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary, format: 'css' }) - expect(propFormatter(transformedDictionary.tokens.tokens.foo)).toEqual(' --tokens-foo: 5px;'); - expect(propFormatter(transformedDictionary.tokens.tokens.bar)).toEqual(' --tokens-bar: var(--tokens-foo);'); - }) - }) - }) -}) \ No newline at end of file + describe('outputReferences', () => { + it('should support outputReferences', () => { + const propFormatter = createPropertyFormatter({ + outputReferences: true, + dictionary: { tokens: dictionary }, + format: 'css', + }); + expect(propFormatter(dictionary.foo)).to.equal(' --foo: 5px;'); + expect(propFormatter(dictionary.ref)).to.equal(' --ref: var(--foo);'); + }); + + it('should support outputReferences when values are transformed by (transitive) "value" transforms', () => { + const propFormatter = createPropertyFormatter({ + outputReferences: true, + dictionary: { tokens: transformedDictionary }, + format: 'css', + }); + expect(propFormatter(transformedDictionary.foo)).to.equal(' --foo: 5px;'); + expect(propFormatter(transformedDictionary.ref)).to.equal(' --ref: var(--foo);'); + }); + + it('should support number values for outputReferences', () => { + const propFormatter = createPropertyFormatter({ + outputReferences: true, + dictionary: { tokens: numberDictionary }, + format: 'css', + }); + expect(propFormatter(numberDictionary.foo)).to.equal(' --foo: 10;'); + expect(propFormatter(numberDictionary.ref)).to.equal(' --ref: var(--foo);'); + }); + + it('should support valid falsy values for outputReferences', () => { + const propFormatter = createPropertyFormatter({ + outputReferences: true, + dictionary: { tokens: numberDictionary }, + format: 'css', + }); + expect(propFormatter(numberDictionary.zero)).to.equal(' --zero: 0;'); + expect(propFormatter(numberDictionary['ref-zero'])).to.equal( + ' --ref-zero: var(--zero);', + ); + }); + + it('should support multiple references for outputReferences', () => { + const propFormatter = createPropertyFormatter({ + outputReferences: true, + dictionary: { tokens: multiDictionary }, + format: 'css', + }); + expect(propFormatter(multiDictionary.foo)).to.equal(' --foo: 10px;'); + expect(propFormatter(multiDictionary.bar)).to.equal(' --bar: 15px;'); + expect(propFormatter(multiDictionary.ref)).to.equal( + ' --ref: var(--foo) 5px var(--bar);', + ); + }); + + it('should support conditionally outputting references', () => { + const unfilteredTokens = { + foo: { + value: '5px', + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + type: 'spacing', + }, + bar: { + value: '5px', + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'bar', + path: ['bar'], + type: 'spacing', + }, + qux: { + value: '5px', + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'qux', + path: ['qux'], + type: 'spacing', + }, + }; + const tokens = { ...unfilteredTokens }; + const allTokens = flattenTokens(tokens); + const propFormatter = createPropertyFormatter({ + dictionary: { + tokens, + unfilteredTokens, + allTokens, + }, + format: 'css', + // outputReferences function that only outputs the refs if the token name is "bar" + outputReferences: (token) => token.name === 'bar', + }); + expect(propFormatter(tokens.bar)).to.equal(' --bar: var(--foo);'); + expect(propFormatter(tokens.qux)).to.equal(' --qux: 5px;'); + }); + + it('should make it easy to not output refs for tokens that contains refs that are filtered out', () => { + const unfilteredTokens = { + foo: { + value: '5px', + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + type: 'spacing', + }, + bar: { + value: '10px', + original: { + value: '10px', + type: 'spacing', + }, + name: 'bar', + path: ['bar'], + type: 'spacing', + }, + 'ref foo': { + value: '5px', + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'ref-foo', + path: ['ref foo'], + type: 'spacing', + }, + 'ref bar': { + value: '10px', + original: { + value: '{bar}', + type: 'spacing', + }, + name: 'ref-bar', + path: ['ref bar'], + type: 'spacing', + }, + }; + const tokens = { ...unfilteredTokens }; + delete tokens.foo; + const allTokens = flattenTokens(tokens); + const propFormatter = createPropertyFormatter({ + dictionary: { + tokens, + unfilteredTokens, + allTokens, + }, + format: 'css', + // outputReferences function that only outputs the refs if the referred tokens are not filtered out + outputReferences: outputReferencesFilter, + }); + + expect(propFormatter(tokens['ref foo'])).to.equal(' --ref-foo: 5px;'); + expect(propFormatter(tokens['ref bar'])).to.equal(' --ref-bar: var(--bar);'); + }); + + it('DTCG: should make it easy to not output refs for tokens that contains refs that are filtered out', () => { + const unfilteredTokens = { + foo: { + $value: '5px', + original: { + $value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + $type: 'spacing', + }, + bar: { + $value: '10px', + original: { + $value: '10px', + $type: 'spacing', + }, + name: 'bar', + path: ['bar'], + $type: 'spacing', + }, + 'ref foo': { + $value: '5px', + original: { + $value: '{foo}', + $type: 'spacing', + }, + name: 'ref-foo', + path: ['ref foo'], + $type: 'spacing', + }, + 'ref bar': { + $value: '10px', + original: { + $value: '{bar}', + $type: 'spacing', + }, + name: 'ref-bar', + path: ['ref bar'], + $type: 'spacing', + }, + }; + const tokens = { ...unfilteredTokens }; + delete tokens.foo; + const allTokens = flattenTokens(tokens, true); + const propFormatter = createPropertyFormatter({ + dictionary: { + tokens, + unfilteredTokens, + allTokens, + }, + format: 'css', + usesDtcg: true, + // outputReferences function that only outputs the refs if the referred tokens are not filtered out + outputReferences: outputReferencesFilter, + }); + + expect(propFormatter(tokens['ref foo'])).to.equal(' --ref-foo: 5px;'); + expect(propFormatter(tokens['ref bar'])).to.equal(' --ref-bar: var(--bar);'); + }); + + it('should support object value references for outputReferences', () => { + // The ref is an object type value, which means there will usually be some kind of transform (e.g. a CSS shorthand transform) + // to change it from an object to a string. In our example, we use a border CSS shorthand for border token. + // In this case, since it is an object value, we will run the transformation on the transformed (string) value. + const propFormatter = createPropertyFormatter({ + outputReferences: true, + dictionary: { tokens: objectDictionary }, + format: 'css', + }); + // expect(propFormatter(objectDictionary.tokens.foo)).to.equal(' --foo: 5px;'); + + expect(propFormatter(objectDictionary.ref)).to.equal( + ' --ref: var(--foo) dashed #FF00FF;', + ); + }); + }); + + describe('commentStyle', () => { + const commentDictionary = { + color: { + red: { + name: 'color-red', + value: '#FF0000', + comment: 'Foo bar qux', + path: ['color', 'red'], + original: { + value: '#FF0000', + }, + }, + green: { + name: 'color-green', + value: '#00FF00', + comment: 'Foo bar qux', + path: ['color', 'green'], + original: { + value: '#00FF00', + }, + }, + blue: { + name: 'color-blue', + value: '#0000FF', + comment: 'Foo\nbar\nqux', + path: ['color', 'blue'], + original: { + value: '#0000FF', + }, + }, + }, + }; + + it('should default to putting comment next to the output value', async () => { + // long commentStyle + const cssFormatter = createPropertyFormatter({ + format: 'css', + dictionary: { tokens: commentDictionary }, + }); + // short commentStyle + const sassFormatter = createPropertyFormatter({ + format: 'sass', + dictionary: { tokens: commentDictionary }, + }); + + // red = single-line comment, blue = multi-line comment + const cssRed = cssFormatter(commentDictionary.color.red); + const cssBlue = cssFormatter(commentDictionary.color.blue); + const sassRed = sassFormatter(commentDictionary.color.red); + const sassBlue = sassFormatter(commentDictionary.color.blue); + + await expect(cssRed).to.matchSnapshot(1); + await expect(cssBlue).to.matchSnapshot(2); + + await expect(sassRed).to.matchSnapshot(3); + await expect(sassBlue).to.matchSnapshot(4); + }); + + it('allows overriding formatting commentStyle', async () => { + // long commentStyle + const cssFormatter = createPropertyFormatter({ + format: 'css', + dictionary: { tokens: commentDictionary }, + formatting: { commentStyle: 'long', commentPosition: 'above' }, + }); + // short commentStyle + const sassFormatter = createPropertyFormatter({ + format: 'sass', + dictionary: { tokens: commentDictionary }, + formatting: { commentStyle: 'short', commentPosition: 'above' }, + }); + + const cssRed = cssFormatter(commentDictionary.color.green); + const sassRed = sassFormatter(commentDictionary.color.green); + + await expect(cssRed).to.matchSnapshot(1); + await expect(sassRed).to.matchSnapshot(2); + }); + }); + + describe('DTCG', () => { + const dtcgDictionary = { + color: { + red: { + name: 'color-red', + $value: '#FF0000', + original: { + $value: '#FF0000', + }, + $description: 'Foo bar qux red', + path: ['color', 'red'], + }, + green: { + name: 'color-green', + $value: '#00FF00', + original: { + $value: '#00FF00', + }, + $description: 'Foo bar qux green', + path: ['color', 'green'], + }, + blue: { + name: 'color-blue', + $value: '#0000FF', + original: { + $value: '#0000FF', + }, + $description: 'Foo\nbar\nqux\nblue', + path: ['color', 'blue'], + }, + ref: { + name: 'color-ref', + $value: '#FF0000', + original: { + $value: '{color.red}', + }, + $description: 'Foo\nbar\nqux\nref', + path: ['color', 'ref'], + }, + }, + }; + it('supports DTCG spec $description property for comments', async () => { + // long commentStyle + const cssFormatter = createPropertyFormatter({ + format: 'css', + dictionary: { tokens: dtcgDictionary }, + usesDtcg: true, + }); + + const cssRed = cssFormatter(dtcgDictionary.color.red); + const cssGreen = cssFormatter(dtcgDictionary.color.green); + const cssBlue = cssFormatter(dtcgDictionary.color.blue); + + await expect(cssRed).to.matchSnapshot(1); + await expect(cssGreen).to.matchSnapshot(2); + await expect(cssBlue).to.matchSnapshot(3); + }); + + it('supports DTCG spec $value for outputReferences', async () => { + // long commentStyle + const cssFormatter = createPropertyFormatter({ + format: 'css', + outputReferences: true, + dictionary: { tokens: dtcgDictionary }, + usesDtcg: true, + }); + + const cssRef = cssFormatter(dtcgDictionary.color.ref); + + await expect(cssRef).to.matchSnapshot(); + }); + }); + }); + }); +}); diff --git a/__tests__/common/formatHelpers/fileHeader.test.js b/__tests__/common/formatHelpers/fileHeader.test.js index 6474241b8..9c2f46816 100644 --- a/__tests__/common/formatHelpers/fileHeader.test.js +++ b/__tests__/common/formatHelpers/fileHeader.test.js @@ -10,116 +10,129 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { fixDate } from '../../__helpers.js'; +import fileHeader from '../../../dist/esm/common/formatHelpers/fileHeader.mjs'; -const fileHeader = require('../../../lib/common/formatHelpers/fileHeader'); - -const defaultLine1 = `Do not edit directly`; +const defaultLine1 = `Do not edit directly, this file was auto-generated.`; const defaultLine2 = `Generated on Sat, 01 Jan 2000 00:00:00 GMT`; describe('common', () => { describe('formatHelpers', () => { + beforeEach(() => { + // reset Date again, for some reasons these tests are flaky otherwise in the pipelines + fixDate(); + }); describe('fileHeader', () => { - it(`should default to /**/ comment style`, () => { - const comment = fileHeader({}); - expect(comment).toEqual( -`/** + it(`should default to /**/ comment style`, async () => { + const comment = await fileHeader({}); + expect(comment).to.equal( + `/** + * ${defaultLine1} + */ + +`, + ); + }); + + it(`should allow adding timestamp to the fileheader`, async () => { + const comment = await fileHeader({ formatting: { fileHeaderTimestamp: true } }); + expect(comment).to.equal( + `/** * ${defaultLine1} * ${defaultLine2} */ -`); +`, + ); }); - it(`should handle commentStyle short`, () => { - const comment = fileHeader({commentStyle: 'short'}); - expect(comment).toEqual( -` + it(`should handle commentStyle short`, async () => { + const comment = await fileHeader({ commentStyle: 'short' }); + expect(comment).to.equal( + ` // ${defaultLine1} -// ${defaultLine2} -`); +`, + ); }); - it(`should handle commentStyle xml`, () => { - const comment = fileHeader({commentStyle: 'xml'}); - expect(comment).toEqual( -``); +-->`, + ); }); - it(`should handle showFileHeader option`, () => { - const comment = fileHeader({ + it(`should handle showFileHeader option`, async () => { + const comment = await fileHeader({ file: { options: { - showFileHeader: false - } - } + showFileHeader: false, + }, + }, }); - expect(comment).toEqual(''); + expect(comment).to.equal(''); }); - it(`should handle custom fileHeader function`, () => { - const comment = fileHeader({ + it(`should handle custom fileHeader function`, async () => { + const comment = await fileHeader({ file: { options: { fileHeader: () => { - return [ - `Never gonna give you up`, - `Never gonna let you down` - ] - } - } - } + return [`Never gonna give you up`, `Never gonna let you down`]; + }, + }, + }, }); - expect(comment).toEqual( -`/** + expect(comment).to.equal( + `/** * Never gonna give you up * Never gonna let you down */ -`); +`, + ); }); - it(`should handle custom fileHeader function with default`, () => { - const comment = fileHeader({ + it(`should handle custom fileHeader function with default`, async () => { + const comment = await fileHeader({ file: { options: { fileHeader: (defaultMessage) => { - return [ - ...defaultMessage, - `Never gonna give you up`, - `Never gonna let you down` - ] - } - } - } + return [...defaultMessage, `Never gonna give you up`, `Never gonna let you down`]; + }, + }, + }, }); - expect(comment).toEqual( -`/** + expect(comment).to.equal( + `/** * ${defaultLine1} - * ${defaultLine2} * Never gonna give you up * Never gonna let you down */ -`); +`, + ); }); - it('should handle custom formatting', () => { - const comment = fileHeader({formatting: { - prefix: ` `, - header: `{#\n`, - footer: `\n#}` - }}); - expect(comment).toEqual( -`{# + it('should handle custom formatting', async () => { + const comment = await fileHeader({ + formatting: { + prefix: ` `, + header: `{#\n`, + footer: `\n#}`, + }, + }); + expect(comment).to.equal( + `{# ${defaultLine1} - ${defaultLine2} -#}`); +#}`, + ); }); }); }); -}); \ No newline at end of file +}); diff --git a/__tests__/common/formatHelpers/getTypeScriptType.test.js b/__tests__/common/formatHelpers/getTypeScriptType.test.js index bceabfb6b..7d38a1272 100644 --- a/__tests__/common/formatHelpers/getTypeScriptType.test.js +++ b/__tests__/common/formatHelpers/getTypeScriptType.test.js @@ -10,47 +10,62 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const getTypeScriptType = require('../../../lib/common/formatHelpers/getTypeScriptType'); +import { expect } from 'chai'; +import getTypeScriptType from '../../../dist/esm/common/formatHelpers/getTypeScriptType.mjs'; describe('common', () => { describe('formatHelpers', () => { describe('getTypeScriptType', () => { it('should recognize basic types', () => { - expect(getTypeScriptType('a string')).toEqual('string'); - expect(getTypeScriptType(3.14159)).toEqual('number'); - expect(getTypeScriptType(true)).toEqual('boolean'); + expect(getTypeScriptType('a string')).to.equal('string'); + expect(getTypeScriptType(3.14159)).to.equal('number'); + expect(getTypeScriptType(true)).to.equal('boolean'); }); it('should recognize arrays consisting out of same-type primitives', () => { - expect(getTypeScriptType(['an', 'array', 'of', 'strings'])).toEqual('string[]'); - expect(getTypeScriptType([3.14159])).toEqual('number[]'); - expect(getTypeScriptType([true, false, true, true])).toEqual('boolean[]'); + expect(getTypeScriptType(['an', 'array', 'of', 'strings'])).to.equal('string[]'); + expect(getTypeScriptType([3.14159])).to.equal('number[]'); + expect(getTypeScriptType([true, false, true, true])).to.equal('boolean[]'); }); it('should recognize arrays consisting out of different primitives', () => { - expect(getTypeScriptType(['string', 3.14, false])).toEqual('(string | number | boolean)[]'); + expect(getTypeScriptType(['string', 3.14, false])).to.equal( + '(string | number | boolean)[]', + ); }); it('should support nested arrays', () => { - expect(getTypeScriptType([[100, 200], [300, 400]])).toEqual('number[][]'); + expect( + getTypeScriptType([ + [100, 200], + [300, 400], + ]), + ).to.equal('number[][]'); }); it('should handle simple object types', () => { - expect(getTypeScriptType({})).toEqual('{ }'); - expect(getTypeScriptType({ property1: '', property2: false })).toEqual('{ property1: string, property2: boolean }'); + expect(getTypeScriptType({})).to.equal('{ }'); + expect(getTypeScriptType({ property1: '', property2: false })).to.equal( + '{ property1: string, property2: boolean }', + ); }); it('should handle complex object types', () => { - const complexObject = { property1: 'foo', property2: ['foo', 'bar'], property3: { subProperty1: 'foo', subProperty2: ['foo', 'bar', 1], } } - expect(getTypeScriptType(complexObject)).toEqual('{ property1: string, property2: string[], property3: { subProperty1: string, subProperty2: (string | number)[] } }'); + const complexObject = { + property1: 'foo', + property2: ['foo', 'bar'], + property3: { subProperty1: 'foo', subProperty2: ['foo', 'bar', 1] }, + }; + expect(getTypeScriptType(complexObject)).to.equal( + '{ property1: string, property2: string[], property3: { subProperty1: string, subProperty2: (string | number)[] } }', + ); }); it('should handle outputStringLiterals', () => { - const stringValue = 'I am a string'; - const options = { outputStringLiterals: true}; - expect(getTypeScriptType(stringValue, options)).toEqual(`"${stringValue}"`); + const stringValue = 'I "am" a string'; + const options = { outputStringLiterals: true }; + expect(getTypeScriptType(stringValue, options)).to.equal('"I \\"am\\" a string"'); }); }); }); -}); \ No newline at end of file +}); diff --git a/__tests__/common/formatHelpers/setSwiftFileProperties.test.js b/__tests__/common/formatHelpers/setSwiftFileProperties.test.js index 26263fef0..d36278ee4 100644 --- a/__tests__/common/formatHelpers/setSwiftFileProperties.test.js +++ b/__tests__/common/formatHelpers/setSwiftFileProperties.test.js @@ -10,42 +10,48 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const setSwiftFileProperties = require('../../../lib/common/formatHelpers/setSwiftFileProperties'); +import { expect } from 'chai'; +import setSwiftFileProperties from '../../../dist/esm/common/formatHelpers/setSwiftFileProperties.mjs'; describe('common', () => { describe('formatHelpers', () => { - describe('setSwiftFileProperties', () => { it('should default accessControl be public', () => { const file = setSwiftFileProperties({}, undefined, 'ios-swift'); - expect(file.accessControl).toEqual('public '); + expect(file.accessControl).to.equal('public'); }); it('should default objectType be class', () => { const file = setSwiftFileProperties({}, undefined, 'ios-swift'); - expect(file.objectType).toEqual('class'); + expect(file.objectType).to.equal('class'); }); it('should default import be ["UIKit"]', () => { const file = setSwiftFileProperties({}, undefined, 'ios-swift'); const fileSeparate = setSwiftFileProperties({}, undefined, 'ios-swift-separate'); - expect(file.import).toEqual(['UIKit']); - expect(fileSeparate.import).toEqual(['UIKit']); + expect(file.import).to.eql(['UIKit']); + expect(fileSeparate.import).to.eql(['UIKit']); }); it('should transform string import to array', () => { const file = setSwiftFileProperties({ import: 'SwiftUI' }, undefined, 'ios-swift'); - expect(file.import).toEqual(['SwiftUI']); + expect(file.import).to.eql(['SwiftUI']); }); it('should file be properly configured', () => { - const file = setSwiftFileProperties({ objectType: 'extension', import: ['SwiftUI'], accessControl: 'public'}, undefined, 'ios-swift'); - expect(file.objectType).toEqual('extension'); - expect(file.import).toEqual(['SwiftUI']); - expect(file.accessControl).toEqual('public '); + const file = setSwiftFileProperties( + { + objectType: 'extension', + import: ['SwiftUI'], + accessControl: 'public', + }, + undefined, + 'ios-swift', + ); + expect(file.objectType).to.equal('extension'); + expect(file.import).to.eql(['SwiftUI']); + expect(file.accessControl).to.equal('public'); }); - }); - }) -}) \ No newline at end of file + }); +}); diff --git a/__tests__/common/transforms.test.js b/__tests__/common/transforms.test.js index c69edf3a3..c99d8be07 100644 --- a/__tests__/common/transforms.test.js +++ b/__tests__/common/transforms.test.js @@ -10,782 +10,1430 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var transforms = require('../../lib/common/transforms'); -var path = require('path'); -var Color = require('tinycolor2'); +import { expect } from 'chai'; +import { join } from 'path-unified'; +import Color from 'tinycolor2'; +import transforms, { isColor } from '../../dist/esm/common/transforms.mjs'; describe('common', () => { describe('transforms', () => { - - describe('name/cti/camel', () => { - it('should handle prefix', () => { - expect(transforms["name/cti/camel"].transformer( - { - path: ['one','two','three'] - },{ - prefix: 'prefix' - } - )).toBe('prefixOneTwoThree'); - }); - - it('should handle no prefix', () => { - expect(transforms["name/cti/camel"].transformer( - { - path: ['one','two','three'] - },{ - } - )).toBe('oneTwoThree'); - }); - }); - - describe('name/ti/camel', () => { - it('should handle prefix', () => { - expect(transforms["name/ti/camel"].transformer( - { - path: ['one','two','three'] - },{ - prefix: 'prefix' - } - )).toBe('prefixTwoThree'); - }); - - it('should handle no prefix', () => { - expect(transforms["name/ti/camel"].transformer( - { - path: ['one','two','three'] - },{ - } - )).toBe('twoThree'); - }); - }); - - describe('name/cti/kebab', () => { + describe('name/camel', () => { it('should handle prefix', () => { - expect(transforms["name/cti/kebab"].transformer( - { - path: ['one','two','three'] - },{ - prefix: 'prefix' - } - )).toBe('prefix-one-two-three'); + expect( + transforms['name/camel'].transform( + { + path: ['one', 'two', 'three'], + }, + { + prefix: 'prefix', + }, + ), + ).to.equal('prefixOneTwoThree'); }); it('should handle no prefix', () => { - expect(transforms["name/cti/kebab"].transformer( - { - path: ['one','two','three'] - },{ - } - )).toBe('one-two-three'); + expect( + transforms['name/camel'].transform( + { + path: ['one', 'two', 'three'], + }, + {}, + ), + ).to.equal('oneTwoThree'); }); }); - describe('name/cti/snake', () => { + describe('name/kebab', () => { it('should handle prefix', () => { - expect(transforms["name/cti/snake"].transformer( - { - path: ['one','two','three'] - },{ - prefix: 'prefix' - } - )).toBe('prefix_one_two_three'); + expect( + transforms['name/kebab'].transform( + { + path: ['one', 'two', 'three'], + }, + { + prefix: 'prefix', + }, + ), + ).to.equal('prefix-one-two-three'); }); it('should handle no prefix', () => { - expect(transforms["name/cti/snake"].transformer( - { - path: ['one','two','three'] - },{ - } - )).toBe('one_two_three'); + expect( + transforms['name/kebab'].transform( + { + path: ['one', 'two', 'three'], + }, + {}, + ), + ).to.equal('one-two-three'); }); }); - describe('name/cti/constant', () => { + describe('name/snake', () => { it('should handle prefix', () => { - expect(transforms["name/cti/constant"].transformer( - { - path: ['one','two','three'] - },{ - prefix: 'prefix' - } - )).toBe('PREFIX_ONE_TWO_THREE'); + expect( + transforms['name/snake'].transform( + { + path: ['one', 'two', 'three'], + }, + { + prefix: 'prefix', + }, + ), + ).to.equal('prefix_one_two_three'); }); it('should handle no prefix', () => { - expect(transforms["name/cti/constant"].transformer( - { - path: ['one','two','three'] - },{ - } - )).toBe('ONE_TWO_THREE'); + expect( + transforms['name/snake'].transform( + { + path: ['one', 'two', 'three'], + }, + {}, + ), + ).to.equal('one_two_three'); }); }); - describe('name/ti/constant', () => { + describe('name/constant', () => { it('should handle prefix', () => { - expect(transforms["name/ti/constant"].transformer( - { - path: ['one','two','three'] - },{ - prefix: 'prefix' - } - )).toBe('PREFIX_TWO_THREE'); + expect( + transforms['name/constant'].transform( + { + path: ['one', 'two', 'three'], + }, + { + prefix: 'prefix', + }, + ), + ).to.equal('PREFIX_ONE_TWO_THREE'); }); it('should handle no prefix', () => { - expect(transforms["name/ti/constant"].transformer( - { - path: ['one','two','three'] - },{ - } - )).toBe('TWO_THREE'); + expect( + transforms['name/constant'].transform( + { + path: ['one', 'two', 'three'], + }, + {}, + ), + ).to.equal('ONE_TWO_THREE'); }); }); describe('attribute/color', () => { it('should handle normal colors', () => { - var attributes = transforms["attribute/color"].transformer({ - value: "#aaaaaa" - }); - expect(attributes).toHaveProperty('rgb.a', 1); - expect(attributes).toHaveProperty('rgb.r', 170); - expect(attributes).toHaveProperty('hsl.s', 0); + const attributes = transforms['attribute/color'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(attributes).to.have.nested.property('rgb.a', 1); + expect(attributes).to.have.nested.property('rgb.r', 170); + expect(attributes).to.have.nested.property('hsl.s', 0); }); it('should handle colors with transparency', () => { - var attributes = transforms["attribute/color"].transformer({ - value: "#aaaaaa99" - }); - var attributes2 = transforms["attribute/color"].transformer({ - value: "rgba(170,170,170,0.6)" - }); - expect(attributes).toHaveProperty('rgb.a', 0.6); - expect(attributes).toHaveProperty('rgb.r', 170); - expect(attributes).toHaveProperty('hsl.s', 0); - expect(attributes2).toHaveProperty('rgb.a', 0.6); - expect(attributes2).toHaveProperty('rgb.r', 170); - expect(attributes2).toHaveProperty('hsl.s', 0); + const attributes = transforms['attribute/color'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + const attributes2 = transforms['attribute/color'].transform( + { + value: 'rgba(170,170,170,0.6)', + }, + {}, + {}, + ); + expect(attributes).to.have.nested.property('rgb.a', 0.6); + expect(attributes).to.have.nested.property('rgb.r', 170); + expect(attributes).to.have.nested.property('hsl.s', 0); + expect(attributes2).to.have.nested.property('rgb.a', 0.6); + expect(attributes2).to.have.nested.property('rgb.r', 170); + expect(attributes2).to.have.nested.property('hsl.s', 0); }); }); describe('transform', () => { describe('attribute/cti', () => { - const prop = { - "path": ["color", "background", "button", "primary", "active", "extra"], + path: ['color', 'background', 'button', 'primary', 'active', 'extra'], }; - const propShort = { "path": ["color", "primary"] }; + const propShort = { path: ['color', 'primary'] }; const propOverride = { - "path": ["button", "primary", "border", "width"], - "attributes": { "category": "size", "component": "button" } + path: ['button', 'primary', 'border', 'width'], + attributes: { category: 'size', component: 'button' }, }; - const attrs = transforms["attribute/cti"].transformer(prop); - const attrsShort = transforms["attribute/cti"].transformer(propShort); - const attrsOverride = transforms["attribute/cti"].transformer(propOverride); + const attrs = transforms['attribute/cti'].transform(prop, {}, {}); + const attrsShort = transforms['attribute/cti'].transform(propShort, {}, {}); + const attrsOverride = transforms['attribute/cti'].transform(propOverride, {}, {}); it('should assign attributes correctly', () => { - expect(attrs).toEqual({ - "category": "color", - "type": "background", - "item": "button", - "subitem": "primary", - "state": "active" + expect(attrs).eql({ + category: 'color', + type: 'background', + item: 'button', + subitem: 'primary', + state: 'active', }); }); - it('should not assign path props when path is short' , () => { - expect(attrsShort).toEqual({ - "category": "color", - "type": "primary" + it('should not assign path props when path is short', () => { + expect(attrsShort).eql({ + category: 'color', + type: 'primary', }); }); it('should leave other attributes alone', () => { - expect(attrsOverride).toHaveProperty('component', 'button'); + expect(attrsOverride).to.have.property('component', 'button'); }); it('should not override previously assigned path attributes', () => { - expect(attrsOverride).toHaveProperty('category', 'size'); + expect(attrsOverride).to.have.property('category', 'size'); }); }); }); describe('color/hex', () => { it('should handle hex colors', () => { - var value = transforms["color/hex"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("#aaaaaa"); + const value = transforms['color/hex'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaa'); }); it('should handle hex8 colors', () => { - var value = transforms["color/hex"].transformer({ - value: "#aaaaaaaa" - }); - expect(value).toBe("#aaaaaa"); + const value = transforms['color/hex'].transform( + { + value: '#aaaaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaa'); }); it('should handle rgb colors', () => { - var value = transforms["color/hex"].transformer({ - value: "rgb(170,170,170)" - }); - expect(value).toBe("#aaaaaa"); + const value = transforms['color/hex'].transform( + { + value: 'rgb(170,170,170)', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaa'); }); it('should handle rgb (object) colors', () => { - var value = transforms["color/hex"].transformer({ - value: { - r: '170', - g: '170', - b: '170' - } - }); - var value2 = transforms["color/hex"].transformer({ - value: "rgb(170,170,170)" - }); - expect(value).toBe("#aaaaaa"); - expect(value2).toBe("#aaaaaa"); + const value = transforms['color/hex'].transform( + { + value: { + r: '170', + g: '170', + b: '170', + }, + }, + {}, + {}, + ); + const value2 = transforms['color/hex'].transform( + { + value: 'rgb(170,170,170)', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaa'); + expect(value2).to.equal('#aaaaaa'); }); it('should handle hsl colors', () => { - var value = transforms["color/hex"].transformer({ - value: { - h: '0', - s: '0', - l: '0.5' - } - }); - var value2 = transforms["color/hex"].transformer({ - value: "hsl(0,0,0.5)" - }); - expect(value).toBe("#808080"); - expect(value2).toBe("#808080"); + const value = transforms['color/hex'].transform( + { + value: { + h: '0', + s: '0', + l: '0.5', + }, + }, + {}, + {}, + ); + const value2 = transforms['color/hex'].transform( + { + value: 'hsl(0,0,0.5)', + }, + {}, + {}, + ); + expect(value).to.equal('#808080'); + expect(value2).to.equal('#808080'); }); }); - describe('color/hex8', () => { it('should handle hex colors', () => { - var value = transforms["color/hex8"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("#aaaaaaff"); + const value = transforms['color/hex8'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaaff'); }); it('should handle rgb colors', () => { - var value = transforms["color/hex8"].transformer({ - value: "rgb(170,170,170)" - }); - expect(value).toBe("#aaaaaaff"); + const value = transforms['color/hex8'].transform( + { + value: 'rgb(170,170,170)', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaaff'); }); it('should handle rgba colors', () => { - var value = transforms["color/hex8"].transformer({ - value: "rgba(170,170,170,0.6)" - }); - expect(value).toBe("#aaaaaa99"); + const value = transforms['color/hex8'].transform( + { + value: 'rgba(170,170,170,0.6)', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaa99'); }); }); describe('color/hex8android', () => { it('should handle colors without alpha', () => { - var value = transforms["color/hex8android"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("#ffaaaaaa"); + const value = transforms['color/hex8android'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('#ffaaaaaa'); }); it('should handle colors with alpha', () => { - var value = transforms["color/hex8android"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("#99aaaaaa"); + const value = transforms['color/hex8android'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal('#99aaaaaa'); }); }); describe('color/rgb', () => { it('should handle normal colors', () => { - var value = transforms["color/rgb"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("rgb(170, 170, 170)"); + const value = transforms['color/rgb'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('rgb(170, 170, 170)'); }); it('should handle colors with transparency', () => { - var value = transforms["color/rgb"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("rgba(170, 170, 170, 0.6)"); + const value = transforms['color/rgb'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal('rgba(170, 170, 170, 0.6)'); }); }); describe('color/hsl-4', () => { it('should handle normal colors', () => { - var value = transforms["color/hsl-4"].transformer({ - value: "#009688" - }); - expect(value).toBe("hsl(174 100% 29%)"); + const value = transforms['color/hsl-4'].transform( + { + value: '#009688', + }, + {}, + {}, + ); + expect(value).to.equal('hsl(174 100% 29%)'); }); it('should handle colors with transparency', () => { - var value = transforms["color/hsl-4"].transformer({ - value: "#00968899" - }); - expect(value).toBe("hsl(174 100% 29% / 0.6)"); + const value = transforms['color/hsl-4'].transform( + { + value: '#00968899', + }, + {}, + {}, + ); + expect(value).to.equal('hsl(174 100% 29% / 0.6)'); }); }); describe('color/hsl', () => { it('should handle normal colors', () => { - var value = transforms["color/hsl"].transformer({ - value: "#009688" - }); - expect(value).toBe("hsl(174, 100%, 29%)"); + const value = transforms['color/hsl'].transform( + { + value: '#009688', + }, + {}, + {}, + ); + expect(value).to.equal('hsl(174, 100%, 29%)'); }); it('should handle colors with transparency', () => { - var value = transforms["color/hsl"].transformer({ - value: "#00968899" - }); - expect(value).toBe("hsla(174, 100%, 29%, 0.6)"); + const value = transforms['color/hsl'].transform( + { + value: '#00968899', + }, + {}, + {}, + ); + expect(value).to.equal('hsla(174, 100%, 29%, 0.6)'); }); }); describe('color/composeColor', () => { it('should handle color without alpha', () => { - var value = transforms["color/composeColor"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("Color(0xffaaaaaa)"); + const value = transforms['color/composeColor'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('Color(0xffaaaaaa)'); }); it('should handle color with alpha', () => { - var value = transforms["color/composeColor"].transformer({ - value: "#aaaaaaff" - }); - expect(value).toBe("Color(0xffaaaaaa)"); + const value = transforms['color/composeColor'].transform( + { + value: '#aaaaaaff', + }, + {}, + {}, + ); + expect(value).to.equal('Color(0xffaaaaaa)'); }); - }); describe('color/UIColor', () => { it('should handle normal colors', () => { - var value = transforms["color/UIColor"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("[UIColor colorWithRed:0.667f green:0.667f blue:0.667f alpha:1.000f]"); + const value = transforms['color/UIColor'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal( + '[UIColor colorWithRed:0.667f green:0.667f blue:0.667f alpha:1.000f]', + ); }); it('should retain enough precision when converting to decimal', () => { - var value = transforms["color/UIColor"].transformer({ - value: "#1d1d1d" - }); - expect(value).toBe("[UIColor colorWithRed:0.114f green:0.114f blue:0.114f alpha:1.000f]"); + const value = transforms['color/UIColor'].transform( + { + value: '#1d1d1d', + }, + {}, + {}, + ); + expect(value).to.equal( + '[UIColor colorWithRed:0.114f green:0.114f blue:0.114f alpha:1.000f]', + ); }); it('should handle colors with transparency', () => { - var value = transforms["color/UIColor"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("[UIColor colorWithRed:0.667f green:0.667f blue:0.667f alpha:0.600f]"); + const value = transforms['color/UIColor'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal( + '[UIColor colorWithRed:0.667f green:0.667f blue:0.667f alpha:0.600f]', + ); }); }); describe('color/UIColorSwift', () => { it('should handle normal colors', () => { - var value = transforms["color/UIColorSwift"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha: 1)"); + const value = transforms['color/UIColorSwift'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha: 1)'); }); it('should retain enough precision when converting to decimal', () => { - var value = transforms["color/UIColorSwift"].transformer({ - value: "#1d1d1d" - }); - expect(value).toBe("UIColor(red: 0.114, green: 0.114, blue: 0.114, alpha: 1)"); + const value = transforms['color/UIColorSwift'].transform( + { + value: '#1d1d1d', + }, + {}, + {}, + ); + expect(value).to.equal('UIColor(red: 0.114, green: 0.114, blue: 0.114, alpha: 1)'); }); it('should handle colors with transparency', () => { - var value = transforms["color/UIColorSwift"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha: 0.6)"); + const value = transforms['color/UIColorSwift'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal('UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha: 0.6)'); }); }); describe('color/ColorSwiftUI', () => { it('should handle normal colors', () => { - var value = transforms["color/ColorSwiftUI"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("Color(red: 0.667, green: 0.667, blue: 0.667, opacity: 1)"); + const value = transforms['color/ColorSwiftUI'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('Color(red: 0.667, green: 0.667, blue: 0.667, opacity: 1)'); }); it('should retain enough precision when converting to decimal', () => { - var value = transforms["color/ColorSwiftUI"].transformer({ - value: "#1d1d1d" - }); - expect(value).toBe("Color(red: 0.114, green: 0.114, blue: 0.114, opacity: 1)"); + const value = transforms['color/ColorSwiftUI'].transform( + { + value: '#1d1d1d', + }, + {}, + {}, + ); + expect(value).to.equal('Color(red: 0.114, green: 0.114, blue: 0.114, opacity: 1)'); }); it('should handle colors with transparency', () => { - var value = transforms["color/ColorSwiftUI"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("Color(red: 0.667, green: 0.667, blue: 0.667, opacity: 0.6)"); + const value = transforms['color/ColorSwiftUI'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal('Color(red: 0.667, green: 0.667, blue: 0.667, opacity: 0.6)'); }); }); describe('color/hex8flutter', () => { it('should handle colors without alpha', () => { - var value = transforms["color/hex8flutter"].transformer({ - value: "#aaaaaa" - }); - expect(value).toBe("Color(0xFFAAAAAA)"); + const value = transforms['color/hex8flutter'].transform( + { + value: '#aaaaaa', + }, + {}, + {}, + ); + expect(value).to.equal('Color(0xFFAAAAAA)'); }); it('should handle colors with alpha', () => { - var value = transforms["color/hex8flutter"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("Color(0x99AAAAAA)"); + const value = transforms['color/hex8flutter'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal('Color(0x99AAAAAA)'); }); }); describe('color/css', () => { it('should handle normal colors', () => { - var value = transforms["color/css"].transformer({ - value: "rgb(170, 170, 170)" - }); - expect(value).toBe("#aaaaaa"); + const value = transforms['color/css'].transform( + { + value: 'rgb(170, 170, 170)', + }, + {}, + {}, + ); + expect(value).to.equal('#aaaaaa'); }); it('should handle colors with transparency', () => { - var value = transforms["color/css"].transformer({ - value: "#aaaaaa99" - }); - expect(value).toBe("rgba(170, 170, 170, 0.6)"); + const value = transforms['color/css'].transform( + { + value: '#aaaaaa99', + }, + {}, + {}, + ); + expect(value).to.equal('rgba(170, 170, 170, 0.6)'); }); }); describe('color/sketch', () => { it('should retain hex specificity', () => { - var originalHex = "#0b7dbb"; - var value = transforms["color/sketch"].transformer({ - original: { - value: originalHex - } - }); - var newHex = Color({ + const originalHex = '#0b7dbb'; + const value = transforms['color/sketch'].transform( + { + value: originalHex, + }, + {}, + {}, + ); + const newHex = Color({ r: value.red * 255, g: value.green * 255, - b: value.blue * 255 + b: value.blue * 255, }); - expect(originalHex).toEqual(newHex.toHexString()); + expect(originalHex).equal(newHex.toHexString()); }); }); describe('size/sp', () => { it('should work', () => { - var value = transforms["size/sp"].transformer({ - value: "12px" - }); - var value2 = transforms["size/sp"].transformer({ - value: "12" - }); - expect(value).toBe("12.00sp"); - expect(value2).toBe("12.00sp"); + const value = transforms['size/sp'].transform( + { + value: '12px', + }, + {}, + {}, + ); + const value2 = transforms['size/sp'].transform( + { + value: '12', + }, + {}, + {}, + ); + expect(value).to.equal('12.00sp'); + expect(value2).to.equal('12.00sp'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/sp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/sp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/dp', () => { it('should work', () => { - var value = transforms["size/dp"].transformer({ - value: "12px" - }); - var value2 = transforms["size/dp"].transformer({ - value: "12" - }); - expect(value).toBe("12.00dp"); - expect(value2).toBe("12.00dp"); + const value = transforms['size/dp'].transform( + { + value: '12px', + }, + {}, + {}, + ); + const value2 = transforms['size/dp'].transform( + { + value: '12', + }, + {}, + {}, + ); + expect(value).to.equal('12.00dp'); + expect(value2).to.equal('12.00dp'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' })).to.throw(); }); }); - describe("size/object", () => { - it("should work", () => { - var value = transforms["size/object"].transformer({ - value: "1px" - }); - expect(value.original).toBe("1px"); - expect(value.number).toBe(1); - expect(value.decimal).toEqual(0.01); - expect(value.scale).toBe(16); + describe('size/object', () => { + it('should work', () => { + const value = transforms['size/object'].transform( + { + value: '1px', + }, + {}, + {}, + ); + expect(value.original).to.equal('1px'); + expect(value.number).to.equal(1); + expect(value.decimal).equal(0.01); + expect(value.scale).to.equal(16); }); it('should work with custom base font', () => { - var value = transforms["size/object"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value.original).toBe("1"); - expect(value.number).toBe(1); - expect(value.decimal).toEqual(0.01); - expect(value.scale).toBe(14); - }) + const value = transforms['size/object'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value.original).to.equal('1'); + expect(value.number).to.equal(1); + expect(value.decimal).equal(0.01); + expect(value.scale).to.equal(14); + }); it('should throw an error if prop value is NaN', () => { - expect( () => transforms["size/object"].transformer({value: "a"})).toThrow(); - }) + expect(() => transforms['size/object'].transform({ value: 'a' }, {}, {})).to.throw(); + }); }); describe('size/remToSp', () => { it('should work', () => { - var value = transforms["size/remToSp"].transformer({ - value: "1" - }); - expect(value).toBe("16.00sp"); + const value = transforms['size/remToSp'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16.00sp'); }); it('converts rem to sp using custom base font', () => { - var value = transforms["size/remToSp"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14.00sp"); + const value = transforms['size/remToSp'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14.00sp'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/remToDp', () => { it('should work', () => { - var value = transforms["size/remToDp"].transformer({ - value: "1" - }); - expect(value).toBe("16.00dp"); + const value = transforms['size/remToDp'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16.00dp'); }); it('converts rem to dp using custom base font', () => { - var value = transforms["size/remToDp"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14.00dp"); + const value = transforms['size/remToDp'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14.00dp'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/px', () => { it('should work', () => { - var value = transforms["size/px"].transformer({ - value: "10" - }); - expect(value).toBe("10px"); + const value = transforms['size/px'].transform( + { + value: '10', + }, + {}, + {}, + ); + expect(value).to.equal('10px'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/remToPt', () => { it('should work', () => { - var value = transforms["size/remToPt"].transformer({ - value: "1" - }); - expect(value).toBe("16.00f"); + const value = transforms['size/remToPt'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16.00f'); }); it('converts rem to pt using custom base font', () => { - var value = transforms["size/remToPt"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14.00f"); + const value = transforms['size/remToPt'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14.00f'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/compose/remToSp', () => { it('should work', () => { - var value = transforms["size/compose/remToSp"].transformer({ - value: "1" - }); - expect(value).toBe("16.00.sp"); + const value = transforms['size/compose/remToSp'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16.00.sp'); }); it('converts rem to sp using custom base font', () => { - var value = transforms["size/compose/remToSp"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14.00.sp"); + const value = transforms['size/compose/remToSp'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14.00.sp'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/compose/remToSp"].transformer({value: "a"})).toThrow(); + expect(() => + transforms['size/compose/remToSp'].transform({ value: 'a' }, {}, {}), + ).to.throw(); }); }); describe('size/compose/em', () => { it('should work', () => { - var value = transforms["size/compose/em"].transformer({ - value: "10" - }); - expect(value).toBe("10.em"); + const value = transforms['size/compose/em'].transform( + { + value: '10', + }, + {}, + {}, + ); + expect(value).to.equal('10.em'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/compose/em"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/compose/em'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/compose/remToDp', () => { it('should work', () => { - var value = transforms["size/compose/remToDp"].transformer({ - value: "1" - }); - expect(value).toBe("16.00.dp"); + const value = transforms['size/compose/remToDp'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16.00.dp'); }); it('converts rem to dp using custom base font', () => { - var value = transforms["size/compose/remToDp"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14.00.dp"); + const value = transforms['size/compose/remToDp'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14.00.dp'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/compose/remToDp"].transformer({value: "a"})).toThrow(); + expect(() => + transforms['size/compose/remToDp'].transform({ value: 'a' }, {}, {}), + ).to.throw(); }); }); describe('size/swift/remToCGFloat', () => { it('should work', () => { - var value = transforms["size/swift/remToCGFloat"].transformer({ - value: "1" - }); - expect(value).toBe("CGFloat(16.00)"); + const value = transforms['size/swift/remToCGFloat'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('CGFloat(16.00)'); }); it('converts rem to CGFloat using custom base font', () => { - var value = transforms["size/swift/remToCGFloat"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("CGFloat(14.00)"); + const value = transforms['size/swift/remToCGFloat'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('CGFloat(14.00)'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/rem/remToCGFloat"].transformer({value: "a"})).toThrow(); + expect(() => + transforms['size/rem/remToCGFloat'].transform({ value: 'a' }, {}, {}), + ).to.throw(); }); }); describe('size/remToPx', () => { it('should work', () => { - var value = transforms["size/remToPx"].transformer({ - value: "1" - }); - expect(value).toBe("16px"); + const value = transforms['size/remToPx'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16px'); }); it('converts rem to px using custom base font', () => { - var value = transforms["size/remToPx"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14px"); + const value = transforms['size/remToPx'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14px'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/pxToRem', () => { - const pxToRemTransformer = transforms["size/pxToRem"].transformer; + const pxToRemtransform = transforms['size/pxToRem'].transform; ['12', '12px', '12rem'].forEach((value) => { it(`ignoring unit, scales "${value}" to rem`, () => { - expect(pxToRemTransformer({value})).toBe('0.75rem'); + expect(pxToRemtransform({ value }, {}, {})).to.equal('0.75rem'); }); }); it('converts pixel to rem using custom base font', () => { - expect(pxToRemTransformer({value: '14px'}, {basePxFontSize: 14})).toBe('1rem'); + expect(pxToRemtransform({ value: '14px' }, { basePxFontSize: 14 }, {})).to.equal('1rem'); }); ['0', '0px', '0rem'].forEach((value) => { - it(`zero value "${value}" is returned without a unit`, () => { - expect(pxToRemTransformer({value})).toBe('0'); - }); + it(`zero value "${value}" is returned without a unit`, () => { + expect(pxToRemtransform({ value }, {}, {})).to.equal('0'); + }); }); it('should throw an error if prop value is Nan', () => { - expect( () => pxToRemTransformer({value: "a"})).toThrow(); + expect(() => pxToRemtransform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/rem', () => { it('should work', () => { - var value = transforms["size/rem"].transformer({ - value: "1" - }); - expect(value).toBe("1rem"); + const value = transforms['size/rem'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('1rem'); }); it('should throw an error if prop value is Nan', () => { - expect( () => transforms["size/dp"].transformer({value: "a"})).toThrow(); + expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); }); }); describe('size/flutter/remToDouble', () => { it('should work', () => { - var value = transforms["size/flutter/remToDouble"].transformer({ - value: "1" - }); - expect(value).toBe("16.00"); + const value = transforms['size/flutter/remToDouble'].transform( + { + value: '1', + }, + {}, + {}, + ); + expect(value).to.equal('16.00'); }); it('converts rem to double using custom base font', () => { - var value = transforms["size/flutter/remToDouble"].transformer({value: "1"}, {basePxFontSize: 14}); - expect(value).toBe("14.00"); + const value = transforms['size/flutter/remToDouble'].transform( + { value: '1' }, + { basePxFontSize: 14 }, + {}, + ); + expect(value).to.equal('14.00'); }); }); describe('content/quote', () => { it('should work', () => { - var value = transforms["content/quote"].transformer({ - value: "hello" - }); - expect(value).toBe("'hello'"); + const value = transforms['content/quote'].transform( + { + value: 'hello', + }, + {}, + {}, + ); + expect(value).to.equal("'hello'"); }); }); - describe('content/icon', () => { + describe('html/icon', () => { it('should work', () => { - var value = transforms["content/icon"].transformer({ - value: "" - }); - expect(value).toBe("'\\E001'"); + const value = transforms['html/icon'].transform( + { + value: '', + }, + {}, + {}, + ); + expect(value).to.equal("'\\E001'"); }); }); describe('content/objC/literal', () => { it('should work', () => { - var value = transforms["content/objC/literal"].transformer({ - value: "hello" - }); - expect(value).toBe('@"hello"'); + const value = transforms['content/objC/literal'].transform( + { + value: 'hello', + }, + {}, + {}, + ); + expect(value).to.equal('@"hello"'); }); }); - describe('asset/objC/literal', () => { + describe('asset/url', () => { it('should work', () => { - var value = transforms["asset/objC/literal"].transformer({ - value: "hello" - }); - expect(value).toBe('@"hello"'); + const value = transforms['asset/url'].transform( + { + value: 'https://example.com', + }, + {}, + {}, + ); + expect(value).to.equal('url("https://example.com")'); + }); + + it('should escape double quotes', () => { + const value = transforms['asset/url'].transform( + { + value: + 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="90" height="45"%3E%3Cpath d="M10 10h60" stroke="%2300F" stroke-width="5"/%3E%3Cpath d="M10 20h60" stroke="%230F0" stroke-width="5"/%3E%3Cpath d="M10 30h60" stroke="red" stroke-width="5"/%3E%3C/svg%3E"', + }, + {}, + {}, + ); + expect(value).to.equal( + 'url("data:image/svg+xml,%3Csvg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"90\\" height=\\"45\\"%3E%3Cpath d=\\"M10 10h60\\" stroke=\\"%2300F\\" stroke-width=\\"5\\"/%3E%3Cpath d=\\"M10 20h60\\" stroke=\\"%230F0\\" stroke-width=\\"5\\"/%3E%3Cpath d=\\"M10 30h60\\" stroke=\\"red\\" stroke-width=\\"5\\"/%3E%3C/svg%3E\\"")', + ); }); }); - describe('font/objC/literal', () => { + describe('asset/objC/literal', () => { it('should work', () => { - var value = transforms["font/objC/literal"].transformer({ - value: "hello" - }); - expect(value).toBe('@"hello"'); + const value = transforms['asset/objC/literal'].transform( + { + value: 'hello', + }, + {}, + {}, + ); + expect(value).to.equal('@"hello"'); }); }); describe('time/seconds', () => { it('should work', () => { - var value = transforms["time/seconds"].transformer({ - value: "1000" + const value = transforms['time/seconds'].transform( + { + value: '1000', + }, + {}, + {}, + ); + expect(value).to.equal('1.00s'); + }); + }); + + describe('fontFamily/css', () => { + const fontFamilyTransform = (token) => transforms['fontFamily/css'].transform(token, {}, {}); + + it('should handle simple fontFamily as is', () => { + expect(fontFamilyTransform({ value: 'Arial', type: 'fontFamily' })).to.equal('Arial'); + }); + + it('should comma separated type fontFamily values', () => { + expect(fontFamilyTransform({ value: 'Arial, sans-serif', type: 'fontFamily' })).to.equal( + 'Arial, sans-serif', + ); + }); + + it('should handle array type fontFamily values', () => { + expect( + fontFamilyTransform({ value: ['Arial', 'sans-serif'], type: 'fontFamily' }), + ).to.equal('Arial, sans-serif'); + }); + + it('should wrap fontFamily values with spaces in quotes', () => { + expect(fontFamilyTransform({ value: 'Gill Sans', type: 'fontFamily' })).to.equal( + "'Gill Sans'", + ); + expect( + fontFamilyTransform({ + value: 'Gill Sans, Arial, Comic Sans, Open Sans, sans-serif', + type: 'fontFamily', + }), + ).to.equal("'Gill Sans', Arial, 'Comic Sans', 'Open Sans', sans-serif"); + expect( + fontFamilyTransform({ + value: ['Gill Sans', 'Arial', 'Comic Sans', 'Open Sans', 'sans-serif'], + type: 'fontFamily', + }), + ).to.equal("'Gill Sans', Arial, 'Comic Sans', 'Open Sans', sans-serif"); + }); + + it('should handle fontFamily prop within typography tokens', () => { + expect( + fontFamilyTransform({ + value: { + fontFamily: ['Gill Sans', 'sans-serif'], + fontWeight: 300, + fontSize: '20px', + lineHeight: '1.5', + }, + type: 'typography', + }), + ).to.eql({ + fontFamily: "'Gill Sans', sans-serif", + fontWeight: 300, + fontSize: '20px', + lineHeight: '1.5', + }); + + expect( + fontFamilyTransform({ + value: { + fontWeight: 300, + fontSize: '20px', + lineHeight: '1.5', + }, + type: 'typography', + }), + ).to.eql({ + fontWeight: 300, + fontSize: '20px', + lineHeight: '1.5', }); - expect(value).toBe("1.00s"); }); }); - describe('asset/path', () => { - it('should work', () => { - var value = transforms["asset/path"].transformer({ - value: "foo.json" + describe('cubicBezier/css', () => { + const cubicBezierTransform = (token) => + transforms['cubicBezier/css'].transform(token, {}, {}); + + it('should stringify cubicBezier values to cubicBezier() CSS function', () => { + expect(cubicBezierTransform({ value: [0.5, 0, 1, 1], type: 'cubicBezier' })).to.equal( + 'cubic-bezier(0.5, 0, 1, 1)', + ); + expect(cubicBezierTransform({ value: 'ease-in-out', type: 'cubicBezier' })).to.equal( + 'ease-in-out', + ); + }); + + it('should stringify transition token cubicBezier properties to cubicBezier() CSS function', () => { + expect( + cubicBezierTransform({ + value: { + duration: '200ms', + delay: '0ms', + timingFunction: [0.5, 0, 1, 1], + }, + type: 'transition', + }), + ).to.eql({ + duration: '200ms', + delay: '0ms', + timingFunction: 'cubic-bezier(0.5, 0, 1, 1)', + }); + expect( + cubicBezierTransform({ + value: { + duration: '200ms', + delay: '0ms', + timingFunction: 'ease-in-out', + }, + type: 'transition', + }), + ).to.eql({ + duration: '200ms', + delay: '0ms', + timingFunction: 'ease-in-out', + }); + + expect( + cubicBezierTransform({ + value: { + duration: '200ms', + delay: '0ms', + }, + type: 'transition', + }), + ).to.eql({ + duration: '200ms', + delay: '0ms', }); - expect(value).toBe(path.join(process.cwd(), "foo.json")); }); }); + describe('typography/css/shorthand', () => { + const typographyTransform = (value, platformConfig = {}) => + transforms['typography/css/shorthand'].transform({ value }, platformConfig, {}); + + it('transforms typography object to typography shorthand', () => { + expect( + typographyTransform({ + fontWeight: '500', + fontSize: '20px', + fontVariant: 'small-caps', + fontWidth: 'condensed', + fontStyle: 'italic', + lineHeight: '1.5', + fontFamily: 'Arial', + }), + ).to.equal('italic small-caps 500 condensed 20px/1.5 Arial'); + }); + + it('transforms fontWeight prop according to fontweight map for CSS and px dimensions', () => { + expect( + typographyTransform({ + fontWeight: 300, + fontSize: '20px', + lineHeight: '1.5', + fontFamily: 'Arial', + }), + ).to.equal('300 20px/1.5 Arial'); + }); + + it('provides defaults for missing properties', () => { + expect(typographyTransform({})).to.equal('16px sans-serif'); + expect(typographyTransform({}, { basePxFontSize: 12 })).to.equal('12px sans-serif'); + }); + }); + + // https://design-tokens.github.io/community-group/format/#border + describe('border/css/shorthand', () => { + const borderTransform = (value) => + transforms['border/css/shorthand'].transform({ value, type: 'border' }, {}, {}); + + it('transforms border object to border shorthand', () => { + expect( + borderTransform({ + width: '5px', + style: 'dashed', + color: '#000000', + }), + ).to.equal('5px dashed #000000'); + }); + + // https://design-tokens.github.io/community-group/format/#example-fallback-for-object-stroke-style + it('handles stroke style of type object using dashed fallback', () => { + expect( + borderTransform({ + width: '5px', + style: { + dashArray: ['0.5rem', '0.25rem'], + lineCap: 'round', + }, + color: '#000000', + }), + ).to.equal('5px dashed #000000'); + }); + + it('allows every property to be optional', () => { + expect(borderTransform({})).to.equal('none'); + }); + }); + + describe('strokeStyle/css/shorthand', () => { + const strokeTransform = (value, platformConfig = {}) => + transforms['strokeStyle/css/shorthand'].transform({ value }, platformConfig, {}); + + it('transforms strokeStyle object value to strokeStyle CSS fallback string value', () => { + expect( + strokeTransform({ + dashArray: ['0.5rem', '0.25rem'], + lineCap: 'round', + }), + ).to.equal('dashed'); + + expect(strokeTransform('dotted')).to.equal('dotted'); + }); + }); + + describe('transition/css/shorthand', () => { + const transitionTransform = (value, platformConfig = {}) => + transforms['transition/css/shorthand'].transform({ value }, platformConfig, {}); + + it('transforms transition object value to transition CSS shorthand string value', () => { + expect( + transitionTransform({ + duration: '200ms', + delay: '0ms', + timingFunction: 'cubic-bezier(0.5, 0, 1, 1)', + }), + ).to.equal('200ms cubic-bezier(0.5, 0, 1, 1) 0ms'); + + expect( + transitionTransform({ + duration: '200ms', + delay: '0ms', + timingFunction: 'ease-in-out', + }), + ).to.equal('200ms ease-in-out 0ms'); + + expect(transitionTransform('200ms linear 50ms')).to.equal('200ms linear 50ms'); + }); + }); + + describe('shadow/css/shorthand', () => { + const shadowTransform = (value, platformConfig = {}) => + transforms['shadow/css/shorthand'].transform({ value }, platformConfig, {}); + + it('transforms shadow object value to shadow CSS shorthand string value', () => { + expect( + shadowTransform({ + type: 'inset', + color: '#00000080', + offsetX: '4px', + offsetY: '4px', + blur: '12px', + spread: '6px', + }), + ).to.equal('inset 4px 4px 12px 6px #00000080'); + + expect(shadowTransform('4px 4px 12px 6px #00000080')).to.equal( + '4px 4px 12px 6px #00000080', + ); + }); + + it('transforms shadow object value with missing properties using defaults', () => { + expect(shadowTransform({})).to.equal('0 0 0 #000000'); + }); + + it('handles arrays of shadows', () => { + expect( + shadowTransform([ + { + type: 'inset', + color: '#000000', + offsetX: '4px', + offsetY: '4px', + blur: '12px', + spread: '6px', + }, + { + color: 'rgba(0,0,0, 0.4)', + offsetX: '2px', + offsetY: '2px', + blur: '4px', + }, + ]), + ).to.equal('inset 4px 4px 12px 6px #000000, 2px 2px 4px rgba(0,0,0, 0.4)'); + }); + }); + + /** + * The spec for gradient type tokens is not very well thought out at this moment + * https://design-tokens.github.io/community-group/format/#gradient + * This will inevitably change in a breaking manner, so any transform written as of the time of writing (13-05-24) + * will require a breaking change when it does. + * Therefore, a community-built custom transform is the better fit for now. + */ + describe.skip('gradient/css/shorthand', () => { + const gradientTransform = (value, platformConfig = {}) => + transforms['gradient/css/shorthand'].transform({ value }, platformConfig, {}); + + it('transforms gradient object value to gradient CSS shorthand string value', () => { + expect( + gradientTransform([ + { + color: '#0000ff', + position: 0, + }, + { + color: '#ff0000', + position: 1, + }, + ]), + ).to.equal('inset 4px 4px 12px 6px #000000, 2px 2px 4px rgba(0,0,0, 0.4)'); + + expect(gradientTransform('4px 4px 12px 6px #00000080')).to.equal( + '4px 4px 12px 6px #00000080', + ); + }); + }); + + // FIXME: find a browser/node cross compatible way to transform local path + // current implementation incorrectly uses process.cwd() rather than using + // the filePath of the token to determine where the asset is located relative to the token that refers to it + describe.skip('asset/path', () => { + it('should work', () => { + const value = transforms['asset/path'].transform( + { + value: 'foo.json', + }, + {}, + {}, + ); + expect(value).to.equal(join('foo.json')); + }); + }); + }); + + describe('transform filters', () => { + describe('isColor', () => { + it('should match short hex colors', () => { + expect(isColor({ type: 'color', value: '369' }, {})).to.be.true; + expect(isColor({ type: 'color', value: '#369' }, {})).to.be.true; + }); + + it('should match standard hex colors', () => { + expect(isColor({ type: 'color', value: 'e66465' }, {})).to.be.true; + expect(isColor({ type: 'color', value: '#e66465' }, {})).to.be.true; + }); + + it('should match 8-digit hex colors', () => { + expect(isColor({ type: 'color', value: 'e66465FF' }, {})).to.be.true; + expect(isColor({ type: 'color', value: '#e66465FF' }, {})).to.be.true; + }); + + it('should match legacy rgb/rgba colors', () => { + expect(isColor({ type: 'color', value: 'rgb(132, 99, 255)' }, {})).to.be.true; + expect(isColor({ type: 'color', value: 'rgb(132, 99, 255, 0.5)' }, {})).to.be.true; + expect(isColor({ type: 'color', value: 'rgba(132, 99, 255, 0.5)' }, {})).to.be.true; + }); + + it('should match rgb colors', () => { + expect(isColor({ type: 'color', value: 'rgb(132 99 255)' }, {})).to.be.true; + expect(isColor({ type: 'color', value: 'rgb(132 99 255 / .5)' }, {})).to.be.true; + expect(isColor({ type: 'color', value: 'rgb(132 99 255 / 50%)' }, {})).to.be.true; + }); + + it('should match legacy hsl/hsla colors', () => { + expect(isColor({ type: 'color', value: 'hsl(30, 100%, 50%, 0.6)' }, {})).to.be.true; + expect(isColor({ type: 'color', value: 'hsla(30, 100%, 50%, 0.6)' }, {})).to.be.true; + }); + + it('should match hsl colors', () => { + expect(isColor({ type: 'color', value: 'hsl(30 100% 50% / .6)' }, {})).to.be.true; + expect(isColor({ type: 'color', value: 'hsl(30.2 100% 50% / 60%)' }, {})).to.be.true; + }); + + it('should match named colors', () => { + expect(isColor({ type: 'color', value: 'red' }, {})).to.be.true; + }); + + it('should ignore gradients', () => { + expect(isColor({ type: 'color', value: 'linear-gradient(#e66465, #9198e5)' }, {})).to.be + .false; + }); + + it('should ignore values that cannot convert to a color', () => { + expect(isColor({ type: 'color', value: 'currentColor' }, {})).to.be.false; + }); + }); }); }); diff --git a/__tests__/exportPlatform.test.js b/__tests__/exportPlatform.test.js index 08edecfdb..93ecd46af 100644 --- a/__tests__/exportPlatform.test.js +++ b/__tests__/exportPlatform.test.js @@ -10,336 +10,326 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { stubMethod, restore } from 'hanbi'; +import StyleDictionary from 'style-dictionary'; +import { usesReferences } from 'style-dictionary/utils'; +import { fileToJSON, cleanConsoleOutput } from './__helpers.js'; -const helpers = require('./__helpers'); -const config = helpers.fileToJSON(__dirname + '/__configs/test.json'); -const StyleDictionary = require('../index'); -const styleDictionary = StyleDictionary.extend(config); +const config = fileToJSON('__tests__/__configs/test.json'); describe('exportPlatform', () => { + let styleDictionary; + beforeEach(async () => { + restore(); + styleDictionary = new StyleDictionary(config); + await styleDictionary.hasInitialized; + }); - it('should throw if not given a platform', () => { - expect( - function(){ - styleDictionary.exportPlatform() - } - ).toThrow(); + it('should throw if not given a platform', async () => { + await expect(styleDictionary.exportPlatform()).to.eventually.be.rejectedWith( + 'Please supply a valid platform', + ); }); - it('should throw if not given a proper platform', () => { - expect( - function(){ - styleDictionary.exportPlatform('foo'); - } - ).toThrow(); + it('should throw if not given a proper platform', async () => { + await expect(styleDictionary.exportPlatform('foo')).to.eventually.be.rejectedWith( + 'Please supply a valid platform', + ); }); - it('should not throw if given a proper platform', () => { - expect( - function(){ - styleDictionary.exportPlatform('web'); - } - ).not.toThrow(); + it('should not throw if given a proper platform', async () => { + await expect(styleDictionary.exportPlatform('web')).to.eventually.be.fulfilled; }); - it('should return an object', () => { - var dictionary = styleDictionary.exportPlatform('web'); - expect(typeof dictionary).toBe('object'); + it('should return an object', async () => { + const dictionary = await styleDictionary.exportPlatform('web'); + expect(typeof dictionary).to.equal('object'); }); - it('should have the same structure as the original properties', () => { - var dictionary = styleDictionary.exportPlatform('web'); - expect(Object.keys(dictionary)).toEqual(Object.keys(styleDictionary.properties)); + it('should have the same structure as the original tokens', async () => { + const dictionary = await styleDictionary.exportPlatform('web'); + expect(Object.keys(dictionary)).to.eql(Object.keys(styleDictionary.tokens)); }); - it('should have resolved references', () => { - var dictionary = styleDictionary.exportPlatform('web'); - expect(dictionary.color.font.link.value).toEqual(dictionary.color.base.blue['100'].value); + it('should have resolved references', async () => { + const dictionary = await styleDictionary.exportPlatform('web'); + expect(dictionary.color.font.link.value).to.eql(dictionary.color.base.blue['100'].value); }); - it('should have applied transforms', () => { - var dictionary = styleDictionary.exportPlatform('web'); - expect(dictionary.size.padding.base.value.indexOf('px')).toBeGreaterThan(0); + it('should have applied transforms', async () => { + const dictionary = await styleDictionary.exportPlatform('web'); + expect(dictionary.size.padding.base.value.endsWith('px')).to.be.true; }); - it('should have applied transforms for props with refs in it', () => { - const StyleDictionaryExtended = styleDictionary.extend({ - platforms: { - test: { - transforms: ['color/css','color/darken'] - } - } + describe('transitive transforms', () => { + it('should have applied transforms for props with refs in it', async () => { + const StyleDictionaryExtended = await styleDictionary.extend({ + platforms: { + test: { + transforms: ['color/css', 'color/darken'], + }, + }, + }); + StyleDictionary.registerTransform({ + type: 'value', + name: 'color/darken', + transitive: true, + filter: function (prop) { + return !!prop.original.transformColor; + }, + transform: function (prop) { + return prop.value + '-darker'; + }, + }); + const dictionary = await StyleDictionaryExtended.exportPlatform('test'); + expect(dictionary.color.button.active.value).to.equal('#0077cc-darker'); + expect(dictionary.color.button.hover.value).to.equal('#0077cc-darker-darker'); }); - StyleDictionaryExtended.registerTransform({ - type: 'value', - name: 'color/darken', - transitive: true, - matcher: function(prop) { return !!prop.original.transformColor; }, - transformer: function(prop) { return prop.value + '-darker'; } + it('should have transitive transforms applied without .value in references', async () => { + const sd = new StyleDictionary({ + tokens: { + one: { value: 'foo' }, + two: { value: '{one.value}' }, + three: { value: '{two}' }, + four: { value: '{one}' }, + five: { value: '{four.value}' }, + six: { value: '{one}' }, + seven: { value: '{six}' }, + eight: { value: '{one.value}' }, + nine: { value: '{eight.value}' }, + }, + hooks: { + transforms: { + transitive: { + type: 'value', + transitive: true, + transform: (token) => `${token.value}-bar`, + }, + }, + }, + platforms: { + test: { + transforms: ['transitive'], + }, + }, + }); + const dictionary = await sd.exportPlatform('test'); + expect(dictionary.one.value).to.equal('foo-bar'); + expect(dictionary.two.value).to.equal('foo-bar-bar'); + expect(dictionary.three.value).to.equal('foo-bar-bar-bar'); + expect(dictionary.four.value).to.equal('foo-bar-bar'); + expect(dictionary.five.value).to.equal('foo-bar-bar-bar'); + expect(dictionary.six.value).to.equal('foo-bar-bar'); + expect(dictionary.seven.value).to.equal('foo-bar-bar-bar'); + expect(dictionary.eight.value).to.equal('foo-bar-bar'); + expect(dictionary.nine.value).to.equal('foo-bar-bar-bar'); }); - const dictionary = StyleDictionaryExtended.exportPlatform('test'); - - expect(dictionary.color.button.active.value).toEqual('#0077CC-darker'); - expect(dictionary.color.button.hover.value).toEqual('#0077CC-darker-darker'); - }); - - it('should have transitive transforms applied without .value in references', () => { - const dictionary = StyleDictionary.extend({ - tokens: { - one: { value: 'foo' }, - two: { value: '{one.value}' }, - three: { value: '{two}' }, - four: { value: '{one}' }, - five: { value: '{four.value}' }, - six: { value: '{one}' }, - seven: { value: '{six}'}, - eight: { value: '{one.value}' }, - nine: { value: '{eight.value}' } - }, - transform: { - transitive: { - type: 'value', - transitive: true, - transformer: (token) => `${token.value}-bar` - } - }, - platforms: { - test: { - transforms: ['transitive'] - } - } - }).exportPlatform('test'); - - expect(dictionary.one.value).toEqual('foo-bar'); - expect(dictionary.two.value).toEqual('foo-bar-bar'); - expect(dictionary.three.value).toEqual('foo-bar-bar-bar'); - expect(dictionary.four.value).toEqual('foo-bar-bar'); - expect(dictionary.five.value).toEqual('foo-bar-bar-bar'); - expect(dictionary.six.value).toEqual('foo-bar-bar'); - expect(dictionary.seven.value).toEqual('foo-bar-bar-bar'); - expect(dictionary.eight.value).toEqual('foo-bar-bar'); - expect(dictionary.nine.value).toEqual('foo-bar-bar-bar'); + it('should apply transitive transforms with references nested beyond "value" prop, so transforms can consume the resolved value', async () => { + const StyleDictionaryExtended = new StyleDictionary({ + tokens: { + a: { + value: 0.5, + }, + b: { + value: '#fff', + type: 'color', + $extensions: { + 'bar.foo': { + darken: '{a}', + }, + }, + }, + }, + platforms: { + test: { + transforms: ['color/darken'], + }, + }, + }); + StyleDictionaryExtended.registerTransform({ + type: 'value', + name: 'color/darken', + transitive: true, + filter: (token) => token.type === 'color', + transform: (token) => { + const darkenMod = token?.$extensions?.['bar.foo']?.darken; + if (usesReferences(darkenMod)) { + // defer this transform, because our darken value is a ref + return undefined; + } + if (typeof darkenMod === 'number') { + // don't actually darken, just return darken value for this test + return '#000'; + } + return token.value; + }, + }); + const dictionary = await StyleDictionaryExtended.exportPlatform('test'); + expect(dictionary.b.value).to.equal('#000'); + }); }); - it('should not have mutated the original properties', () => { - var dictionary = styleDictionary.exportPlatform('web'); - expect(dictionary.color.font.link.value).not.toEqual(styleDictionary.properties.color.font.link.value); - expect(styleDictionary.properties.size.padding.base.value.indexOf('px')).toBe(-1); + it('should not have mutated the original tokens', async () => { + const dictionary = await styleDictionary.exportPlatform('web'); + expect(dictionary.color.font.link.value).to.not.equal( + styleDictionary.tokens.color.font.link.value, + ); + expect(styleDictionary.tokens.size.padding.base.value.endsWith('px')).to.be.false; }); - // Make sure when we perform transforms and resolve references // we don't mutate the original object added to the property. - it('properties should have original value untouched', () => { - var dictionary = styleDictionary.exportPlatform('web'); - var properties = helpers.fileToJSON(__dirname + '/__properties/colors.json'); - expect(dictionary.color.font.link.original.value).toEqual(properties.color.font.link.value); + it('tokens should have original value untouched', async () => { + const dictionary = await styleDictionary.exportPlatform('web'); + const tokens = fileToJSON('__tests__/__tokens/colors.json'); + expect(dictionary.color.font.link.original.value).to.equal(tokens.color.font.link.value); }); - it('should not mutate original value if value is an object', () => { - const dictionary = StyleDictionary.extend({ - properties: { + it('should not mutate original value if value is an object', async () => { + const sd = new StyleDictionary({ + tokens: { color: { red: { value: { - h: "{hue.red}", + h: '{hue.red}', s: 50, - l: 50 - } - } + l: 50, + }, + }, }, hue: { - red: 20 - } + red: 20, + }, }, platforms: { web: { - transformGroup: 'web' - } - } - }).exportPlatform('web'); - expect(dictionary.color.red.original.value.h).toEqual("{hue.red}"); - expect(dictionary.color.red.value.h).toEqual(20); - }); - - describe('reference warnings', () => { - const errorMessage = `Problems were found when trying to resolve property references`; - const platforms = { - css: { - transformGroup: `css` - } - } - - it('should throw if there are simple property reference errors', () => { - const properties = { - a: "#ff0000", - b: "{c}" - } - expect( - function() { - StyleDictionary.extend({ - properties, - platforms - }).exportPlatform('css') - } - ).toThrow(errorMessage); - }); - - it('should throw if there are circular reference errors', () => { - const properties = { - a: "{b}", - b: "{a}" - } - expect( - function() { - StyleDictionary.extend({ - properties, - platforms - }).exportPlatform('css') - } - ).toThrow(errorMessage); - }); - - it('should throw if there are complex property reference errors', () => { - const properties = { - color: { - core: { - red: { valuer: "#ff0000" }, // notice misspelling - blue: { "value:": "#0000ff" } - }, - danger: { value: "{color.core.red.value}" }, - warning: { value: "{color.base.red.valuer}" }, - info: { value: "{color.core.blue.value}" }, - error: { value: "{color.danger.value}" } - } - } - expect( - function() { - StyleDictionary.extend({ - properties, - platforms - }).exportPlatform('css') - } - ).toThrow(errorMessage); + transformGroup: 'web', + }, + }, }); + const dictionary = await sd.exportPlatform('web'); + expect(dictionary.color.red.original.value.h).to.equal('{hue.red}'); + expect(dictionary.color.red.value.h).to.equal(20); }); - it('should handle .value and non .value references per the W3C spec', () => { + it('should handle .value and non .value references per the DTCG spec', async () => { const tokens = { colors: { red: { value: '#f00' }, error: { value: '{colors.red}' }, danger: { value: '{colors.error}' }, alert: { value: '{colors.error.value}' }, - } - } - + }, + }; const expected = { colors: { red: { value: '#f00', name: 'colors-red', - path: ['colors','red'], + path: ['colors', 'red'], + original: { + value: '#f00', + }, attributes: { category: 'colors', - type: 'red' + type: 'red', }, - original: { - value: '#f00' - } }, error: { value: '#f00', name: 'colors-error', - path: ['colors','error'], + path: ['colors', 'error'], + original: { + value: '{colors.red}', + }, attributes: { category: 'colors', - type: 'error' + type: 'error', }, - original: { - value: '{colors.red}' - } }, danger: { value: '#f00', name: 'colors-danger', - path: ['colors','danger'], + path: ['colors', 'danger'], + original: { + value: '{colors.error}', + }, attributes: { category: 'colors', - type: 'danger' + type: 'danger', }, - original: { - value: '{colors.error}' - } }, alert: { value: '#f00', name: 'colors-alert', - path: ['colors','alert'], + path: ['colors', 'alert'], + original: { + value: '{colors.error.value}', + }, attributes: { category: 'colors', - type: 'alert' + type: 'alert', }, - original: { - value: '{colors.error.value}' - } }, - } - } - - const actual = StyleDictionary.extend({ + }, + }; + const actual = await new StyleDictionary({ tokens, platforms: { css: { - transformGroup: `css` - } - } + transformGroup: `css`, + }, + }, }).exportPlatform('css'); - expect(actual).toEqual(expected); + expect(actual).to.eql(expected); }); - describe('token references without .value', () => { + describe('token references without .value', async () => { const tokens = { color: { - red: { value: '#f00' }, - error: { value: '{color.red}' }, - errorWithValue: { value: '{color.red.value}' }, - danger: { value: '{color.error}' }, - dangerWithValue: { value: '{color.error.value}' }, - dangerErrorValue: { value: '{color.errorWithValue}' } - } - } - - const actual = StyleDictionary.extend({ + red: { value: '#f00', type: 'color' }, + error: { value: '{color.red}', type: 'color' }, + errorWithValue: { value: '{color.red.value}', type: 'color' }, + danger: { value: '{color.error}', type: 'color' }, + dangerWithValue: { value: '{color.error.value}', type: 'color' }, + dangerErrorValue: { value: '{color.errorWithValue}', type: 'color' }, + }, + }; + + const sd = new StyleDictionary({ tokens, platforms: { css: { - transformGroup: 'css' - } - } - }).exportPlatform('css'); + transformGroup: 'css', + }, + }, + }); + const actual = await sd.exportPlatform('css'); it('should work if referenced directly', () => { - expect(actual.color.error.value).toEqual('#ff0000'); + expect(actual.color.error.value).to.equal('#ff0000'); }); + it('should work if there is a transitive reference', () => { - expect(actual.color.danger.value).toEqual('#ff0000'); + expect(actual.color.danger.value).to.equal('#ff0000'); }); + it('should work if there is a transitive reference with .value', () => { - expect(actual.color.errorWithValue.value).toEqual('#ff0000'); - expect(actual.color.dangerWithValue.value).toEqual('#ff0000'); - expect(actual.color.dangerErrorValue.value).toEqual('#ff0000'); + expect(actual.color.errorWithValue.value).to.equal('#ff0000'); + expect(actual.color.dangerWithValue.value).to.equal('#ff0000'); + expect(actual.color.dangerErrorValue.value).to.equal('#ff0000'); }); }); - describe('non-token references', () => { + describe('non-token references', async () => { const tokens = { nonTokenColor: 'hsl(10,20%,20%)', hue: { red: '10', green: '120', - blue: '220' + blue: '220', }, comment: 'hello', color: { @@ -351,53 +341,485 @@ describe('exportPlatform', () => { value: { h: '{hue.red}', s: '100%', - l: '50%' - } + l: '50%', + }, + type: 'color', }, blue: { value: '{nonTokenColor}', - comment: '{comment}' + comment: '{comment}', + type: 'color', }, green: { - value: 'hsl({hue.green}, 50%, 50%)' - } - } - } - + value: 'hsl({hue.green}, 50%, 50%)', + type: 'color', + }, + }, + }; // making the css/color transform transitive so we can be sure the references // get resolved properly and transformed. - const transitiveTransform = Object.assign({}, - StyleDictionary.transform['color/css'], - {transitive: true} - ); + const transitiveTransform = Object.assign({}, StyleDictionary.hooks.transforms['color/css'], { + transitive: true, + }); - const actual = StyleDictionary.extend({ + const sd = new StyleDictionary({ tokens, - transform: { - transitiveTransform + hooks: { + transforms: { + transitiveTransform, + }, }, platforms: { css: { - transforms: [ - 'attribute/cti', - 'name/cti/kebab', - 'transitiveTransform' - ] - } - } - }).exportPlatform('css'); + transforms: ['name/kebab', 'transitiveTransform'], + }, + }, + }); + const actual = await sd.exportPlatform('css'); it('should work if referenced directly', () => { - expect(actual.color.blue.value).toEqual('#3d2c29'); + expect(actual.color.blue.value).to.equal('#3d2c29'); }); it('should work if referenced from a non-value', () => { - expect(actual.color.blue.comment).toEqual(tokens.comment); + expect(actual.color.blue.comment).to.equal(tokens.comment); }); it('should work if interpolated', () => { - expect(actual.color.green.value).toEqual('#40bf40'); + expect(actual.color.green.value).to.equal('#40bf40'); }); it('should work if part of an object value', () => { - expect(actual.color.red.value).toEqual('#ff2b00'); + expect(actual.color.red.value).to.equal('#ff2b00'); + }); + }); + + describe('reference warnings', () => { + const errorMessage = (amount = 1) => `Reference Errors: +Some token references (${amount}) could not be found. +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; + const platforms = { + css: { + transformGroup: `css`, + }, + }; + + it('should throw if there are simple property reference errors', async () => { + const tokens = { + a: '#ff0000', + b: '{c}', + }; + + const sd = new StyleDictionary({ + tokens, + platforms, + }); + + await expect(sd.exportPlatform('css')).to.eventually.be.rejectedWith(errorMessage()); + }); + + it('should throw if there are circular reference errors', async () => { + const tokens = { + a: '{b}', + b: '{a}', + }; + + const sd = new StyleDictionary({ + tokens, + platforms, + }); + await expect(sd.exportPlatform('css')).to.eventually.be.rejectedWith(errorMessage()); + }); + + it('should throw if there are complex property reference errors', async () => { + const tokens = { + color: { + core: { + red: { valuer: '#ff0000' }, // notice misspelling + blue: { 'value:': '#0000ff' }, + }, + danger: { value: '{color.core.red.value}' }, + warning: { value: '{color.base.red.valuer}' }, + info: { value: '{color.core.blue.value}' }, + error: { value: '{color.danger.value}' }, + }, + }; + const sd = new StyleDictionary({ + tokens, + platforms, + }); + await expect(sd.exportPlatform('css')).to.eventually.be.rejectedWith(errorMessage(4)); + }); + }); + + describe('CSS shorthand transforms integration', () => { + describe('typography', () => { + it('should warn the user about CSS Font shorthand unknown properties', async () => { + const logStub = stubMethod(console, 'log'); + const sd = new StyleDictionary({ + tokens: { + foo: { + bar: { + value: { + fontWeight: '500', + fontSize: '20px', + letterSpacing: 'normal', + paragraphSpacing: '20px', + textColor: '#000000', + }, + type: 'typography', + }, + }, + }, + platforms: { + css: { + transforms: ['typography/css/shorthand'], + }, + }, + }); + + await sd.exportPlatform('css'); + console.warn(cleanConsoleOutput(logStub.firstCall.args[0])); + + expect(cleanConsoleOutput(logStub.firstCall.args[0])).to.equal(` +Unknown CSS Font Shorthand properties found for 1 tokens, CSS output for Font values will be missing some typography token properties as a result: +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`); + + sd.log.verbosity = 'verbose'; + await sd.exportPlatform('css'); + + expect(cleanConsoleOutput(Array.from(logStub.calls)[1].args[0])).to.equal(` +Unknown CSS Font Shorthand properties found for 1 tokens, CSS output for Font values will be missing some typography token properties as a result: + +letterSpacing, paragraphSpacing, textColor for token at foo.bar +`); + + sd.tokens.foo.bar.filePath = '/tokens.json'; + await sd.exportPlatform('css'); + + expect(cleanConsoleOutput(Array.from(logStub.calls)[2].args[0])).to.equal(` +Unknown CSS Font Shorthand properties found for 1 tokens, CSS output for Font values will be missing some typography token properties as a result: + +letterSpacing, paragraphSpacing, textColor for token at foo.bar in /tokens.json +`); + + sd.log.verbosity = 'silent'; + await sd.exportPlatform('css'); + expect(Array.from(logStub.calls)[3]).to.be.undefined; + + sd.log.verbosity = 'default'; + sd.log.warnings = 'disabled'; + await sd.exportPlatform('css'); + expect(Array.from(logStub.calls)[3]).to.be.undefined; + + sd.log.warnings = 'error'; + await expect(sd.exportPlatform('css')).to.be.eventually.rejectedWith(` +Unknown CSS Font Shorthand properties found for 1 tokens, CSS output for Font values will be missing some typography token properties as a result: +Use log.verbosity "verbose" or use CLI option --verbose for more details. +`); + }); + + it('should properly transform typography tokens that are references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: '{foo}', + type: 'typography', + }, + foo: { + value: { + fontWeight: '500', + fontSize: '20px', + letterSpacing: 'normal', + paragraphSpacing: '20px', + textColor: '#000000', + }, + type: 'typography', + }, + }, + platforms: { + css: { + transforms: ['typography/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.bar.value).to.equal('500 20px sans-serif'); + }); + + it('should properly transform typography tokens that contain references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: '500', + type: 'fontWeight', + }, + foo: { + value: { + fontWeight: '{bar}', + fontSize: '20px', + letterSpacing: 'normal', + paragraphSpacing: '20px', + textColor: '#000000', + }, + type: 'typography', + }, + }, + platforms: { + css: { + transforms: ['typography/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.foo.value).to.equal('500 20px sans-serif'); + }); + }); + + describe('border', () => { + it('should properly transform typography tokens that are references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: '{foo}', + type: 'border', + }, + foo: { + value: { + style: 'dashed', + color: '#000', + width: '2px', + }, + type: 'border', + }, + }, + platforms: { + css: { + transforms: ['border/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.bar.value).to.equal('2px dashed #000'); + }); + + it('should properly transform typography tokens that contain references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: 'dashed', + type: 'strokeStyle', + }, + foo: { + value: { + style: '{bar}', + color: '#000', + width: '2px', + }, + type: 'border', + }, + }, + platforms: { + css: { + transforms: ['border/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.foo.value).to.equal('2px dashed #000'); + }); + }); + + describe('transition', () => { + it('should properly transform transition tokens that are references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: '{foo}', + type: 'transition', + }, + foo: { + value: { + duration: '200ms', + delay: '0ms', + timingFunction: [0.5, 0, 1, 1], + }, + type: 'transition', + }, + }, + platforms: { + css: { + transforms: ['cubicBezier/css', 'transition/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.bar.value).to.equal('200ms cubic-bezier(0.5, 0, 1, 1) 0ms'); + }); + + it('should properly transform transition tokens that contain references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: [0.5, 0, 1, 1], + type: 'cubicBezier', + }, + foo: { + value: { + duration: '200ms', + delay: '0ms', + timingFunction: '{bar}', + }, + type: 'transition', + }, + }, + platforms: { + css: { + transforms: ['cubicBezier/css', 'transition/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.foo.value).to.equal('200ms cubic-bezier(0.5, 0, 1, 1) 0ms'); + }); + }); + + describe('shadow', () => { + it('should properly transform typography tokens that are references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: '{foo}', + type: 'shadow', + }, + foo: { + value: { + offsetX: '2px', + offsetY: '4px', + blur: '10px', + color: '#000', + }, + type: 'shadow', + }, + }, + platforms: { + css: { + transforms: ['shadow/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.bar.value).to.equal('2px 4px 10px #000'); + }); + + it('should properly transform typography tokens that contain references', async () => { + const sd = new StyleDictionary({ + tokens: { + bar: { + value: '#000', + type: 'color', + }, + foo: { + value: [ + { + offsetX: '2px', + offsetY: '4px', + blur: '10px', + color: '{bar}', + }, + { + offsetX: '4px', + offsetY: '8px', + blur: '12px', + color: '{bar}', + }, + ], + type: 'shadow', + }, + }, + platforms: { + css: { + transforms: ['shadow/css/shorthand'], + }, + }, + }); + + const transformed = await sd.exportPlatform('css'); + expect(transformed.foo.value).to.equal('2px 4px 10px #000, 4px 8px 12px #000'); + }); + }); + }); + + describe('DTCG forward compatibility', () => { + it('should allow using $value instead of value', async () => { + const sd = new StyleDictionary({ + tokens: { + $type: 'dimension', + dimensions: { + sm: { + $value: '5', + }, + md: { + $value: '10', + value: '2000', + }, + value: { + $value: '20', + }, + nested: { + value: { + deep: { + $value: '30', + }, + }, + }, + }, + reftest: { $value: '{zero.$value}' }, + zero: { $value: '0' }, + reftest2: { $value: '{one}' }, + one: { $value: '1' }, + }, + hooks: { + transforms: { + 'custom/add/px': { + type: 'value', + filter: (token) => { + return token.$type === 'dimension'; + }, + transform: (token) => { + return `${sd.usesDtcg ? token.$value : token.value}px`; + }, + }, + }, + }, + platforms: { + css: { + transforms: ['name/kebab', 'custom/add/px'], + }, + }, + }); + + const tokens = await sd.exportPlatform('css'); + + expect(tokens.dimensions.sm.$value).to.equal('5px'); + expect(tokens.dimensions.md.$value).to.equal('10px'); + + // unaffected, because "metadata" property + expect(tokens.dimensions.md.value).to.equal('2000'); + + // considers "value" a token name here + expect(tokens.dimensions.value.$value).to.equal('20px'); + + // considers "value" a token group here + expect(tokens.dimensions.nested.value.deep.$value).to.equal('30px'); + + expect(tokens.reftest.$value).to.equal('0px'); + expect(tokens.reftest2.$value).to.equal('1px'); }); }); }); diff --git a/__tests__/extend.test.js b/__tests__/extend.test.js deleted file mode 100644 index 80c796e11..000000000 --- a/__tests__/extend.test.js +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var helpers = require('./__helpers'); -var StyleDictionary = require('../index'); -var _ = require('../lib/utils/es6_'); - -function traverseObj(obj, fn) { - for (let key in obj) { - fn.apply(this, [obj, key, obj[key]]); - if (obj[key] && typeof obj[key] === 'object') { - traverseObj(obj[key], fn); - } - } -} - -var test_props = { - size: { - padding: { - tiny: {value:'0'} - } - } -}; - -describe('extend', () => { - describe('method signature', () => { - it('should accept a string as a path to a JSON file', () => { - var StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/__configs/test.json'); - expect(StyleDictionaryExtended).toHaveProperty('platforms.web'); - }); - - it('should accept an object as options', () => { - var config = helpers.fileToJSON(__dirname + '/__configs/test.json'); - var StyleDictionaryExtended = StyleDictionary.extend(config); - expect(StyleDictionaryExtended).toHaveProperty('platforms.web'); - }); - - it('should override attributes', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - properties: { - foo: 'bar' - } - }); - expect(StyleDictionaryExtended).toHaveProperty('properties.foo', 'bar'); - }); - - it('should have all same properties', () => { - var StyleDictionaryExtended = StyleDictionary.extend({}); - _.each(_.keys(StyleDictionaryExtended), function(property) { - expect(StyleDictionaryExtended).toHaveProperty(property); - }); - }); - }); - - describe('includes', () => { - it('should throw if include isnt an array', () => { - expect( - StyleDictionary.extend.bind(null, {include: {}}) - ).toThrow('include must be an array'); - }); - - it('should not update properties if include glob paths dont resolve to anything', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - include: ['foo'] - }); - expect(typeof StyleDictionaryExtended.properties.size).toBe('undefined'); - }); - - it('should properly glob paths', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - include: [__dirname + '/__properties/*.json'] - }); - expect(typeof StyleDictionaryExtended.properties.size.padding.tiny).toBe('object'); - }); - - it('should build the properties object if an include is given', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - include: [__dirname + "/__properties/paddings.json"] - }); - var output = helpers.fileToJSON(__dirname + "/__properties/paddings.json"); - traverseObj(output, (obj) => { - if (obj.hasOwnProperty('value') && !obj.filePath) { - obj.filePath = __dirname + "/__properties/paddings.json"; - obj.isSource = false; - } - }); - expect(StyleDictionaryExtended.properties).toEqual(output); - }); - - it('should override existing properties if include is given', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - properties: test_props, - "include": [__dirname + "/__properties/paddings.json"] - }); - var output = helpers.fileToJSON(__dirname + "/__properties/paddings.json"); - traverseObj(output, (obj) => { - if (obj.hasOwnProperty('value') && !obj.filePath) { - obj.filePath = __dirname + "/__properties/paddings.json"; - obj.isSource = false; - } - }); - expect(StyleDictionaryExtended.properties).toEqual(output); - }); - - it('should update properties if there are includes', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - include: [__dirname + '/__configs/include.json'] - }); - expect(typeof StyleDictionaryExtended.properties.size.padding.tiny).toBe('object'); - }); - - it('should override existing properties if there are includes', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - properties: test_props, - include: [__dirname + '/__configs/include.json'] - }); - expect(StyleDictionaryExtended).toHaveProperty('properties.size.padding.tiny.value', '3'); - }); - }); - - describe('source', () => { - it('should throw if source isnt an array', () => { - expect( - StyleDictionary.extend.bind(null, {source: {}}) - ).toThrow('source must be an array'); - }); - - it('should not update properties if source glob paths don\'t resolve to anything', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - source: ['foo'] - }); - expect(typeof StyleDictionaryExtended.properties.size).toBe('undefined'); - }); - - it('should build the properties object if a source is given', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - "source": [__dirname + "/__properties/paddings.json"] - }); - var output = helpers.fileToJSON(__dirname + "/__properties/paddings.json"); - traverseObj(output, (obj) => { - if (obj.hasOwnProperty('value') && !obj.filePath) { - obj.filePath = __dirname + "/__properties/paddings.json"; - obj.isSource = true; - } - }); - expect(StyleDictionaryExtended.properties).toEqual(output); - }); - - it('should use relative filePaths for the filePath property', () => { - var filePath = "__tests__/__properties/paddings.json"; - var StyleDictionaryExtended = StyleDictionary.extend({ - "source": [filePath] - }); - var output = helpers.fileToJSON(__dirname + "/__properties/paddings.json"); - traverseObj(output, (obj) => { - if (obj.hasOwnProperty('value') && !obj.filePath) { - obj.filePath = filePath; - obj.isSource = true; - } - }); - expect(StyleDictionaryExtended.properties).toEqual(output); - }); - - it('should override existing properties source is given', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - properties: test_props, - source: [__dirname + "/__properties/paddings.json"] - }); - var output = helpers.fileToJSON(__dirname + "/__properties/paddings.json"); - traverseObj(output, (obj) => { - if (obj.hasOwnProperty('value') && !obj.filePath) { - obj.filePath = __dirname + "/__properties/paddings.json"; - obj.isSource = true; - } - }); - expect(StyleDictionaryExtended.properties).toEqual(output); - }); - }); - - // This is to allow style dictionaries to depend on other style dictionaries and - // override properties. Useful for skinning - it('should not throw a collision error if a source file collides with an include', () => { - var StyleDictionaryExtended = StyleDictionary.extend({ - include: [__dirname + "/__properties/paddings.1.json"], - source: [__dirname + "/__properties/paddings.json"], - log: 'error' - }); - var output = helpers.fileToJSON(__dirname + "/__properties/paddings.json"); - traverseObj(output, (obj) => { - if (obj.hasOwnProperty('value') && !obj.filePath) { - obj.filePath = __dirname + "/__properties/paddings.json"; - obj.isSource = true; - } - }); - expect(StyleDictionaryExtended.properties).toEqual(output); - }); - - it('should throw a error if the collision is in source files and log is set to error', () => { - expect( - StyleDictionary.extend.bind(null, { - source: [__dirname + "/__properties/paddings.1.json", __dirname + "/__properties/paddings.json"], - log: 'error' - }) - ).toThrow('Collisions detected'); - }); - - it('should throw a warning if the collision is in source files and log is set to warn', () => { - expect( - StyleDictionary.extend.bind(null, { - source: [__dirname + "/__properties/paddings.json", __dirname + "/__properties/paddings.json"], - log: 'warn' - }) - ).not.toThrow(); - }); - - it('should accept a string as a path to a JSON5 file', function() { - var StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/__configs/test.json5'); - expect(StyleDictionaryExtended).toHaveProperty('platforms.web'); - }); - - it('should accept a string as a path to a JSONC file', function() { - var StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/__configs/test.jsonc'); - expect(StyleDictionaryExtended).toHaveProperty('platforms.web'); - }); - - it('should allow for chained extends and not mutate the original', function() { - var StyleDictionary1 = StyleDictionary.extend({ - foo: 'bar' - }); - var StyleDictionary2 = StyleDictionary1.extend({ - foo: 'baz' - }); - var StyleDictionary3 = StyleDictionary.extend({ - foo: 'bar' - }).extend({ - foo: 'boo' - }); - expect(StyleDictionary1.foo).toBe('bar'); - expect(StyleDictionary2.foo).toBe('baz'); - expect(StyleDictionary3.foo).toBe('boo'); - expect(StyleDictionary).not.toHaveProperty('foo'); - }); - - it(`should not pollute the prototype`, () => { - const obj = {}; - let opts = JSON.parse('{"__proto__":{"polluted":"yes"}}'); - console.log("Before : " + obj.polluted); - StyleDictionary.extend(opts); - console.log("After : " + obj.polluted); - expect(obj.polluted).toBeUndefined(); - }); -}); diff --git a/__tests__/filterProperties.test.js b/__tests__/filterProperties.test.js deleted file mode 100644 index c435bbf29..000000000 --- a/__tests__/filterProperties.test.js +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var filterProperties = require('../lib/filterProperties'); -var helpers = require('./__helpers'); -var flattenProperties = require("../lib/utils/flattenProperties"); -var _ = require('../lib/utils/es6_'); - -var colorRed = { - "value": "#FF0000", - "original": { - "value": "#FF0000", - }, - "name": "color-red", - "attributes": { type: "color" }, - "path": [ - "color", - "red" - ] -} - -var colorBlue = { - "value": "#0000FF", - "original": { - "value": "#0000FF", - }, - "name": "color-blue", - "attributes": { type: "color" }, - "path": [ - "color", - "blue" - ] -} - -var sizeSmall = { - "value": "2px", - "original": { - "value": "2px", - }, - "name": "size-small", - "attributes": { category: "size" }, - "path": [ - "size", - "small" - ] -} - -var sizeLarge = { - "value": "4px", - "original": { - "value": "4px", - }, - "name": "size-large", - "attributes": { category: "size" }, - "path": [ - "size", - "large" - ] -} - -var not_kept = { - "value": 0, - "original": { - "value": 0, - }, - "name": "falsy_values-not_kept", - "attributes": { category: "falsy_values" }, - "path": [ - "falsy_values", - "not_kept" - ] -} - -var kept = { - "value": 0, - "original": { - "value": 0, - }, - "name": "falsy_values-kept", - "attributes": { category: "falsy_values" }, - "path": [ - "falsy_values", - "kept" - ] -} - -var properties = { - "color": { - "red": colorRed, - "blue": colorBlue, - }, - "size": { - "small": sizeSmall, - "large": sizeLarge, - } -}; - -var falsy_values = { - "kept": kept, - "not_kept": not_kept, -}; - -var dictionary = { - "properties": properties, - "allProperties": flattenProperties(properties) -} - -var falsy_dictionary = { - "properties": falsy_values, - "allProperties": flattenProperties(falsy_values) -} - -describe('filterProperties', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should return the original dictionary if no filter is provided', () => { - expect(dictionary).toMatchObject(filterProperties(dictionary)); - }); - - it('should work with a filter function', () => { - var filter = function(property) { - return property.path.includes("size"); - } - var filteredDictionary = filterProperties(dictionary, filter); - _.each(filteredDictionary.allProperties, function(property) { - expect(property).not.toBe(colorRed); - expect(property).not.toBe(colorBlue); - }); - expect(filteredDictionary.allProperties).toEqual([sizeSmall, sizeLarge]); - expect(filteredDictionary.properties).toHaveProperty('size'); - expect(filteredDictionary.properties).not.toHaveProperty('color'); - }); - - it('should work with falsy values and a filter function', () => { - var filter = function(property) { - return property.path.includes("kept"); - } - - var filteredDictionary = filterProperties(falsy_dictionary, filter); - _.each(filteredDictionary.allProperties, function(property) { - expect(property).not.toBe(not_kept); - }); - expect(filteredDictionary.allProperties).toEqual([kept]); - expect(filteredDictionary.properties).toHaveProperty('kept'); - expect(filteredDictionary.properties).not.toHaveProperty('not_kept'); - }); - - describe('should throw if', () => { - it('filter is a string', () => { - expect( - function(){ - filterProperties(dictionary, 'my_filter') - } - ).toThrow(/filter is not a function/); - }); - it('filter is an object', () => { - expect( - function(){ - filterProperties(dictionary, { "attributes": { "category": "size" } }) - } - ).toThrow(/filter is not a function/); - }); - }); - -}); diff --git a/__tests__/filterTokens.test.js b/__tests__/filterTokens.test.js new file mode 100644 index 000000000..4b188196a --- /dev/null +++ b/__tests__/filterTokens.test.js @@ -0,0 +1,183 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import filterTokens from '../dist/esm/filterTokens.mjs'; +import { clearOutput } from './__helpers.js'; +import flattenTokens from '../dist/esm/utils/flattenTokens.mjs'; + +const colorRed = { + value: '#FF0000', + type: 'color', + original: { + value: '#FF0000', + }, + name: 'color-red', + path: ['color', 'red'], +}; + +const colorBlue = { + value: '#0000FF', + type: 'color', + original: { + value: '#0000FF', + }, + name: 'color-blue', + path: ['color', 'blue'], +}; + +const sizeSmall = { + value: '2px', + type: 'dimension', + original: { + value: '2px', + }, + name: 'size-small', + path: ['size', 'small'], +}; + +const sizeLarge = { + value: '4px', + type: 'dimension', + original: { + value: '4px', + }, + name: 'size-large', + path: ['size', 'large'], +}; + +const not_kept = { + value: 0, + type: 'number', + original: { + value: 0, + }, + name: 'falsy_values-not_kept', + path: ['falsy_values', 'not_kept'], +}; + +const kept = { + value: 0, + type: 'number', + original: { + value: 0, + }, + name: 'falsy_values-kept', + path: ['falsy_values', 'kept'], +}; + +const tokens = { + color: { + red: colorRed, + blue: colorBlue, + }, + size: { + small: sizeSmall, + large: sizeLarge, + }, +}; + +const falsy_values = { + kept: kept, + not_kept: not_kept, +}; + +const dictionary = { + tokens, + allTokens: flattenTokens(tokens), +}; + +const falsy_dictionary = { + tokens: falsy_values, + allTokens: flattenTokens(falsy_values), +}; + +describe('filterTokens', () => { + beforeEach(() => { + clearOutput(); + }); + + afterEach(() => { + clearOutput(); + }); + + it('should return the original dictionary if no filter is provided', async () => { + expect(dictionary).to.eql(await filterTokens(dictionary)); + }); + + it('should work with a filter function', async () => { + const filter = (property) => property.path.includes('size'); + const filteredDictionary = await filterTokens(dictionary, filter); + filteredDictionary.allTokens.forEach((property) => { + expect(property).to.not.equal(colorRed); + expect(property).not.to.not.equal(colorBlue); + }); + expect(filteredDictionary.allTokens).to.eql([sizeSmall, sizeLarge]); + expect(filteredDictionary.tokens).to.have.property('size'); + expect(filteredDictionary.tokens).to.not.have.property('color'); + }); + + it('should work with falsy values and a filter function', async () => { + const filter = (property) => property.path.includes('kept'); + + const filteredDictionary = await filterTokens(falsy_dictionary, filter); + filteredDictionary.allTokens.forEach((property) => { + expect(property).to.not.equal(not_kept); + }); + expect(filteredDictionary.allTokens).to.eql([kept]); + expect(filteredDictionary.tokens).to.have.property('kept'); + expect(filteredDictionary.tokens).to.not.have.property('not_kept'); + }); + + it('should work with async filters', async () => { + const filtered = await filterTokens(dictionary, async (token) => { + await new Promise((resolve) => setTimeout(resolve, 100)); + return token.path.includes('size'); + }); + + expect(filtered.allTokens.map((token) => token.name)).to.eql(['size-small', 'size-large']); + expect(filtered.tokens).to.eql({ + size: { + small: { + value: '2px', + type: 'dimension', + original: { value: '2px' }, + name: 'size-small', + path: ['size', 'small'], + }, + large: { + value: '4px', + type: 'dimension', + original: { + value: '4px', + }, + name: 'size-large', + path: ['size', 'large'], + }, + }, + }); + }); + + describe('should throw if', () => { + it('filter is a string', async () => { + await expect(filterTokens(dictionary, 'my_filter')).to.eventually.rejectedWith( + /filter is not a function/, + ); + }); + + it('filter is an object', async () => { + await expect(filterTokens(dictionary, { type: 'dimension' })).to.eventually.rejectedWith( + /filter is not a function/, + ); + }); + }); +}); diff --git a/__tests__/formats/__constants.js b/__tests__/formats/__constants.js deleted file mode 100644 index de6c91b27..000000000 --- a/__tests__/formats/__constants.js +++ /dev/null @@ -1,64 +0,0 @@ -const createDictionary = require("../../lib/utils/createDictionary"); - -const colorPropertyName = "color-base-red-400"; -const colorPropertyValue = "#EF5350"; - -const colorProperties = { - color: { - base: { - red: { - 400: { - "name": colorPropertyName, - "value": colorPropertyValue, - "original": { - "value": colorPropertyValue - }, - "attributes": { - "category": "color", - "type": "base", - "item": "red", - "subitem": "400" - }, - "path": [ - "color", - "base", - "red", - "400" - ] - } - } - } - } -}; - -const iconPropertyName = "content-icon-email"; -const iconPropertyValue = "'\\E001'"; -const itemClass = "3d_rotation"; - -const iconProperties = { - content: { - icon: { - email: { - "name": iconPropertyName, - "value": iconPropertyValue, - "original": { - "value": iconPropertyValue - }, - "attributes": { - "category": "content", - "type": "icon", - "item": itemClass - }, - path: ['content','icon','email'] - } - } - } -}; - -const colorDictionary = createDictionary({ properties: colorProperties }); -const iconDictionary = createDictionary({ properties: iconProperties }); - -module.exports = { - colorDictionary, - iconDictionary -} \ No newline at end of file diff --git a/__tests__/formats/__snapshots__/all.test.js.snap b/__tests__/formats/__snapshots__/all.test.js.snap deleted file mode 100644 index 8c209b615..000000000 --- a/__tests__/formats/__snapshots__/all.test.js.snap +++ /dev/null @@ -1,802 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formats all should match android/colors snapshot 1`] = ` -" - - - - #FF0000 - - -" -`; - -exports[`formats all should match android/dimens snapshot 1`] = ` -" - - - - - -" -`; - -exports[`formats all should match android/fontDimens snapshot 1`] = ` -" - - - - - -" -`; - -exports[`formats all should match android/integers snapshot 1`] = ` -" - - - - - -" -`; - -exports[`formats all should match android/resources snapshot 1`] = ` -" - - - - #FF0000 - - -" -`; - -exports[`formats all should match android/strings snapshot 1`] = ` -" - - - - - -" -`; - -exports[`formats all should match compose/object snapshot 1`] = ` -" - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - - -package ; - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.* - -object { - /** comment */ - val color_red = #FF0000 -} -" -`; - -exports[`formats all should match css/fonts.css snapshot 1`] = ` -" -" -`; - -exports[`formats all should match css/variables snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -:root { - --color_red: #FF0000; /* comment */ -} -" -`; - -exports[`formats all should match flutter/class.dart snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - - -import 'dart:ui'; - -class { - ._(); - - static const color_red = #FF0000; /* comment */ -} -" -`; - -exports[`formats all should match ios/colors.h snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import - -typedef NS_ENUM(NSInteger, ) { -color_red -}; - -@interface : NSObject -+ (NSArray *)values; -+ (UIColor *)color:()color; -@end -" -`; - -exports[`formats all should match ios/colors.m snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\".h\\" - -@implementation - -+ (UIColor *)color:()colorEnum{ - return [[self values] objectAtIndex:colorEnum]; -} - -+ (NSArray *)values { - static NSArray* colorArray; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - colorArray = @[ -#FF0000 - ]; - }); - - return colorArray; -} - -@end -" -`; - -exports[`formats all should match ios/macros snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import -#import - -#define color_red #FF0000 - -" -`; - -exports[`formats all should match ios/plist snapshot 1`] = ` -" - - - - - - color_red - - r - NaN - g - NaN - b - NaN - a - 1 - - - - -" -`; - -exports[`formats all should match ios/singleton.h snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import -#import - -@interface : NSObject - -+ (NSDictionary *)properties; -+ (NSDictionary *)getProperty:(NSString *)keyPath; -+ (nonnull)getValue:(NSString *)keyPath; - -@end -" -`; - -exports[`formats all should match ios/singleton.m snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\".h\\" - -@implementation - -+ (NSDictionary *)getProperty:(NSString *)keyPath { - return [[self properties] valueForKeyPath:keyPath]; -} - -+ (nonnull)getValue:(NSString *)keyPath { - return [[self properties] valueForKeyPath:[NSString stringWithFormat:@\\"%@.value\\", keyPath]]; -} - -+ (NSDictionary *)properties { - static NSDictionary * dictionary; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - dictionary = @{ - @\\"color\\": @{ - @\\"red\\": @{ - @\\"value\\": #FF0000, - @\\"name\\": @\\"color_red\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"red\\" - } - } - }; - }); - - return dictionary; -} - -@end - - -" -`; - -exports[`formats all should match ios/static.h snapshot 1`] = ` -" -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import - - -extern const color_red; -" -`; - -exports[`formats all should match ios/static.m snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\".h\\" - - - const color_red = #FF0000; -" -`; - -exports[`formats all should match ios/strings.h snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import - - -extern NSString * const color_red; - -@interface : NSObject -+ (NSArray *)values; -@end -" -`; - -exports[`formats all should match ios/strings.m snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -#import \\".h\\" - - -NSString * const color_red = #FF0000; - -@implementation - -+ (NSArray *)values { - static NSArray* array; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - array = @[ - @{ - @\\"value\\": #FF0000, - @\\"name\\": @\\"color_red\\", - @\\"category\\": @\\"color\\", - @\\"type\\": @\\"red\\" - } - ]; - }); - - return array; -} - -@end - - -" -`; - -exports[`formats all should match ios-swift/any.swift snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit - -public class { - public static let color_red = #FF0000 /* comment */ -} -" -`; - -exports[`formats all should match ios-swift/class.swift snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit - -public class { - public static let color_red = #FF0000 /* comment */ -} -" -`; - -exports[`formats all should match ios-swift/enum.swift snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit - -public enum { - public static let color_red = #FF0000 /* comment */ -} -" -`; - -exports[`formats all should match javascript/es6 snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -export const color_red = \\"#FF0000\\"; // comment -" -`; - -exports[`formats all should match javascript/module snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -module.exports = { - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#FF0000\\", - \\"original\\": { - \\"value\\": \\"#FF0000\\" - }, - \\"name\\": \\"color_red\\", - \\"comment\\": \\"comment\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -}; -" -`; - -exports[`formats all should match javascript/module-flat snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -module.exports = { - \\"color_red\\": \\"#FF0000\\" -}; -" -`; - -exports[`formats all should match javascript/object snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -var _styleDictionary = { - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#FF0000\\", - \\"original\\": { - \\"value\\": \\"#FF0000\\" - }, - \\"name\\": \\"color_red\\", - \\"comment\\": \\"comment\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -}; -" -`; - -exports[`formats all should match javascript/umd snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -(function(root, factory) { - if (typeof module === \\"object\\" && module.exports) { - module.exports = factory(); - } else if (typeof exports === \\"object\\") { - exports[\\"_styleDictionary\\"] = factory(); - } else if (typeof define === \\"function\\" && define.amd) { - define([], factory); - } else { - root[\\"_styleDictionary\\"] = factory(); - } -}(this, function() { - return { - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#FF0000\\", - \\"original\\": { - \\"value\\": \\"#FF0000\\" - }, - \\"name\\": \\"color_red\\", - \\"comment\\": \\"comment\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -}; -})) -" -`; - -exports[`formats all should match json snapshot 1`] = ` -"{ - \\"color\\": { - \\"red\\": { - \\"value\\": \\"#FF0000\\", - \\"original\\": { - \\"value\\": \\"#FF0000\\" - }, - \\"name\\": \\"color_red\\", - \\"comment\\": \\"comment\\", - \\"attributes\\": { - \\"category\\": \\"color\\", - \\"type\\": \\"red\\" - }, - \\"path\\": [ - \\"color\\", - \\"red\\" - ] - } - } -} -" -`; - -exports[`formats all should match json/asset snapshot 1`] = `"{}"`; - -exports[`formats all should match json/flat snapshot 1`] = ` -"{ - \\"color_red\\": \\"#FF0000\\" -} -" -`; - -exports[`formats all should match json/nested snapshot 1`] = ` -"{ - \\"color\\": { - \\"red\\": \\"#FF0000\\" - } -} -" -`; - -exports[`formats all should match less/icons snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -" -`; - -exports[`formats all should match less/variables snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -@color_red: #FF0000; // comment -" -`; - -exports[`formats all should match sass/map-deep snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$color_red: #FF0000 !default; // comment - -$tokens: ( - 'color': ( - 'red': $color_red - ) -); -" -`; - -exports[`formats all should match sass/map-flat snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$tokens: ( - // comment - 'color_red': #FF0000 -); -" -`; - -exports[`formats all should match scss/icons snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -" -`; - -exports[`formats all should match scss/map-deep snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$color_red: #FF0000 !default; // comment - -$tokens: ( - 'color': ( - 'red': $color_red - ) -); -" -`; - -exports[`formats all should match scss/map-flat snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$tokens: ( - // comment - 'color_red': #FF0000 -); -" -`; - -exports[`formats all should match scss/variables snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -$color_red: #FF0000; // comment -" -`; - -exports[`formats all should match sketch/palette snapshot 1`] = ` -"{ - \\"compatibleVersion\\": \\"1.0\\", - \\"pluginVersion\\": \\"1.1\\", - \\"colors\\": [] -} -" -`; - -exports[`formats all should match sketch/palette/v2 snapshot 1`] = ` -"{ - \\"compatibleVersion\\": \\"2.0\\", - \\"pluginVersion\\": \\"2.2\\", - \\"colors\\": [ - { - \\"0\\": \\"#\\", - \\"1\\": \\"F\\", - \\"2\\": \\"F\\", - \\"3\\": \\"0\\", - \\"4\\": \\"0\\", - \\"5\\": \\"0\\", - \\"6\\": \\"0\\", - \\"name\\": \\"color_red\\" - } - ] -} -" -`; - -exports[`formats all should match stylus/variables snapshot 1`] = ` -" -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - -$color_red= #FF0000; // comment -" -`; - -exports[`formats all should match typescript/es6-declarations snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -/** comment */ -export const color_red : string; -" -`; - -exports[`formats all should match typescript/module-declarations snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -export default tokens; - -declare interface DesignToken { - value: any; - name?: string; - comment?: string; - themeable?: boolean; - attributes?: { - category?: string; - type?: string; - item?: string; - subitem?: string; - state?: string; - [key: string]: any; - }; - [key: string]: any; -} - -declare const tokens: { - \\"color\\": { - \\"red\\": DesignToken - } -} -" -`; diff --git a/__tests__/formats/__snapshots__/all.test.snap.js b/__tests__/formats/__snapshots__/all.test.snap.js new file mode 100644 index 000000000..2eed5c385 --- /dev/null +++ b/__tests__/formats/__snapshots__/all.test.snap.js @@ -0,0 +1,1515 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats all should match css/variables snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --color_red: #FF0000; /* comment */ +} +`; +/* end snapshot formats all should match css/variables snapshot */ + +snapshots["formats all should match scss/map-flat snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ + +$tokens: ( + // comment + 'color_red': #FF0000 +);`; +/* end snapshot formats all should match scss/map-flat snapshot */ + +snapshots["formats all should match scss/map-deep snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ + +$color_red: #FF0000 !default; // comment + +$tokens: ( + 'color': ( + 'red': $color_red + ) +); +`; +/* end snapshot formats all should match scss/map-deep snapshot */ + +snapshots["formats all should match scss/variables snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +$color_red: #FF0000; // comment +`; +/* end snapshot formats all should match scss/variables snapshot */ + +snapshots["formats all should match scss/icons snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +`; +/* end snapshot formats all should match scss/icons snapshot */ + +snapshots["formats all should match less/variables snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +@color_red: #FF0000; // comment +`; +/* end snapshot formats all should match less/variables snapshot */ + +snapshots["formats all should match less/icons snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +`; +/* end snapshot formats all should match less/icons snapshot */ + +snapshots["formats all should match stylus/variables snapshot"] = +` +// Do not edit directly, this file was auto-generated. + +$color_red= #FF0000; // comment +`; +/* end snapshot formats all should match stylus/variables snapshot */ + +snapshots["formats all should match javascript/module snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +module.exports = { + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot formats all should match javascript/module snapshot */ + +snapshots["formats all should match javascript/module-flat snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +module.exports = { + "color_red": "#FF0000" +}; +`; +/* end snapshot formats all should match javascript/module-flat snapshot */ + +snapshots["formats all should match javascript/object snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +var _styleDictionary = { + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot formats all should match javascript/object snapshot */ + +snapshots["formats all should match javascript/umd snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +(function(root, factory) { + if (typeof module === "object" && module.exports) { + module.exports = factory(); + } else if (typeof exports === "object") { + exports["_styleDictionary"] = factory(); + } else if (typeof define === "function" && define.amd) { + define([], factory); + } else { + root["_styleDictionary"] = factory(); + } +}(this, function() { + return { + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +}; +})) +`; +/* end snapshot formats all should match javascript/umd snapshot */ + +snapshots["formats all should match javascript/es6 snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +export const color_red = "#FF0000"; // comment +`; +/* end snapshot formats all should match javascript/es6 snapshot */ + +snapshots["formats all should match typescript/es6-declarations snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +/** comment */ +export const color_red : string; +`; +/* end snapshot formats all should match typescript/es6-declarations snapshot */ + +snapshots["formats all should match typescript/module-declarations snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +export default tokens; + +declare interface DesignToken { + value?: any; + type?: string; + comment?: string; + name?: string; + themeable?: boolean; + attributes?: Record; + [key: string]: any; +} + +declare const tokens: { + "color": { + "red": DesignToken + } +} +`; +/* end snapshot formats all should match typescript/module-declarations snapshot */ + +snapshots["formats all should match android/resources snapshot"] = +` + + + + #FF0000 +`; +/* end snapshot formats all should match android/resources snapshot */ + +snapshots["formats all should match android/colors snapshot"] = +` + + + + #FF0000 +`; +/* end snapshot formats all should match android/colors snapshot */ + +snapshots["formats all should match android/dimens snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/dimens snapshot */ + +snapshots["formats all should match android/fontDimens snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/fontDimens snapshot */ + +snapshots["formats all should match android/integers snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/integers snapshot */ + +snapshots["formats all should match android/strings snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/strings snapshot */ + +snapshots["formats all should match compose/object snapshot"] = +` + +// Do not edit directly, this file was auto-generated. + + + +package ; + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.* + +object { + /** comment */ + val color_red = #FF0000 +}`; +/* end snapshot formats all should match compose/object snapshot */ + +snapshots["formats all should match ios/macros snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import +#import + +#define color_red #FF0000 +`; +/* end snapshot formats all should match ios/macros snapshot */ + +snapshots["formats all should match ios/plist snapshot"] = +` + + + + + + color_red + + r + NaN + g + NaN + b + NaN + a + 1 + + + +`; +/* end snapshot formats all should match ios/plist snapshot */ + +snapshots["formats all should match ios/singleton.m snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import ".h" + +@implementation + ++ (NSDictionary *)getProperty:(NSString *)keyPath { + return [[self properties] valueForKeyPath:keyPath]; +} + ++ (nonnull)getValue:(NSString *)keyPath { + return [[self properties] valueForKeyPath:[NSString stringWithFormat:@"%@.value", keyPath]]; +} + ++ (NSDictionary *)properties { + static NSDictionary * dictionary; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + dictionary = @{ + @"color": @{ + @"red": @{ + @"value": #FF0000, + @"name": @"color_red" + } + } + }; + }); + + return dictionary; +} + +@end + +`; +/* end snapshot formats all should match ios/singleton.m snapshot */ + +snapshots["formats all should match ios/singleton.h snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import +#import + +@interface : NSObject + ++ (NSDictionary *)properties; ++ (NSDictionary *)getProperty:(NSString *)keyPath; ++ (nonnull)getValue:(NSString *)keyPath; + +@end`; +/* end snapshot formats all should match ios/singleton.h snapshot */ + +snapshots["formats all should match ios/static.h snapshot"] = +` +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import + + +extern const color_red;`; +/* end snapshot formats all should match ios/static.h snapshot */ + +snapshots["formats all should match ios/static.m snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import ".h" + + +const color_red = #FF0000;`; +/* end snapshot formats all should match ios/static.m snapshot */ + +snapshots["formats all should match ios/colors.h snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import + +typedef NS_ENUM(NSInteger, ) { +color_red +}; + +@interface : NSObject ++ (NSArray *)values; ++ (UIColor *)color:()color; +@end`; +/* end snapshot formats all should match ios/colors.h snapshot */ + +snapshots["formats all should match ios/colors.m snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import ".h" + +@implementation + ++ (UIColor *)color:()colorEnum{ + return [[self values] objectAtIndex:colorEnum]; +} + ++ (NSArray *)values { + static NSArray* colorArray; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + colorArray = @[ +#FF0000 + ]; + }); + + return colorArray; +} + +@end`; +/* end snapshot formats all should match ios/colors.m snapshot */ + +snapshots["formats all should match ios/strings.h snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import + + +extern NSString * const color_red; + +@interface : NSObject ++ (NSArray *)values; +@end`; +/* end snapshot formats all should match ios/strings.h snapshot */ + +snapshots["formats all should match ios/strings.m snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +#import ".h" + + +NSString * const color_red = #FF0000; + +@implementation + ++ (NSArray *)values { + static NSArray* array; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + array = @[ + @{ + @"value": #FF0000, + @"name": @"color_red" + } + ]; + }); + + return array; +} + +@end + +`; +/* end snapshot formats all should match ios/strings.m snapshot */ + +snapshots["formats all should match ios-swift/class.swift snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit + +public class { + public static let color_red = #FF0000 /* comment */ +}`; +/* end snapshot formats all should match ios-swift/class.swift snapshot */ + +snapshots["formats all should match ios-swift/enum.swift snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit + +public enum { + public static let color_red = #FF0000 /* comment */ +}`; +/* end snapshot formats all should match ios-swift/enum.swift snapshot */ + +snapshots["formats all should match ios-swift/any.swift snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit + +public class { + public static let color_red = #FF0000 /* comment */ +}`; +/* end snapshot formats all should match ios-swift/any.swift snapshot */ + +snapshots["formats all should match json snapshot"] = +`{ + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +} +`; +/* end snapshot formats all should match json snapshot */ + +snapshots["formats all should match json/asset snapshot"] = +`{}`; +/* end snapshot formats all should match json/asset snapshot */ + +snapshots["formats all should match json/nested snapshot"] = +`{ + "color": { + "red": "#FF0000" + } +} +`; +/* end snapshot formats all should match json/nested snapshot */ + +snapshots["formats all should match json/flat snapshot"] = +`{ + "color_red": "#FF0000" +} +`; +/* end snapshot formats all should match json/flat snapshot */ + +snapshots["formats all should match sketch/palette snapshot"] = +`{ + "compatibleVersion": "1.0", + "pluginVersion": "1.1", + "colors": [ + "#FF0000" + ] +} +`; +/* end snapshot formats all should match sketch/palette snapshot */ + +snapshots["formats all should match sketch/palette/v2 snapshot"] = +`{ + "compatibleVersion": "2.0", + "pluginVersion": "2.2", + "colors": [ + { + "0": "#", + "1": "F", + "2": "F", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "name": "color_red" + } + ] +} +`; +/* end snapshot formats all should match sketch/palette/v2 snapshot */ + +snapshots["formats all should match flutter/class.dart snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + + +import 'dart:ui'; + +class { + ._(); + + static const color_red = #FF0000; /* comment */ +}`; +/* end snapshot formats all should match flutter/class.dart snapshot */ + +snapshots["formats all should match css/fonts.css snapshot"] = +``; +/* end snapshot formats all should match css/fonts.css snapshot */ + +snapshots["formats all should match registerCustomFormatWithNewArgs snapshot"] = +`{ + "dictionary": { + "tokens": { + "color": { + "red": { + "value": "#FF0000", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + } + }, + "allTokens": [ + { + "value": "#FF0000", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + ] + }, + "allTokens": [ + { + "value": "#FF0000", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + ], + "tokens": { + "color": { + "red": { + "value": "#FF0000", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "attributes": { + "category": "color", + "type": "red" + }, + "path": [ + "color", + "red" + ] + } + } + }, + "platform": {}, + "file": { + "destination": "__output/", + "format": "javascript/es6", + "filter": { + "attributes": { + "category": "color" + } + } + }, + "options": {} +}`; +/* end snapshot formats all should match registerCustomFormatWithNewArgs snapshot */ + +snapshots["formats all should match css/variables snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +:root { + --color_red: #FF0000; /* comment */ +} +`; +/* end snapshot formats all should match css/variables snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match scss/map-flat snapshot with fileHeaderTimestamp set"] = +` +/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +$tokens: ( + // comment + 'color_red': #FF0000 +);`; +/* end snapshot formats all should match scss/map-flat snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match scss/map-deep snapshot with fileHeaderTimestamp set"] = +` +/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +$color_red: #FF0000 !default; // comment + +$tokens: ( + 'color': ( + 'red': $color_red + ) +); +`; +/* end snapshot formats all should match scss/map-deep snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match scss/variables snapshot with fileHeaderTimestamp set"] = +` +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +$color_red: #FF0000; // comment +`; +/* end snapshot formats all should match scss/variables snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match scss/icons snapshot with fileHeaderTimestamp set"] = +` +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +`; +/* end snapshot formats all should match scss/icons snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match less/variables snapshot with fileHeaderTimestamp set"] = +` +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +@color_red: #FF0000; // comment +`; +/* end snapshot formats all should match less/variables snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match less/icons snapshot with fileHeaderTimestamp set"] = +` +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +`; +/* end snapshot formats all should match less/icons snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match stylus/variables snapshot with fileHeaderTimestamp set"] = +` +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +$color_red= #FF0000; // comment +`; +/* end snapshot formats all should match stylus/variables snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match javascript/module snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +module.exports = { + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot formats all should match javascript/module snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match javascript/module-flat snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +module.exports = { + "color_red": "#FF0000" +}; +`; +/* end snapshot formats all should match javascript/module-flat snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match javascript/object snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +var _styleDictionary = { + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +}; +`; +/* end snapshot formats all should match javascript/object snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match javascript/umd snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +(function(root, factory) { + if (typeof module === "object" && module.exports) { + module.exports = factory(); + } else if (typeof exports === "object") { + exports["_styleDictionary"] = factory(); + } else if (typeof define === "function" && define.amd) { + define([], factory); + } else { + root["_styleDictionary"] = factory(); + } +}(this, function() { + return { + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +}; +})) +`; +/* end snapshot formats all should match javascript/umd snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match javascript/es6 snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +export const color_red = "#FF0000"; // comment +`; +/* end snapshot formats all should match javascript/es6 snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match typescript/es6-declarations snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +/** comment */ +export const color_red : string; +`; +/* end snapshot formats all should match typescript/es6-declarations snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match typescript/module-declarations snapshot with fileHeaderTimestamp set"] = +`/** + * Do not edit directly, this file was auto-generated. + * Generated on Sat, 01 Jan 2000 00:00:00 GMT + */ + +export default tokens; + +declare interface DesignToken { + value?: any; + type?: string; + comment?: string; + name?: string; + themeable?: boolean; + attributes?: Record; + [key: string]: any; +} + +declare const tokens: { + "color": { + "red": DesignToken + } +} +`; +/* end snapshot formats all should match typescript/module-declarations snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match android/resources snapshot with fileHeaderTimestamp set"] = +` + + + + #FF0000 +`; +/* end snapshot formats all should match android/resources snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match android/colors snapshot with fileHeaderTimestamp set"] = +` + + + + #FF0000 +`; +/* end snapshot formats all should match android/colors snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match android/dimens snapshot with fileHeaderTimestamp set"] = +` + + + + +`; +/* end snapshot formats all should match android/dimens snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match android/fontDimens snapshot with fileHeaderTimestamp set"] = +` + + + + +`; +/* end snapshot formats all should match android/fontDimens snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match android/integers snapshot with fileHeaderTimestamp set"] = +` + + + + +`; +/* end snapshot formats all should match android/integers snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match android/strings snapshot with fileHeaderTimestamp set"] = +` + + + + +`; +/* end snapshot formats all should match android/strings snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match compose/object snapshot with fileHeaderTimestamp set"] = +` + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + + +package ; + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.* + +object { + /** comment */ + val color_red = #FF0000 +}`; +/* end snapshot formats all should match compose/object snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/macros snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import +#import + +#define color_red #FF0000 +`; +/* end snapshot formats all should match ios/macros snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/plist snapshot with fileHeaderTimestamp set"] = +` + + + + + + color_red + + r + NaN + g + NaN + b + NaN + a + 1 + + + +`; +/* end snapshot formats all should match ios/plist snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/singleton.m snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import ".h" + +@implementation + ++ (NSDictionary *)getProperty:(NSString *)keyPath { + return [[self properties] valueForKeyPath:keyPath]; +} + ++ (nonnull)getValue:(NSString *)keyPath { + return [[self properties] valueForKeyPath:[NSString stringWithFormat:@"%@.value", keyPath]]; +} + ++ (NSDictionary *)properties { + static NSDictionary * dictionary; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + dictionary = @{ + @"color": @{ + @"red": @{ + @"value": #FF0000, + @"name": @"color_red" + } + } + }; + }); + + return dictionary; +} + +@end + +`; +/* end snapshot formats all should match ios/singleton.m snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/singleton.h snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import +#import + +@interface : NSObject + ++ (NSDictionary *)properties; ++ (NSDictionary *)getProperty:(NSString *)keyPath; ++ (nonnull)getValue:(NSString *)keyPath; + +@end`; +/* end snapshot formats all should match ios/singleton.h snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/static.h snapshot with fileHeaderTimestamp set"] = +` +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import + + +extern const color_red;`; +/* end snapshot formats all should match ios/static.h snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/static.m snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import ".h" + + +const color_red = #FF0000;`; +/* end snapshot formats all should match ios/static.m snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/colors.h snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import + +typedef NS_ENUM(NSInteger, ) { +color_red +}; + +@interface : NSObject ++ (NSArray *)values; ++ (UIColor *)color:()color; +@end`; +/* end snapshot formats all should match ios/colors.h snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/colors.m snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import ".h" + +@implementation + ++ (UIColor *)color:()colorEnum{ + return [[self values] objectAtIndex:colorEnum]; +} + ++ (NSArray *)values { + static NSArray* colorArray; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + colorArray = @[ +#FF0000 + ]; + }); + + return colorArray; +} + +@end`; +/* end snapshot formats all should match ios/colors.m snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/strings.h snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import + + +extern NSString * const color_red; + +@interface : NSObject ++ (NSArray *)values; +@end`; +/* end snapshot formats all should match ios/strings.h snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios/strings.m snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +#import ".h" + + +NSString * const color_red = #FF0000; + +@implementation + ++ (NSArray *)values { + static NSArray* array; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + array = @[ + @{ + @"value": #FF0000, + @"name": @"color_red" + } + ]; + }); + + return array; +} + +@end + +`; +/* end snapshot formats all should match ios/strings.m snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios-swift/class.swift snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +import UIKit + +public class { + public static let color_red = #FF0000 /* comment */ +}`; +/* end snapshot formats all should match ios-swift/class.swift snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios-swift/enum.swift snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +import UIKit + +public enum { + public static let color_red = #FF0000 /* comment */ +}`; +/* end snapshot formats all should match ios-swift/enum.swift snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match ios-swift/any.swift snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + +import UIKit + +public class { + public static let color_red = #FF0000 /* comment */ +}`; +/* end snapshot formats all should match ios-swift/any.swift snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match css/fonts.css snapshot with fileHeaderTimestamp set"] = +``; +/* end snapshot formats all should match css/fonts.css snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match json snapshot with fileHeaderTimestamp set"] = +`{ + "color": { + "red": { + "value": "#FF0000", + "type": "color", + "original": { + "value": "#FF0000" + }, + "name": "color_red", + "comment": "comment", + "path": [ + "color", + "red" + ] + } + } +} +`; +/* end snapshot formats all should match json snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match json/asset snapshot with fileHeaderTimestamp set"] = +`{}`; +/* end snapshot formats all should match json/asset snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match json/nested snapshot with fileHeaderTimestamp set"] = +`{ + "color": { + "red": "#FF0000" + } +} +`; +/* end snapshot formats all should match json/nested snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match json/flat snapshot with fileHeaderTimestamp set"] = +`{ + "color_red": "#FF0000" +} +`; +/* end snapshot formats all should match json/flat snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match sketch/palette snapshot with fileHeaderTimestamp set"] = +`{ + "compatibleVersion": "1.0", + "pluginVersion": "1.1", + "colors": [ + "#FF0000" + ] +} +`; +/* end snapshot formats all should match sketch/palette snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match sketch/palette/v2 snapshot with fileHeaderTimestamp set"] = +`{ + "compatibleVersion": "2.0", + "pluginVersion": "2.2", + "colors": [ + { + "0": "#", + "1": "F", + "2": "F", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "name": "color_red" + } + ] +} +`; +/* end snapshot formats all should match sketch/palette/v2 snapshot with fileHeaderTimestamp set */ + +snapshots["formats all should match flutter/class.dart snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + + + +import 'dart:ui'; + +class { + ._(); + + static const color_red = #FF0000; /* comment */ +}`; +/* end snapshot formats all should match flutter/class.dart snapshot with fileHeaderTimestamp set */ + diff --git a/__tests__/formats/__snapshots__/androidResources.test.js.snap b/__tests__/formats/__snapshots__/androidResources.test.js.snap deleted file mode 100644 index b172aa532..000000000 --- a/__tests__/formats/__snapshots__/androidResources.test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formats android/resources should match default snapshot 1`] = ` -" - - - - 12rem - 18rem - #ff0000 - #ffffff - - -" -`; - -exports[`formats android/resources with resourceMap override should match snapshot 1`] = ` -" - - - - #F2F3F4 - #000000 - - -" -`; - -exports[`formats android/resources with resourceType override should match snapshot 1`] = ` -" - - - - 12rem - 18rem - #ff0000 - #ffffff - - -" -`; diff --git a/__tests__/formats/__snapshots__/androidResources.test.snap.js b/__tests__/formats/__snapshots__/androidResources.test.snap.js new file mode 100644 index 000000000..062f56abd --- /dev/null +++ b/__tests__/formats/__snapshots__/androidResources.test.snap.js @@ -0,0 +1,43 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats android/resources should match default snapshot"] = +` + + + + 12rem + 18rem + #ff0000 + #ffffff +`; +/* end snapshot formats android/resources should match default snapshot */ + +snapshots["formats android/resources with resourceType override should match snapshot"] = +` + + + + 12rem + 18rem + #ff0000 + #ffffff +`; +/* end snapshot formats android/resources with resourceType override should match snapshot */ + +snapshots["formats android/resources with resourceMap override should match snapshot"] = +` + + + + #F2F3F4 + #000000 +`; +/* end snapshot formats android/resources with resourceMap override should match snapshot */ + diff --git a/__tests__/formats/__snapshots__/es6Constants.test.snap.js b/__tests__/formats/__snapshots__/es6Constants.test.snap.js new file mode 100644 index 000000000..b1c3207b6 --- /dev/null +++ b/__tests__/formats/__snapshots__/es6Constants.test.snap.js @@ -0,0 +1,12 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats javascript/es6 should be a valid JS file and match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +export const red = "#EF5350"; +`; +/* end snapshot formats javascript/es6 should be a valid JS file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/javascriptModule.test.snap.js b/__tests__/formats/__snapshots__/javascriptModule.test.snap.js new file mode 100644 index 000000000..e68258d9a --- /dev/null +++ b/__tests__/formats/__snapshots__/javascriptModule.test.snap.js @@ -0,0 +1,18 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats javascript/module should be a valid JS file and match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +module.exports = { + "color": { + "red": { + "value": "#FF0000" + } + } +}; +`; +/* end snapshot formats javascript/module should be a valid JS file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/javascriptModuleFlat.test.snap.js b/__tests__/formats/__snapshots__/javascriptModuleFlat.test.snap.js new file mode 100644 index 000000000..aef449948 --- /dev/null +++ b/__tests__/formats/__snapshots__/javascriptModuleFlat.test.snap.js @@ -0,0 +1,14 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats javascript/module-flat should be a valid JS file and match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +module.exports = { + "ColorRed": "#EF5350" +}; +`; +/* end snapshot formats javascript/module-flat should be a valid JS file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/javascriptObject.test.snap.js b/__tests__/formats/__snapshots__/javascriptObject.test.snap.js new file mode 100644 index 000000000..d5a44faf7 --- /dev/null +++ b/__tests__/formats/__snapshots__/javascriptObject.test.snap.js @@ -0,0 +1,18 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats javascript/object should be valid JS syntax and match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +var foo = { + "color": { + "red": { + "value": "#FF0000" + } + } +}; +`; +/* end snapshot formats javascript/object should be valid JS syntax and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/javascriptUmd.test.snap.js b/__tests__/formats/__snapshots__/javascriptUmd.test.snap.js new file mode 100644 index 000000000..acc2dd985 --- /dev/null +++ b/__tests__/formats/__snapshots__/javascriptUmd.test.snap.js @@ -0,0 +1,30 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats javascript/umd should be a valid JS file and match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +(function(root, factory) { + if (typeof module === "object" && module.exports) { + module.exports = factory(); + } else if (typeof exports === "object") { + exports["_styleDictionary"] = factory(); + } else if (typeof define === "function" && define.amd) { + define([], factory); + } else { + root["_styleDictionary"] = factory(); + } +}(this, function() { + return { + "color": { + "red": { + "value": "#FF0000" + } + } +}; +})) +`; +/* end snapshot formats javascript/umd should be a valid JS file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/json.test.snap.js b/__tests__/formats/__snapshots__/json.test.snap.js new file mode 100644 index 000000000..64e11b458 --- /dev/null +++ b/__tests__/formats/__snapshots__/json.test.snap.js @@ -0,0 +1,14 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats json should be a valid JSON file and match snapshot"] = +`{ + "color": { + "red": { + "value": "#FF0000" + } + } +} +`; +/* end snapshot formats json should be a valid JSON file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/jsonFlat.test.snap.js b/__tests__/formats/__snapshots__/jsonFlat.test.snap.js new file mode 100644 index 000000000..390899621 --- /dev/null +++ b/__tests__/formats/__snapshots__/jsonFlat.test.snap.js @@ -0,0 +1,10 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats json/flat should be a valid JSON file and match snapshot"] = +`{ + "color-base-red-400": "#EF5350" +} +`; +/* end snapshot formats json/flat should be a valid JSON file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/jsonNested.test.snap.js b/__tests__/formats/__snapshots__/jsonNested.test.snap.js new file mode 100644 index 000000000..e4a6762d4 --- /dev/null +++ b/__tests__/formats/__snapshots__/jsonNested.test.snap.js @@ -0,0 +1,25 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats json/nested should be a valid JSON file and match snapshot"] = +`{ + "color": { + "base": { + "comment": "This is a comment", + "metadata": [ + 1, + 2, + 3 + ], + "red": { + "primary": "#611D1C", + "secondary": { + "inverse": "#000000" + } + } + } + } +} +`; +/* end snapshot formats json/nested should be a valid JSON file and match snapshot */ + diff --git a/__tests__/formats/__snapshots__/lessIcons.test.snap.js b/__tests__/formats/__snapshots__/lessIcons.test.snap.js new file mode 100644 index 000000000..f2387e3bf --- /dev/null +++ b/__tests__/formats/__snapshots__/lessIcons.test.snap.js @@ -0,0 +1,18 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats less/icons should have a valid less syntax and match snapshot 1"] = +` +// Do not edit directly, this file was auto-generated. + +@content-icon-email: '\\E001'; +.sd-icon.3d_rotation:before { content: @content-icon-email; }`; +/* end snapshot formats less/icons should have a valid less syntax and match snapshot 1 */ + +snapshots["formats less/icons should have a valid less syntax and match snapshot 2"] = +`.sd-icon.3d_rotation:before { + content: '\\E001'; +} +`; +/* end snapshot formats less/icons should have a valid less syntax and match snapshot 2 */ + diff --git a/__tests__/formats/__snapshots__/lessVariables.test.snap.js b/__tests__/formats/__snapshots__/lessVariables.test.snap.js new file mode 100644 index 000000000..817554b1a --- /dev/null +++ b/__tests__/formats/__snapshots__/lessVariables.test.snap.js @@ -0,0 +1,16 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + + +snapshots["formats less/variables should have a valid less syntax and match snapshot 1"] = +` +// Do not edit directly, this file was auto-generated. + +@color-base-red-400: #EF5350; +`; +/* end snapshot formats less/variables should have a valid less syntax and match snapshot 1 */ + +snapshots["formats less/variables should have a valid less syntax and match snapshot 2"] = +``; +/* end snapshot formats less/variables should have a valid less syntax and match snapshot 2 */ + diff --git a/__tests__/formats/__snapshots__/scssIcons.test.snap.js b/__tests__/formats/__snapshots__/scssIcons.test.snap.js new file mode 100644 index 000000000..6aee10f31 --- /dev/null +++ b/__tests__/formats/__snapshots__/scssIcons.test.snap.js @@ -0,0 +1,17 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats scss/icons should have a valid scss syntax and match snapshot 1"] = +` +// Do not edit directly, this file was auto-generated. + +$content-icon-email: '\\E001'; +.sd-icon.three-d_rotation:before { content: $content-icon-email; }`; +/* end snapshot formats scss/icons should have a valid scss syntax and match snapshot 1 */ + +snapshots["formats scss/icons should have a valid scss syntax and match snapshot 2"] = +`.sd-icon.three-d_rotation:before { + content: "\\e001"; +}`; +/* end snapshot formats scss/icons should have a valid scss syntax and match snapshot 2 */ + diff --git a/__tests__/formats/__snapshots__/scssMaps.test.js.snap b/__tests__/formats/__snapshots__/scssMaps.test.js.snap deleted file mode 100644 index 8a24215f5..000000000 --- a/__tests__/formats/__snapshots__/scssMaps.test.js.snap +++ /dev/null @@ -1,54 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formats scss/map-deep scss/map-deep snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$size-font-small: 12rem !default; -$size-font-large: 18rem !default; -$color-base-red: #ff0000 !default; // comment -$color-white: #ffffff !default; -$asset-icon-book: \\"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItYm9vayI+PHBhdGggZD0iTTQgMTkuNUEyLjUgMi41IDAgMCAxIDYuNSAxN0gyMCI+PC9wYXRoPjxwYXRoIGQ9Ik02LjUgMkgyMHYyMEg2LjVBMi41IDIuNSAwIDAgMSA0IDE5LjV2LTE1QTIuNSAyLjUgMCAwIDEgNi41IDJ6Ij48L3BhdGg+PC9zdmc+\\" !default; - -$tokens: ( - 'size': ( - 'font': ( - 'small': $size-font-small, - 'large': $size-font-large - ) - ), - 'color': ( - 'base': ( - 'red': $color-base-red - ), - 'white': $color-white - ), - 'asset': ( - 'icon': ( - 'book': $asset-icon-book - ) - ) -); -" -`; - -exports[`formats scss/map-flat scss/map-flat snapshot 1`] = ` -" -/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -$tokens: ( - 'size-font-small': 12rem, - 'size-font-large': 18rem, - // comment - 'color-base-red': #ff0000, - 'color-white': #ffffff, - 'asset-icon-book': \\"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItYm9vayI+PHBhdGggZD0iTTQgMTkuNUEyLjUgMi41IDAgMCAxIDYuNSAxN0gyMCI+PC9wYXRoPjxwYXRoIGQ9Ik02LjUgMkgyMHYyMEg2LjVBMi41IDIuNSAwIDAgMSA0IDE5LjV2LTE1QTIuNSAyLjUgMCAwIDEgNi41IDJ6Ij48L3BhdGg+PC9zdmc+\\" -); -" -`; diff --git a/__tests__/formats/__snapshots__/scssMaps.test.snap.js b/__tests__/formats/__snapshots__/scssMaps.test.snap.js new file mode 100644 index 000000000..3bc3c4183 --- /dev/null +++ b/__tests__/formats/__snapshots__/scssMaps.test.snap.js @@ -0,0 +1,53 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["scss/map-flat snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ + +$tokens: ( + 'size-font-small': 12rem, + 'size-font-large': 18rem, + // comment + 'color-base-red': #ff0000, + 'color-white': #ffffff, + 'asset-icon-book': url("data:image/png;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItYm9vayI+PHBhdGggZD0iTTQgMTkuNUEyLjUgMi41IDAgMCAxIDYuNSAxN0gyMCI+PC9wYXRoPjxwYXRoIGQ9Ik02LjUgMkgyMHYyMEg2LjVBMi41IDIuNSAwIDAgMSA0IDE5LjV2LTE1QTIuNSAyLjUgMCAwIDEgNi41IDJ6Ij48L3BhdGg+PC9zdmc+") +);`; +/* end snapshot scss/map-flat snapshot */ + +snapshots["scss/map-deep snapshot"] = +` +/** + * Do not edit directly, this file was auto-generated. + */ + +$size-font-small: 12rem !default; +$size-font-large: 18rem !default; +$color-base-red: #ff0000 !default; // comment +$color-white: #ffffff !default; +$asset-icon-book: url("data:image/png;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItYm9vayI+PHBhdGggZD0iTTQgMTkuNUEyLjUgMi41IDAgMCAxIDYuNSAxN0gyMCI+PC9wYXRoPjxwYXRoIGQ9Ik02LjUgMkgyMHYyMEg2LjVBMi41IDIuNSAwIDAgMSA0IDE5LjV2LTE1QTIuNSAyLjUgMCAwIDEgNi41IDJ6Ij48L3BhdGg+PC9zdmc+") !default; + +$tokens: ( + 'size': ( + 'font': ( + 'small': $size-font-small, + 'large': $size-font-large + ) + ), + 'color': ( + 'base': ( + 'red': $color-base-red + ), + 'white': $color-white + ), + 'asset': ( + 'icon': ( + 'book': $asset-icon-book + ) + ) +); +`; +/* end snapshot scss/map-deep snapshot */ + diff --git a/__tests__/formats/__snapshots__/scssVariables.test.snap.js b/__tests__/formats/__snapshots__/scssVariables.test.snap.js new file mode 100644 index 000000000..75abfb3be --- /dev/null +++ b/__tests__/formats/__snapshots__/scssVariables.test.snap.js @@ -0,0 +1,15 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats scss/variables should have a valid scss syntax and match snapshot 1"] = +` +// Do not edit directly, this file was auto-generated. + +$color-base-red-400: #EF5350; +`; +/* end snapshot formats scss/variables should have a valid scss syntax and match snapshot 1 */ + +snapshots["formats scss/variables should have a valid scss syntax and match snapshot 2"] = +``; +/* end snapshot formats scss/variables should have a valid scss syntax and match snapshot 2 */ + diff --git a/__tests__/formats/__snapshots__/stylusVariable.test.snap.js b/__tests__/formats/__snapshots__/stylusVariable.test.snap.js new file mode 100644 index 000000000..81630c8ff --- /dev/null +++ b/__tests__/formats/__snapshots__/stylusVariable.test.snap.js @@ -0,0 +1,12 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats stylus/variables should have a valid stylus syntax and match snapshot 1"] = +` +// Do not edit directly +// Generated on Sat, 01 Jan 2000 00:00:00 GMT + +$color-base-red-400= #EF5350; +`; +/* end snapshot formats stylus/variables should have a valid stylus syntax and match snapshot 1 */ + diff --git a/__tests__/formats/__snapshots__/swiftFile.test.js.snap b/__tests__/formats/__snapshots__/swiftFile.test.js.snap deleted file mode 100644 index acee8fe60..000000000 --- a/__tests__/formats/__snapshots__/swiftFile.test.js.snap +++ /dev/null @@ -1,74 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formats ios-swift/any.swift should match default snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit - -public class StyleDictionary { - public static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) -} -" -`; - -exports[`formats ios-swift/any.swift with access control override should match snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit - -internal class StyleDictionary { - internal static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) -} -" -`; - -exports[`formats ios-swift/any.swift with import override should match snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit -import AnotherModule - -public class StyleDictionary { - public static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) -} -" -`; - -exports[`formats ios-swift/any.swift with objectType override should match snapshot 1`] = ` -" -// -// __output/ -// - -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT - - -import UIKit - -public struct StyleDictionary { - public static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) -} -" -`; diff --git a/__tests__/formats/__snapshots__/swiftFile.test.snap.js b/__tests__/formats/__snapshots__/swiftFile.test.snap.js new file mode 100644 index 000000000..c5b67623c --- /dev/null +++ b/__tests__/formats/__snapshots__/swiftFile.test.snap.js @@ -0,0 +1,68 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats ios-swift/any.swift should match default snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit + +public class StyleDictionary { + public static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) +}`; +/* end snapshot formats ios-swift/any.swift should match default snapshot */ + +snapshots["formats ios-swift/any.swift with import override should match snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit +import AnotherModule + +public class StyleDictionary { + public static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) +}`; +/* end snapshot formats ios-swift/any.swift with import override should match snapshot */ + +snapshots["formats ios-swift/any.swift with objectType override should match snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit + +public struct StyleDictionary { + public static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) +}`; +/* end snapshot formats ios-swift/any.swift with objectType override should match snapshot */ + +snapshots["formats ios-swift/any.swift with access control override should match snapshot"] = +` +// +// __output/ +// + +// Do not edit directly, this file was auto-generated. + + +import UIKit + +internal class StyleDictionary { + internal static let colorBaseRed = UIColor(red: 1.000, green: 0.000, blue: 0.000, alpha: 1) +}`; +/* end snapshot formats ios-swift/any.swift with access control override should match snapshot */ + diff --git a/__tests__/formats/__snapshots__/typeScriptEs6Declarations.test.js.snap b/__tests__/formats/__snapshots__/typeScriptEs6Declarations.test.js.snap deleted file mode 100644 index 8d567211b..000000000 --- a/__tests__/formats/__snapshots__/typeScriptEs6Declarations.test.js.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formats typescript/es6-declarations with outputStringLiterals should match snapshot 1`] = ` -"/** - * Do not edit directly - * Generated on Sat, 01 Jan 2000 00:00:00 GMT - */ - -/** Used for errors */ -export const colorRed : \\"#FF0000\\"; -" -`; diff --git a/__tests__/formats/__snapshots__/typeScriptEs6Declarations.test.snap.js b/__tests__/formats/__snapshots__/typeScriptEs6Declarations.test.snap.js new file mode 100644 index 000000000..9a2481da5 --- /dev/null +++ b/__tests__/formats/__snapshots__/typeScriptEs6Declarations.test.snap.js @@ -0,0 +1,14 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["formats typescript/es6-declarations with outputStringLiterals should match snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +/** Used for errors */ +export const colorRed : "#FF0000"; +export const fontFamily : "\\"Source Sans Pro\\", Arial, sans-serif"; +`; +/* end snapshot formats typescript/es6-declarations with outputStringLiterals should match snapshot */ + diff --git a/__tests__/formats/all.test.js b/__tests__/formats/all.test.js index d24c16520..07a1f4d15 100644 --- a/__tests__/formats/all.test.js +++ b/__tests__/formats/all.test.js @@ -10,62 +10,81 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens, deepmerge } from 'style-dictionary/utils'; -var formats = require('../../lib/common/formats'); -var createDictionary = require('../../lib/utils/createDictionary'); -var createFormatArgs = require('../../lib/utils/createFormatArgs'); -var _ = require('../../lib/utils/es6_'); - -var file = { - "destination": "__output/", - "format": "javascript/es6", - "filter": { - "attributes": { - "category": "color" - } - } +const file = { + destination: '__output/', + format: 'javascript/es6', + filter: { + type: 'color', + }, }; -var properties = { - "color": { - "red": { +const tokens = { + color: { + red: { value: '#FF0000', + type: 'color', original: { value: '#FF0000' }, name: 'color_red', comment: 'comment', - attributes: { - category: 'color', - type: 'red', - item: undefined, - subitem: undefined, - state: undefined - }, - path: ['color','red'] - } - } + path: ['color', 'red'], + }, + }, }; -describe('formats', () => { - _.each(_.keys(formats), function(key) { - - var formatter = formats[key].bind(file); - const dictionary = createDictionary({ properties }); - var output = formatter(createFormatArgs({ - dictionary, - file, - platform: {}, - }), {}, file); +describe('formats', async () => { + for (const key of Object.keys(formats)) { + const format = formats[key].bind(file); describe('all', () => { + it('should match ' + key + ' snapshot', async () => { + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ); + await expect(output).to.matchSnapshot(); + }); - it('should match ' + key + ' snapshot', () => { - expect(output).toMatchSnapshot(); + it('should match ' + key + ' snapshot with fileHeaderTimestamp set', async () => { + const _file = deepmerge(file, { + options: { + formatting: { + fileHeaderTimestamp: true, + }, + }, + }); + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file: _file, + platform: {}, + }), + {}, + _file, + ); + await expect(output).to.matchSnapshot(); }); - it('should return ' + key + ' as a string', () => { - expect(typeof output).toBe('string'); + it('should return ' + key + ' as a string', async () => { + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ); + expect(typeof output).to.equal('string'); }); }); - - }); + } }); diff --git a/__tests__/formats/androidResources.test.js b/__tests__/formats/androidResources.test.js index 49d4780ba..83eb755d0 100644 --- a/__tests__/formats/androidResources.test.js +++ b/__tests__/formats/androidResources.test.js @@ -10,158 +10,139 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); - -const properties = { - "size": { - "font": { - "small": { - "value": "12rem", - "original": { - "value": "12px" - }, - "name": "size-font-small", - "attributes": { - "category": "size", - "type": "font", - "item": "small" +const tokens = { + size: { + font: { + small: { + value: '12rem', + type: 'fontSize', + original: { + value: '12px', }, - "path": [ - "size", - "font", - "small" - ] + name: 'size-font-small', + path: ['size', 'font', 'small'], }, - "large": { - "value": "18rem", - "original": { - "value": "18px" - }, - "name": "size-font-large", - "attributes": { - "category": "size", - "type": "font", - "item": "large" + large: { + value: '18rem', + type: 'fontSize', + original: { + value: '18px', }, - "path": [ - "size", - "font", - "large" - ] - } - } + name: 'size-font-large', + path: ['size', 'font', 'large'], + }, + }, }, - "color": { - "base": { - "red": { - "value": "#ff0000", - "comment": "comment", - "original": { - "value": "#FF0000", - "comment": "comment" - }, - "name": "color-base-red", - "attributes": { - "category": "color", - "type": "base", - "item": "red" + color: { + base: { + red: { + value: '#ff0000', + type: 'color', + comment: 'comment', + original: { + value: '#FF0000', + comment: 'comment', }, - "path": [ - "color", - "base", - "red" - ] - } - }, - "white": { - "value": "#ffffff", - "original": { - "value": "#ffffff" + name: 'color-base-red', + path: ['color', 'base', 'red'], }, - "name": "color-white", - "attributes": { - "category": "color", - "type": "white" + }, + white: { + value: '#ffffff', + type: 'color', + original: { + value: '#ffffff', }, - "path": [ - "color", - "white" - ] - } + name: 'color-white', + path: ['color', 'white'], + }, }, }; -const customProperties = { +const customTokens = { backgroundColor: { secondary: { - name: "backgroundColorSecondary", - value: "#F2F3F4", - attributes: { - category: "backgroundColor" - } - } + name: 'backgroundColorSecondary', + value: '#F2F3F4', + type: 'color', + original: { + value: '#F2F3F4', + type: 'color', + }, + }, }, fontColor: { primary: { - name: "fontColorPrimary", - value: "#000000", - attributes: { - category: "fontColor" - } - } + name: 'fontColorPrimary', + value: '#000000', + type: 'color', + original: { + value: '#000000', + type: 'color', + }, + }, }, }; const format = formats['android/resources']; const file = { - "destination": "__output/", - "format": 'android/resources' + destination: '__output/', + format: 'android/resources', }; -const dictionary = createDictionary({ properties }); -const customDictionary = createDictionary({ properties: customProperties }); - describe('formats', () => { - describe(`android/resources`, () => { - - it('should match default snapshot', () => { - expect(format(createFormatArgs({ - dictionary, + it('should match default snapshot', async () => { + const f = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, file, - platform: {} - }), {}, file)).toMatchSnapshot(); + ); + await expect(f).to.matchSnapshot(); }); - it('with resourceType override should match snapshot', () => { - const file = {resourceType: "dimen"} - expect(format(createFormatArgs({ - dictionary, + it('with resourceType override should match snapshot', async () => { + const file = { options: { resourceType: 'dimen' } }; + const f = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, file, - platform: {} - }), {}, file)).toMatchSnapshot(); + ); + await expect(f).to.matchSnapshot(); }); - it('with resourceMap override should match snapshot', () => { + it('with resourceMap override should match snapshot', async () => { const file = { - resourceMap: { - color: 'color', - fontColor: 'color', - backgroundColor: 'color' - } + options: { + resourceMap: { + color: 'color', + fontColor: 'color', + backgroundColor: 'color', + }, + }, }; - expect( - format(createFormatArgs({ - dictionary: customDictionary, + const f = await format( + createFormatArgs({ + dictionary: { tokens: customTokens, allTokens: flattenTokens(customTokens) }, file, - platform: {} - }), {}, file) - ).toMatchSnapshot(); + platform: {}, + }), + {}, + file, + ); + await expect(f).to.matchSnapshot(); }); - }); - }); diff --git a/__tests__/formats/es6Constants.test.js b/__tests__/formats/es6Constants.test.js index c2db78ac0..d1a70b568 100644 --- a/__tests__/formats/es6Constants.test.js +++ b/__tests__/formats/es6Constants.test.js @@ -10,68 +10,47 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "javascript/es6", - "filter": { - "attributes": { - "category": "color" - } - } + destination: '__output/', + format: 'javascript/es6', + filter: { + type: 'color', + }, }; -const properties = { +const tokens = { color: { red: { - "name": "red", - "value": "#EF5350", - "original": { - "value": "#EF5350" + name: 'red', + value: '#EF5350', + original: { + value: '#EF5350', }, - "attributes": { - "category": "color", - "type": "base", - "item": "red", - "subitem": "400" - }, - "path": [ - "color", - "base", - "red", - "400" - ] - } - } + path: ['color', 'base', 'red', '400'], + }, + }, }; -const formatter = formats['javascript/es6'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['javascript/es6']; describe('formats', () => { describe('javascript/es6', () => { - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should be a valid JS file', () => { - fs.writeFileSync('./__tests__/__output/output.js', formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file) ); - const test = require('../__output/output.js'); - expect(test.red).toEqual(dictionary.allProperties[0].value); + it('should be a valid JS file and match snapshot', async () => { + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); }); - }); diff --git a/__tests__/formats/javascriptModule.test.js b/__tests__/formats/javascriptModule.test.js index 8f24f4b59..27b11aa00 100644 --- a/__tests__/formats/javascriptModule.test.js +++ b/__tests__/formats/javascriptModule.test.js @@ -10,52 +10,40 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "javascript/module", - "filter": { - "attributes": { - "category": "color" - } - } + destination: '__output/', + format: 'javascript/module', + filter: { + type: 'color', + }, }; -const properties = { - "color": { - "red": {"value": "#FF0000"} - } +const tokens = { + color: { + red: { value: '#FF0000' }, + }, }; -const formatter = formats['javascript/module'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['javascript/module']; describe('formats', () => { describe('javascript/module', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); + it('should be a valid JS file and match snapshot', async () => { + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - - it('should be a valid JS file', () => { - fs.writeFileSync('./__tests__/__output/output.js', formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file) ); - const test = require('../__output/output.js'); - expect(test.color.red.value).toEqual(dictionary.properties.color.red.value); - }); - }); }); diff --git a/__tests__/formats/javascriptModuleFlat.test.js b/__tests__/formats/javascriptModuleFlat.test.js index 47378aeac..6ca678315 100644 --- a/__tests__/formats/javascriptModuleFlat.test.js +++ b/__tests__/formats/javascriptModuleFlat.test.js @@ -10,60 +10,43 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "javascript/module-flat", + destination: '__output/', + format: 'javascript/module-flat', }; -const properties = { +const tokens = { color: { red: { - value: "#EF5350", - name: "ColorRed", + value: '#EF5350', + name: 'ColorRed', original: { - value: "#EF5350" - }, - attributes: { - category: "color", - type: "red" + value: '#EF5350', }, - path: [ - "color", - "red" - ] - } - } + path: ['color', 'red'], + }, + }, }; -const formatter = formats['javascript/module-flat'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['javascript/module-flat']; describe('formats', () => { describe('javascript/module-flat', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should be a valid JS file', () => { - fs.writeFileSync('./__tests__/__output/output.js', formatter(createFormatArgs({ - dictionary, - file: {}, - platform: {} - }), {}, {}) ); - const test = require('../__output/output.js'); - expect(test.ColorRed).toEqual(dictionary.allProperties[0].value); + it('should be a valid JS file and match snapshot', async () => { + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - }); }); diff --git a/__tests__/formats/javascriptObject.test.js b/__tests__/formats/javascriptObject.test.js index 50276a2d6..056acbcd9 100644 --- a/__tests__/formats/javascriptObject.test.js +++ b/__tests__/formats/javascriptObject.test.js @@ -10,40 +10,38 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const vm = require('vm'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "javascript/object", - "name": "foo" + destination: '__output/', + format: 'javascript/object', + options: { name: 'foo' }, }; -const properties = { - "color": { - "red": {"value": "#FF0000"} - } +const tokens = { + color: { + red: { value: '#FF0000' }, + }, }; -const formatter = formats['javascript/object'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['javascript/object']; describe('formats', () => { describe('javascript/object', () => { - - it('should be valid JS syntax', () => { - const script = new vm.Script(formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)); - const context = {}; - script.runInNewContext(context); - expect(context.foo.color.red.value).toEqual(dictionary.properties.color.red.value); + it('should be valid JS syntax and match snapshot', async () => { + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - }); }); diff --git a/__tests__/formats/javascriptUmd.test.js b/__tests__/formats/javascriptUmd.test.js index 59ff5c7c5..043bc7169 100644 --- a/__tests__/formats/javascriptUmd.test.js +++ b/__tests__/formats/javascriptUmd.test.js @@ -10,52 +10,40 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "javascript/umd", - "filter": { - "attributes": { - "category": "color" - } - } + destination: '__output/', + format: 'javascript/umd', + filter: { + type: 'color', + }, }; -const properties = { - "color": { - "red": {"value": "#FF0000"} - } +const tokens = { + color: { + red: { value: '#FF0000' }, + }, }; -const formatter = formats['javascript/umd'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['javascript/umd']; describe('formats', () => { describe('javascript/umd', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); + it('should be a valid JS file and match snapshot', async () => { + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - - it('should be a valid JS file', () => { - fs.writeFileSync('./__tests__/__output/umd.js', formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file) ); - const test = require('../__output/umd.js'); - expect(test.color.red.value).toEqual(dictionary.properties.color.red.value); - }); - }); }); diff --git a/__tests__/formats/json.test.js b/__tests__/formats/json.test.js index 422ad6bb6..edd7ce5fb 100644 --- a/__tests__/formats/json.test.js +++ b/__tests__/formats/json.test.js @@ -10,47 +10,37 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "json" + destination: '__output/', + format: 'json', }; -const properties = { - "color": { - "red": {"value": "#FF0000"} - } +const tokens = { + color: { + red: { value: '#FF0000' }, + }, }; -const formatter = formats['json'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['json']; describe('formats', () => { describe('json', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should be a valid JSON file', () => { - fs.writeFileSync('./__tests__/__output/output.json', formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file) ); - const test = require('../__output/output.json'); - expect(test.color.red.value).toEqual(dictionary.properties.color.red.value); + it('should be a valid JSON file and match snapshot', async () => { + await expect( + format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); }); - }); diff --git a/__tests__/formats/jsonFlat.test.js b/__tests__/formats/jsonFlat.test.js index 565b68348..25ce33e3b 100644 --- a/__tests__/formats/jsonFlat.test.js +++ b/__tests__/formats/jsonFlat.test.js @@ -10,40 +10,51 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const { colorDictionary } = require('./__constants'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; + +const colorTokenName = 'color-base-red-400'; +const colorTokenValue = '#EF5350'; + +const colorTokens = { + color: { + base: { + red: { + 400: { + name: colorTokenName, + value: colorTokenValue, + original: { + value: colorTokenValue, + }, + path: ['color', 'base', 'red', '400'], + }, + }, + }, + }, +}; const file = { - "destination": "__output/", - "format": "json/flat" + destination: '__output/', + format: 'json/flat', }; -const formatter = formats['json/flat'].bind(file); +const format = formats['json/flat']; describe('formats', () => { describe('json/flat', () => { - - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); - }); - - it('should be a valid JSON file', () => { - fs.writeFileSync('./__tests__/__output/output.flat.json', formatter(createFormatArgs({ - dictionary: colorDictionary, - file, - platform: {} - }), {}, file) ); - const test = require('../__output/output.flat.json'); - expect(test['color-base-red-400']).toEqual(colorDictionary.allProperties[0].value); + it('should be a valid JSON file and match snapshot', async () => { + await expect( + format( + createFormatArgs({ + dictionary: { tokens: colorTokens, allTokens: flattenTokens(colorTokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); }); - }); diff --git a/__tests__/formats/jsonNested.test.js b/__tests__/formats/jsonNested.test.js index 32ba7709a..b372674a7 100644 --- a/__tests__/formats/jsonNested.test.js +++ b/__tests__/formats/jsonNested.test.js @@ -10,23 +10,20 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const fs = require('fs-extra'); -const helpers = require('../__helpers'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { destination: 'output/', format: 'json/nested', }; -const properties = { +const tokens = { color: { base: { comment: 'This is a comment', - metadata: [1,2,3], + metadata: [1, 2, 3], red: { primary: { value: '#611D1C' }, secondary: { @@ -37,46 +34,22 @@ const properties = { }, }; -const formatter = formats['json/nested'].bind(file); -const dictionary = createDictionary({ properties }); - -describe('formats', function() { - describe('json/nested', function() { - beforeEach(() => { - helpers.clearOutput(); - }); - - afterEach(() => { - helpers.clearOutput(); +const format = formats['json/nested']; + +describe('formats', function () { + describe('json/nested', function () { + it('should be a valid JSON file and match snapshot', async () => { + await expect( + format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - - it('should be a valid JSON file', function() { - fs.writeFileSync('./__tests__/__output/json-nested.json', formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)); - const test = require('../__output/json-nested.json'); - expect(test.color.base.red.primary) - .toEqual(dictionary.properties.color.base.red.primary.value); - expect(test.color.base.red.secondary.inverse) - .toEqual(dictionary.properties.color.base.red.secondary.inverse.value); - }); - - it('should handle non-token data', function() { - // non-token data is anything in the dictionary object that is not a token object - // i.e. anything in the rest of the object that doesn't have a 'value' - - fs.writeFileSync('./__tests__/__output/json-nested.json', formatter(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)); - const test = require('../__output/json-nested.json'); - expect(test.color.base.comment) - .toEqual(dictionary.properties.color.base.comment); - expect(test.color.base.metadata) - .toEqual(dictionary.properties.color.base.metadata); - }) }); }); diff --git a/__tests__/formats/lessIcons.test.js b/__tests__/formats/lessIcons.test.js index ab920b830..8984969f4 100644 --- a/__tests__/formats/lessIcons.test.js +++ b/__tests__/formats/lessIcons.test.js @@ -10,60 +10,72 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const less = require('less'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "less/icons", - "name": "foo" + destination: '__output/', + format: 'less/icons', + name: 'foo', }; -const propertyName = "content-icon-email"; +const propertyName = 'content-icon-email'; const propertyValue = "'\\E001'"; -const itemClass = "3d_rotation"; +const itemClass = '3d_rotation'; -const properties = { +const tokens = { content: { icon: { email: { - "name": propertyName, - "value": propertyValue, - "original": { - "value": propertyValue + name: propertyName, + value: propertyValue, + type: 'icon', + original: { + value: propertyValue, }, - "attributes": { - "category": "content", - "type": "icon", - "item": itemClass + attributes: { + item: itemClass, }, - path: ['content','icon','email'] - } - } - } + path: ['content', 'icon', 'email'], + }, + }, + }, }; const platform = { - prefix: 'sd' // Style-Dictionary Prefix + prefix: 'sd', // Style Dictionary Prefix + // FIXME: check why createFormatArgs requires this prefix to be wrapped inside + // an options object for it to be properly set as option? + options: { + prefix: 'sd', + }, }; -const formatter = formats['less/icons'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['less/icons']; describe('formats', () => { describe('less/icons', () => { + it('should have a valid less syntax and match snapshot', async () => { + const result = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform, + }), + ); - it('should have a valid less syntax', () => { - expect.assertions(1); - return expect(less.render(formatter(createFormatArgs({ - dictionary, - file, - platform - }), platform, file))).resolves.toBeDefined(); + let _less; + if (typeof window === 'object') { + await import('less/dist/less.js'); + // eslint-disable-next-line no-undef + _less = less; + } else { + _less = (await import('less')).default; + } + const lessResult = await _less.render(result); + await expect(result).to.matchSnapshot(1); + await expect(lessResult.css).to.matchSnapshot(2); }); - }); }); diff --git a/__tests__/formats/lessVariables.test.js b/__tests__/formats/lessVariables.test.js index ab652672d..8f163c2fa 100644 --- a/__tests__/formats/lessVariables.test.js +++ b/__tests__/formats/lessVariables.test.js @@ -10,63 +10,61 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; -var formats = require('../../lib/common/formats'); -var less = require('less'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); - -var file = { - "destination": "__output/", - "format": "less/variables", - "name": "foo" +const file = { + destination: '__output/', + format: 'less/variables', + name: 'foo', }; -const propertyName = "color-base-red-400"; -const propertyValue = "#EF5350"; +const propertyName = 'color-base-red-400'; +const propertyValue = '#EF5350'; -const properties = { +const tokens = { color: { base: { red: { 400: { - "name": propertyName, - "value": propertyValue, - "original": { - "value": propertyValue - }, - "attributes": { - "category": "color", - "type": "base", - "item": "red", - "subitem": "400" + name: propertyName, + value: propertyValue, + original: { + value: propertyValue, }, - "path": [ - "color", - "base", - "red", - "400" - ] - } - } - } - } + path: ['color', 'base', 'red', '400'], + }, + }, + }, + }, }; -const formatter = formats['less/variables'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['less/variables']; describe('formats', () => { describe('less/variables', () => { - - it('should have a valid less syntax', () => { - expect.assertions(1); - return expect(less.render(formatter(createFormatArgs({ - dictionary, + it('should have a valid less syntax and match snapshot', async () => { + const result = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, file, - platform: {} - }), {}, file))).resolves.toBeDefined(); + ); + let _less; + if (typeof window === 'object') { + await import('less/dist/less.js'); + // eslint-disable-next-line no-undef + _less = less; + } else { + _less = (await import('less')).default; + } + const lessResult = await _less.render(result); + await expect(result).to.matchSnapshot(1); + await expect(lessResult.css).to.matchSnapshot(2); }); - }); }); diff --git a/__tests__/formats/scssIcons.test.js b/__tests__/formats/scssIcons.test.js index 84a87b92c..502d8f86a 100644 --- a/__tests__/formats/scssIcons.test.js +++ b/__tests__/formats/scssIcons.test.js @@ -10,62 +10,66 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const formats = require('../../lib/common/formats'); -const scss = require('node-sass'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import { compileString } from 'sass'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "scss/icons", - "name": "foo" + destination: '__output/', + format: 'scss/icons', + name: 'foo', }; -const propertyName = "content-icon-email"; +const propertyName = 'content-icon-email'; const propertyValue = "'\\E001'"; -const itemClass = "3d_rotation"; +const itemClass = 'three-d_rotation'; -const properties = { +const tokens = { content: { icon: { email: { - "name": propertyName, - "value": propertyValue, - "original": { - "value": propertyValue + name: propertyName, + value: propertyValue, + type: 'icon', + original: { + value: propertyValue, }, - "attributes": { - "category": "content", - "type": "icon", - "item": itemClass + attributes: { + item: itemClass, }, - path: ['content','icon','email'] - } - } - } + path: ['content', 'icon', 'email'], + }, + }, + }, }; const platform = { - prefix: 'sd' // Style-Dictionary Prefix + prefix: 'sd', // Style Dictionary Prefix + // FIXME: check why createFormatArgs requires this prefix to be wrapped inside + // an options object for it to be properly set as option? + options: { + prefix: 'sd', + }, }; -const formatter = formats['scss/icons'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['scss/icons']; describe('formats', () => { describe('scss/icons', () => { - - it('should have a valid scss syntax', () => { - const result = scss.renderSync({ - data: formatter(createFormatArgs({ - dictionary, + it('should have a valid scss syntax and match snapshot', async () => { + const result = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, file, - platform - }), platform, file), - }); - expect(result.css).toBeDefined(); + platform, + }), + platform, + file, + ); + const scssResult = compileString(result); + await expect(result).to.matchSnapshot(1); + await expect(scssResult.css).to.matchSnapshot(2); }); - }); }); diff --git a/__tests__/formats/scssMaps.test.js b/__tests__/formats/scssMaps.test.js index c4d9c2d1f..f6caa1693 100644 --- a/__tests__/formats/scssMaps.test.js +++ b/__tests__/formats/scssMaps.test.js @@ -10,147 +10,101 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { compileString } from 'sass'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; -var formats = require('../../lib/common/formats'); -var scss = require('node-sass'); -var _ = require('../../lib/utils/es6_'); -var createDictionary = require('../../lib/utils/createDictionary'); -var createFormatArgs = require('../../lib/utils/createFormatArgs'); - -var properties = { - "size": { - "font": { - "small": { - "value": "12rem", - "original": { - "value": "12px" - }, - "name": "size-font-small", - "attributes": { - "category": "size", - "type": "font", - "item": "small" +const tokens = { + size: { + font: { + small: { + value: '12rem', + original: { + value: '12px', }, - "path": [ - "size", - "font", - "small" - ] + name: 'size-font-small', + path: ['size', 'font', 'small'], }, - "large": { - "value": "18rem", - "original": { - "value": "18px" - }, - "name": "size-font-large", - "attributes": { - "category": "size", - "type": "font", - "item": "large" + large: { + value: '18rem', + original: { + value: '18px', }, - "path": [ - "size", - "font", - "large" - ] - } - } + name: 'size-font-large', + path: ['size', 'font', 'large'], + }, + }, }, - "color": { - "base": { - "red": { - "value": "#ff0000", - "comment": "comment", - "original": { - "value": "#FF0000", - "comment": "comment" + color: { + base: { + red: { + value: '#ff0000', + comment: 'comment', + original: { + value: '#FF0000', + comment: 'comment', }, - "name": "color-base-red", - "attributes": { - "category": "color", - "type": "base", - "item": "red" - }, - "path": [ - "color", - "base", - "red" - ] - } - }, - "white": { - "value": "#ffffff", - "original": { - "value": "#ffffff" + name: 'color-base-red', + path: ['color', 'base', 'red'], }, - "name": "color-white", - "attributes": { - "category": "color", - "type": "white" + }, + white: { + value: '#ffffff', + original: { + value: '#ffffff', }, - "path": [ - "color", - "white" - ] - } + name: 'color-white', + path: ['color', 'white'], + }, }, - "asset": { - "icon": { - "book": { - "value": "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItYm9vayI+PHBhdGggZD0iTTQgMTkuNUEyLjUgMi41IDAgMCAxIDYuNSAxN0gyMCI+PC9wYXRoPjxwYXRoIGQ9Ik02LjUgMkgyMHYyMEg2LjVBMi41IDIuNSAwIDAgMSA0IDE5LjV2LTE1QTIuNSAyLjUgMCAwIDEgNi41IDJ6Ij48L3BhdGg+PC9zdmc+", - "original": { - "value": "./test/__assets/icons/book.svg" - }, - "name": "asset-icon-book", - "attributes": { - "category": "asset", - "type": "icon", - "item": "book" + asset: { + icon: { + book: { + value: + 'url("data:image/png;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItYm9vayI+PHBhdGggZD0iTTQgMTkuNUEyLjUgMi41IDAgMCAxIDYuNSAxN0gyMCI+PC9wYXRoPjxwYXRoIGQ9Ik02LjUgMkgyMHYyMEg2LjVBMi41IDIuNSAwIDAgMSA0IDE5LjV2LTE1QTIuNSAyLjUgMCAwIDEgNi41IDJ6Ij48L3BhdGg+PC9zdmc+")', + type: 'asset', + original: { + value: '__tests__/__assets/icons/book.svg', }, - "path": [ - "asset", - "icon", - "book" - ] - } - } - } + name: 'asset-icon-book', + path: ['asset', 'icon', 'book'], + }, + }, + }, }; describe('formats', () => { - _.each(['scss/map-flat', 'scss/map-deep'], function(key) { - - describe(key, () => { - - var file = { - "destination": "__output/", - "format": key + for (const key of ['scss/map-flat', 'scss/map-deep']) { + describe(key, async () => { + const file = { + destination: '__output/', + format: key, }; - var formatter = formats[key].bind(file); - const dictionary = createDictionary({ properties }); - var output = formatter(createFormatArgs({ - dictionary, + const format = formats[key].bind(file); + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, file, - platform: {}, - }), {}, file); + ); it('should return ' + key + ' as a string', () => { - expect(typeof output).toBe('string'); + expect(typeof output).to.equal('string'); }); it('should have a valid scss syntax', () => { - const result = scss.renderSync({ - data: output, - }); - expect(result.css).toBeDefined(); + const result = compileString(output); + expect(result.css).to.not.be.undefined; }); - it(key + ' snapshot', () => { - expect(output).toMatchSnapshot(); + it(key + ' snapshot', async () => { + await expect(output).to.matchSnapshot(); }); - }); - - }); + } }); diff --git a/__tests__/formats/scssVariables.test.js b/__tests__/formats/scssVariables.test.js index 3e501b680..97c890030 100644 --- a/__tests__/formats/scssVariables.test.js +++ b/__tests__/formats/scssVariables.test.js @@ -10,86 +10,82 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { compileString } from 'sass'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; -var formats = require('../../lib/common/formats'); -var scss = require('node-sass'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); -var _ = require('../../lib/utils/es6_'); - -var file = { - "destination": "__output/", - "format": "scss/variables", - "name": "foo" +const file = { + destination: '__output/', + format: 'scss/variables', + name: 'foo', }; -const propertyName = "color-base-red-400"; -const propertyValue = "#EF5350"; +const propertyName = 'color-base-red-400'; +const propertyValue = '#EF5350'; -const properties = { +const tokens = { color: { base: { red: { 400: { - "name": propertyName, - "value": propertyValue, - "original": { - "value": propertyValue - }, - "attributes": { - "category": "color", - "type": "base", - "item": "red", - "subitem": "400" + name: propertyName, + value: propertyValue, + original: { + value: propertyValue, }, - "path": [ - "color", - "base", - "red", - "400" - ] - } - } - } - } + path: ['color', 'base', 'red', '400'], + }, + }, + }, + }, }; -var formatter = formats['scss/variables'].bind(file); -const dictionary = createDictionary({properties}); +const format = formats['scss/variables']; describe('formats', () => { describe('scss/variables', () => { - - it('should have a valid scss syntax', () => { - const result = scss.renderSync({ - data: formatter(createFormatArgs({ - dictionary, + it('should have a valid scss syntax and match snapshot', async () => { + const result = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, file, - platform: {} - }), {}, file), - }); - expect(result.css).toBeDefined(); + platform: {}, + }), + {}, + file, + ); + const scssResult = compileString(result); + await expect(result).to.matchSnapshot(1); + await expect(scssResult.css).to.matchSnapshot(2); }); - it('should optionally use !default', () => { - var themeableDictionary = _.cloneDeep(dictionary), - formattedScss = formatter(createFormatArgs({ - dictionary, + it('should optionally use !default', async () => { + const themeableDictionary = { tokens, allTokens: flattenTokens(tokens) }; + const formattedScss = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, file, - platform: {} - }), {}, file), - themeableScss = ""; + platform: {}, + }), + {}, + file, + ); - expect(formattedScss).not.toMatch("!default"); + expect(formattedScss).not.to.match(new RegExp('!default;')); themeableDictionary.allTokens[0].themeable = true; - themeableScss = formatter(createFormatArgs({ - dictionary: themeableDictionary, + const themeableScss = await format( + createFormatArgs({ + dictionary: themeableDictionary, + file, + platform: {}, + }), + {}, file, - platform: {} - }), {}, file); + ); - expect(themeableScss).toMatch("#EF5350 !default;"); + expect(themeableScss).to.match(new RegExp('#EF5350 !default;')); }); }); }); diff --git a/__tests__/formats/stylusVariable.test.js b/__tests__/formats/stylusVariable.test.js index 8d8295e6e..c18e9ec2a 100644 --- a/__tests__/formats/stylusVariable.test.js +++ b/__tests__/formats/stylusVariable.test.js @@ -10,69 +10,57 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +// import stylus from 'stylus'; see comment in test below +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; -var formats = require('../../lib/common/formats'); -var stylus = require('stylus'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); - -var file = { - "destination": "__output/", - "format": "stylus/variables", - "name": "foo" +const file = { + destination: '__output/', + format: 'stylus/variables', + name: 'foo', }; -const propertyName = "color-base-red-400"; -const propertyValue = "#EF5350"; +const propertyName = 'color-base-red-400'; +const propertyValue = '#EF5350'; -const properties = { +const tokens = { color: { base: { red: { 400: { - "name": propertyName, - "value": propertyValue, - "original": { - "value": propertyValue - }, - "attributes": { - "category": "color", - "type": "base", - "item": "red", - "subitem": "400" + name: propertyName, + value: propertyValue, + original: { + value: propertyValue, }, - "path": [ - "color", - "base", - "red", - "400" - ] - } - } - } - } + path: ['color', 'base', 'red', '400'], + }, + }, + }, + }, }; -const formatter = formats['stylus/variables'].bind(file); -const dictionary = createDictionary({ properties }); +const format = formats['stylus/variables']; describe('formats', () => { describe('stylus/variables', () => { - - it('should have a valid stylus syntax', () => { - const stylusArguments = createFormatArgs({ - dictionary, + it('should have a valid stylus syntax and match snapshot', async () => { + const result = format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, file, - platform: {} - }); - stylus.render(formatter(stylusArguments, {}, file), - function (err, css) { - if (err) { - throw new Error(err); - } - expect(css).toBeDefined(); - }); - }); + ); + expect(result).to.matchSnapshot(1); + // Unfortunately, stylus has not followed less and scss in exposing + // a browser compatible version of the package to run client-side. + // const stylusResult = stylus.render(result); + // expect(stylusResult).to.matchSnapshot(2); + }); }); }); diff --git a/__tests__/formats/swiftFile.test.js b/__tests__/formats/swiftFile.test.js index 9eefeb4d6..5e828a693 100644 --- a/__tests__/formats/swiftFile.test.js +++ b/__tests__/formats/swiftFile.test.js @@ -10,26 +10,24 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); -const _ = require('../../lib/utils/es6_'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const originalFile = { - "destination": "__output/", - "format": "ios-swift/any.swift", - "className": "StyleDictionary", - "filter": { - "attributes": { - "category": "color" - } + destination: '__output/', + format: 'ios-swift/any.swift', + options: { + className: 'StyleDictionary', + }, + filter: { + type: 'color', }, - "options": {} }; -var file = {} +let file = {}; -const properties = { +const tokens = { color: { base: { red: { @@ -37,58 +35,77 @@ const properties = { filePath: 'tokens/color/base.json', original: { value: '#FF0000' }, name: 'colorBaseRed', - attributes: { category: 'color', type: 'base', item: 'red' }, - path: [ 'color', 'base', 'red' ] - } - } - } + path: ['color', 'base', 'red'], + }, + }, + }, }; const format = formats['ios-swift/any.swift']; -const dictionary = createDictionary({ properties }); describe('formats', () => { - describe('ios-swift/any.swift', () => { beforeEach(() => { - file = _.cloneDeep(originalFile); + file = structuredClone(originalFile); }); - it('should match default snapshot', () => { - expect(format(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)).toMatchSnapshot(); + it('should match default snapshot', async () => { + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - it('with import override should match snapshot', () => { - file.options.import = ["UIKit", "AnotherModule"]; - expect(format(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)).toMatchSnapshot(); + it('with import override should match snapshot', async () => { + file.options.import = ['UIKit', 'AnotherModule']; + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - it('with objectType override should match snapshot', () => { - file.options.objectType = "struct" - expect(format(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)).toMatchSnapshot(); + it('with objectType override should match snapshot', async () => { + file.options.objectType = 'struct'; + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - it('with access control override should match snapshot', () => { - file.options.accessControl = "internal" - expect(format(createFormatArgs({ - dictionary, - file, - platform: {} - }), {}, file)).toMatchSnapshot(); + it('with access control override should match snapshot', async () => { + file.options.accessControl = 'internal'; + await expect( + await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, + file, + ), + ).to.matchSnapshot(); }); - }); - -}); \ No newline at end of file +}); diff --git a/__tests__/formats/typeScriptEs6Declarations.test.js b/__tests__/formats/typeScriptEs6Declarations.test.js index b9517a71b..fc5df20cd 100644 --- a/__tests__/formats/typeScriptEs6Declarations.test.js +++ b/__tests__/formats/typeScriptEs6Declarations.test.js @@ -10,63 +10,70 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "typescript/es6-declarations" + destination: '__output/', + format: 'typescript/es6-declarations', }; -const properties = { - "color": { - "red": { - "comment": "Used for errors", - "name": "colorRed", - "value": "#FF0000" - } - } +const tokens = { + color: { + red: { + comment: 'Used for errors', + name: 'colorRed', + value: '#FF0000', + }, + }, + font: { + family: { + name: 'fontFamily', + value: '"Source Sans Pro", Arial, sans-serif', + }, + }, }; -const formatter = formats['typescript/es6-declarations'].bind(file); +const format = formats['typescript/es6-declarations']; describe('formats', () => { describe('typescript/es6-declarations', () => { - it('should be a valid TS file', () => { - const dictionary = createDictionary({ properties }); - const output = formatter(createFormatArgs({ - dictionary, - file, - platform: {}, - })); + it('should be a valid TS file', async () => { + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + ); // get all lines that begin with export - const lines = output - .split('\n') - .filter(l => l.indexOf('export') >= 0); + const lines = output.split('\n').filter((l) => l.indexOf('export') >= 0); // assert that any lines have a string type definition - lines.forEach(l => { - expect(l.match(/^export.* : string;$/g).length).toEqual(1); + lines.forEach((l) => { + expect(l.match(/^export.* : string;$/g).length).to.equal(1); }); }); - it('with outputStringLiterals should match snapshot', () => { - const customFile = Object.assign({}, file, { + it('with outputStringLiterals should match snapshot', async () => { + const customFile = { + ...file, options: { - outputStringLiterals: true - } - }); + outputStringLiterals: true, + }, + }; - const dictionary = createDictionary({ properties }); - const output = formatter(createFormatArgs({ - dictionary, - file: customFile, - platform: {}, - })); + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file: customFile, + platform: {}, + }), + ); - expect(output).toMatchSnapshot(); + await expect(output).to.matchSnapshot(); }); }); }); diff --git a/__tests__/formats/typeScriptModuleDeclarations.test.js b/__tests__/formats/typeScriptModuleDeclarations.test.js index 73ac8fb25..43048ed09 100644 --- a/__tests__/formats/typeScriptModuleDeclarations.test.js +++ b/__tests__/formats/typeScriptModuleDeclarations.test.js @@ -10,47 +10,43 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ -const formats = require('../../lib/common/formats'); -const createDictionary = require('../../lib/utils/createDictionary'); -const createFormatArgs = require('../../lib/utils/createFormatArgs'); +import { expect } from 'chai'; +import formats from '../../dist/esm/common/formats.mjs'; +import { createFormatArgs, flattenTokens } from 'style-dictionary/utils'; const file = { - "destination": "__output/", - "format": "typescript/module-declarations", - "filter": { - "attributes": { - "category": "color" - } - } + destination: '__output/', + format: 'typescript/module-declarations', + filter: { type: 'color' }, }; -const properties = { - "color": { - "red": {"value": "#FF0000"} - } +const tokens = { + color: { + red: { value: '#FF0000' }, + }, }; - -var formatter = formats['typescript/module-declarations'].bind(file); +const format = formats['typescript/module-declarations'].bind(file); describe('formats', () => { describe('typescript/module-declarations', () => { - it('should be a valid TS file', () => { - const dictionary = createDictionary({ properties }); - const output = formatter(createFormatArgs({ - dictionary, + it('should be a valid TS file', async () => { + const output = await format( + createFormatArgs({ + dictionary: { tokens, allTokens: flattenTokens(tokens) }, + file, + platform: {}, + }), + {}, file, - platform: {}, - }), {}, file); + ); // get all lines that have DesignToken - const lines = output - .split('\n') - .filter(l => l.indexOf(': DesignToken') >= 0); + const lines = output.split('\n').filter((l) => l.indexOf(': DesignToken') >= 0); // assert that any lines have a DesignToken type definition - lines.forEach(l => { - expect(l.match(/^.*: DesignToken$/g).length).toEqual(1); + lines.forEach((l) => { + expect(l.match(/^.*: DesignToken$/g).length).to.equal(1); }); }); }); diff --git a/__tests__/nameCollisions.test.snap.js b/__tests__/nameCollisions.test.snap.js new file mode 100644 index 000000000..fe25bec64 --- /dev/null +++ b/__tests__/nameCollisions.test.snap.js @@ -0,0 +1,22 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration name collisions should warn users of name collisions for flat files"] = +`⚠️ __integration__/build/variables.css +While building variables.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. +Output name red was generated by: +color.red #f00 +color.background.red #f00 +This many-to-one issue is usually caused by some combination of: +* conflicting or similar paths/names in token definitions +* platform transforms/transformGroups affecting names, especially when removing specificity +* overly inclusive file filters`; +/* end snapshot integration name collisions should warn users of name collisions for flat files */ + +snapshots["integration name collisions should warn users of name collisions for flat files, brief version"] = +`⚠️ __integration__/build/variables.css +While building variables.css, token collisions were found; output may be unexpected. Ignore this warning if intentional. + +Use log.verbosity "verbose" or use CLI option --verbose for more details.`; +/* end snapshot integration name collisions should warn users of name collisions for flat files, brief version */ + diff --git a/__tests__/performAction.test.js b/__tests__/performAction.test.js index aad21193e..d90366691 100644 --- a/__tests__/performAction.test.js +++ b/__tests__/performAction.test.js @@ -10,43 +10,71 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var StyleDictionary = require('../index'); -var StyleDictionaryExtended = StyleDictionary.extend({ - "platforms": { - "android": { - "actions": ["test"] - } - } -}); -var helpers = require('./__helpers'); -var fs = require('fs-extra'); - -StyleDictionaryExtended.registerAction({ - name: 'test', - do: function() { - fs.writeFileSync('./__tests__/__output/action.txt', 'hi') - }, - undo: function() { - fs.removeSync('./__tests__/__output/action.txt') - } -}); +import { expect } from 'chai'; +import { fs } from 'style-dictionary/fs'; +import StyleDictionary from 'style-dictionary'; +import { clearOutput, fileExists } from './__helpers.js'; describe('performAction', () => { - beforeEach(() => { - helpers.clearOutput(); + clearOutput(); }); afterEach(() => { - helpers.clearOutput(); + clearOutput(); }); describe('handle actions', () => { - it('should write to a file properly', () => { - StyleDictionaryExtended.buildPlatform('android'); - expect(helpers.fileExists('./__tests__/__output/action.txt')).toBeTruthy(); + it('should write to a file properly', async () => { + const sd = new StyleDictionary({ + platforms: { + android: { + actions: ['test'], + files: [], + }, + }, + }); + await sd.hasInitialized; + + sd.registerAction({ + name: 'test', + do: function () { + fs.mkdirSync('__tests__/__output', { recursive: true }); + fs.writeFileSync('__tests__/__output/action.txt', 'hi', 'utf-8'); + }, + undo: function () { + fs.unlinkSync('__tests__/__output/action.txt'); + }, + }); + await sd.buildPlatform('android'); + + expect(fileExists('__tests__/__output/action.txt')).to.be.true; }); - }); + it('should handle async actions to write to a file', async () => { + const sd = new StyleDictionary({ + platforms: { + android: { + actions: ['test-async'], + files: [], + }, + }, + }); + await sd.hasInitialized; + + sd.registerAction({ + name: 'test-async', + do: async function () { + fs.promises.mkdir('__tests__/__output', { recursive: true }); + fs.promises.writeFile('__tests__/__output/action.txt', 'hi', 'utf-8'); + }, + undo: async function () { + fs.promises.unlink('__tests__/__output/action.txt'); + }, + }); + await sd.buildPlatform('android'); + + expect(fileExists('__tests__/__output/action.txt')).to.be.true; + }); + }); }); diff --git a/__tests__/register/action.test.js b/__tests__/register/action.test.js index 889954acb..2167b62ca 100644 --- a/__tests__/register/action.test.js +++ b/__tests__/register/action.test.js @@ -10,99 +10,108 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +registerSuite({ + config: { + do: () => {}, + undo: () => {}, + }, + registerMethod: 'registerAction', + prop: 'actions', +}); describe('register', () => { - describe('action', () => { + describe('action', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); it('should error if name is not a string', () => { - expect( - StyleDictionaryExtended.registerAction.bind(null, { - do: function() {} - }) - ).toThrow('name must be a string'); + expect(() => { + StyleDictionaryExtended.registerAction({ + do: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: 1, - do: function() {} - }) - ).toThrow('name must be a string'); + do: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: [], - do: function() {} - }) - ).toThrow('name must be a string'); + do: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: {}, - do: function() {} - }) - ).toThrow('name must be a string'); + do: function () {}, + }); + }).to.throw('name must be a string'); }); it('should error if do is not a function', () => { - expect( - StyleDictionaryExtended.registerAction.bind(null, { - name: 'test' - }) - ).toThrow('do must be a function'); + expect(() => { + StyleDictionaryExtended.registerAction({ + name: 'test', + }); + }).to.throw('do must be a function'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: 'test', - do: 1 - }) - ).toThrow('do must be a function'); + do: 1, + }); + }).to.throw('do must be a function'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: 'test', - do: 'name' - }) - ).toThrow('do must be a function'); + do: 'name', + }); + }).to.throw('do must be a function'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: 'test', - do: [] - }) - ).toThrow('do must be a function'); + do: [], + }); + }).to.throw('do must be a function'); - expect( - StyleDictionaryExtended.registerAction.bind(null, { + expect(() => { + StyleDictionaryExtended.registerAction({ name: 'test', - do: {} - }) - ).toThrow('do must be a function'); + do: {}, + }); + }).to.throw('do must be a function'); }); it('should work if name and do are good', () => { StyleDictionaryExtended.registerAction({ name: 'scss', - do: function() {} + do: function () {}, }); - expect(typeof StyleDictionaryExtended.action['scss'].do).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.actions['scss'].do).to.equal('function'); }); it('should handle an undo function', () => { StyleDictionaryExtended.registerAction({ name: 'scss', - do: function() {}, - undo: function() {} + do: function () {}, + undo: function () {}, }); - expect(typeof StyleDictionaryExtended.action['scss'].undo).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.actions['scss'].undo).to.equal('function'); }); - it('should properly pass the registered format to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(typeof SDE2.action['scss'].do).toBe('function'); + it('should properly pass the registered format to instances', async () => { + const SDE2 = await StyleDictionaryExtended.extend({}); + expect(typeof SDE2.hooks.actions['scss'].do).to.equal('function'); }); - }); }); diff --git a/__tests__/register/fileHeader.test.js b/__tests__/register/fileHeader.test.js index 219359879..5a30bbfa8 100644 --- a/__tests__/register/fileHeader.test.js +++ b/__tests__/register/fileHeader.test.js @@ -10,90 +10,100 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +registerSuite({ + config: { + fileHeader: () => {}, + }, + registerMethod: 'registerFileHeader', + prop: 'fileHeaders', +}); describe('register', () => { - describe('fileHeader', () => { + describe('fileHeader', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); it('should error if name is not a string', () => { - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { - fileHeader: function () {} - }) - ).toThrow('name must be a string'); + expect(() => { + StyleDictionaryExtended.registerFileHeader({ + fileHeader: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: 1, - fileHeader: function () {} - }) - ).toThrow('name must be a string'); + fileHeader: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: [], - fileHeader: function () {} - }) - ).toThrow('name must be a string'); + fileHeader: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: {}, - matcher: function () {} - }) - ).toThrow('name must be a string'); + fileHeader: function () {}, + }); + }).to.throw('name must be a string'); }); it('should error if fileHeader is not a function', () => { - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { - name: 'myCustomHeader' - }) - ).toThrow('fileHeader must be a function'); + expect(() => { + StyleDictionaryExtended.registerFileHeader({ + name: 'myCustomHeader', + }); + }).to.throw('fileHeader must be a function'); - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: 'myCustomHeader', - fileHeader: 1 - }) - ).toThrow('fileHeader must be a function'); + fileHeader: 1, + }); + }).to.throw('fileHeader must be a function'); - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: 'myCustomHeader', - fileHeader: 'name' - }) - ).toThrow('fileHeader must be a function'); + fileHeader: 'name', + }); + }).to.throw('fileHeader must be a function'); - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: 'myCustomHeader', - fileHeader: [] - }) - ).toThrow('fileHeader must be a function'); + fileHeader: [], + }); + }).to.throw('fileHeader must be a function'); - expect( - StyleDictionaryExtended.registerFileHeader.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFileHeader({ name: 'myCustomHeader', - fileHeader: {} - }) - ).toThrow('fileHeader must be a function'); + fileHeader: {}, + }); + }).to.throw('fileHeader must be a function'); }); - it('should work if name and matcher are good', () => { + it('should work if name and fileHeader are good', () => { StyleDictionaryExtended.registerFileHeader({ name: 'myCustomHeader', - fileHeader: function() {} + fileHeader: function () {}, }); - expect(typeof StyleDictionaryExtended.fileHeader['myCustomHeader']).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.fileHeaders['myCustomHeader']).to.equal( + 'function', + ); }); - it('should properly pass the registered fileHeader to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(typeof SDE2.fileHeader['myCustomHeader']).toBe('function'); + it('should properly pass the registered fileHeader to instances', async () => { + const SDE2 = await StyleDictionaryExtended.extend({}); + expect(typeof SDE2.hooks.fileHeaders['myCustomHeader']).to.equal('function'); }); - }); }); diff --git a/__tests__/register/filter.test.js b/__tests__/register/filter.test.js index 49487aa61..b6b06be0f 100644 --- a/__tests__/register/filter.test.js +++ b/__tests__/register/filter.test.js @@ -10,90 +10,98 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +registerSuite({ + config: { + filter: () => {}, + }, + registerMethod: 'registerFilter', + prop: 'filters', +}); describe('register', () => { - describe('filter', () => { + describe('filter', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); it('should error if name is not a string', () => { - expect( - StyleDictionaryExtended.registerFilter.bind(null, { - matcher: function () {} - }) - ).toThrow('name must be a string'); + expect(() => { + StyleDictionaryExtended.registerFilter({ + filter: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: 1, - matcher: function () {} - }) - ).toThrow('name must be a string'); + filter: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: [], - matcher: function () {} - }) - ).toThrow('name must be a string'); + filter: function () {}, + }); + }).to.throw('name must be a string'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: {}, - matcher: function () {} - }) - ).toThrow('name must be a string'); + filter: function () {}, + }); + }).to.throw('name must be a string'); }); - it('should error if matcher is not a function', () => { - expect( - StyleDictionaryExtended.registerFilter.bind(null, { - name: 'test' - }) - ).toThrow('matcher must be a function'); + it('should error if filter is not a function', () => { + expect(() => { + StyleDictionaryExtended.registerFilter({ + name: 'test', + }); + }).to.throw('filter must be a function'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: 'test', - matcher: 1 - }) - ).toThrow('matcher must be a function'); + filter: 1, + }); + }).to.throw('filter must be a function'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: 'test', - matcher: 'name' - }) - ).toThrow('matcher must be a function'); + filter: 'name', + }); + }).to.throw('filter must be a function'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: 'test', - matcher: [] - }) - ).toThrow('matcher must be a function'); + filter: [], + }); + }).to.throw('filter must be a function'); - expect( - StyleDictionaryExtended.registerFilter.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFilter({ name: 'test', - matcher: {} - }) - ).toThrow('matcher must be a function'); + filter: {}, + }); + }).to.throw('filter must be a function'); }); - it('should work if name and matcher are good', () => { + it('should work if name and filter are good', () => { StyleDictionaryExtended.registerFilter({ name: 'scss', - matcher: function() {} + filter: function () {}, }); - expect(typeof StyleDictionaryExtended.filter['scss']).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.filters['scss']).to.equal('function'); }); - it('should properly pass the registered filter to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(typeof SDE2.filter['scss']).toBe('function'); + it('should properly pass the registered filter to instances', async () => { + const SDE2 = await StyleDictionaryExtended.extend({}); + expect(typeof SDE2.hooks.filters['scss']).to.equal('function'); }); - }); }); diff --git a/__tests__/register/format.test.js b/__tests__/register/format.test.js index a6cebdbaf..80dd6872d 100644 --- a/__tests__/register/format.test.js +++ b/__tests__/register/format.test.js @@ -10,92 +10,100 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +registerSuite({ + config: { + format: () => {}, + }, + registerMethod: 'registerFormat', + prop: 'formats', +}); describe('register', () => { - describe('format', () => { + describe('format', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); it('should error if name is not a string', () => { - const errorMessage = `Can't register format; format.name must be a string` - expect( - StyleDictionaryExtended.registerFormat.bind(null, { - formatter: function() {} - }) - ).toThrow(errorMessage); + const errorMessage = `Can't register format; format.name must be a string`; + expect(() => { + StyleDictionaryExtended.registerFormat({ + format: function () {}, + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: 1, - formatter: function() {} - }) - ).toThrow(errorMessage); + format: function () {}, + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: [], - formatter: function() {} - }) - ).toThrow(errorMessage); + format: function () {}, + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: {}, - formatter: function() {} - }) - ).toThrow(errorMessage); + format: function () {}, + }); + }).to.throw(errorMessage); }); it('should error if format is not a function', () => { - const errorMessage = `Can't register format; format.formatter must be a function` - expect( - StyleDictionaryExtended.registerFormat.bind(null, { - name: 'test' - }) - ).toThrow(errorMessage); + const errorMessage = `Can't register format; format.format must be a function`; + expect(() => { + StyleDictionaryExtended.registerFormat({ + name: 'test', + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: 'test', - formatter: 1 - }) - ).toThrow(errorMessage); + format: 1, + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: 'test', - formatter: 'name' - }) - ).toThrow(errorMessage); + format: 'name', + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: 'test', - formatter: [] - }) - ).toThrow(errorMessage); + format: [], + }); + }).to.throw(errorMessage); - expect( - StyleDictionaryExtended.registerFormat.bind(null, { + expect(() => { + StyleDictionaryExtended.registerFormat({ name: 'test', - formatter: {} - }) - ).toThrow(errorMessage); + format: {}, + }); + }).to.throw(errorMessage); }); it('should work if name and format are good', () => { StyleDictionaryExtended.registerFormat({ name: 'scss', - formatter: function() {} + format: function () {}, }); - expect(typeof StyleDictionaryExtended.format['scss']).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.formats['scss']).to.equal('function'); }); - it('should properly pass the registered format to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(typeof SDE2.format['scss']).toBe('function'); + it('should properly pass the registered format to instances', async () => { + const SDE2 = await StyleDictionaryExtended.extend({}); + expect(typeof SDE2.hooks.formats['scss']).to.equal('function'); }); - }); }); diff --git a/__tests__/register/parser.test.js b/__tests__/register/parser.test.js index b38475a9d..b52291d5a 100644 --- a/__tests__/register/parser.test.js +++ b/__tests__/register/parser.test.js @@ -10,90 +10,128 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +registerSuite({ + config: { + pattern: /\.json/g, + parser: () => {}, + }, + registerMethod: 'registerParser', + prop: 'parsers', +}); describe('register', () => { - describe('parser', () => { + describe('parser', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); + + it('should error if name is not a string', () => { + expect(() => { + StyleDictionaryExtended.registerParser({ + pattern: /$.json/, + parser: function () {}, + }); + }).to.throw("Can't register parser; parser.name must be a string"); + + expect(() => { + StyleDictionaryExtended.registerParser({ + name: {}, + pattern: /$.json/, + parser: function () {}, + }); + }).to.throw("Can't register parser; parser.name must be a string"); + }); it('should error if pattern is not a regex', () => { - expect( - StyleDictionaryExtended.registerParser.bind(null, { - parse: function () {} - }) - ).toThrow('pattern must be a regular expression'); + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', + parser: function () {}, + }); + }).to.throw('pattern must be a regular expression'); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: 1, - parse: function () {} - }) - ).toThrow('pattern must be a regular expression'); + parser: function () {}, + }); + }).to.throw('pattern must be a regular expression'); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: [], - parse: function () {} - }) - ).toThrow('pattern must be a regular expression'); + parser: function () {}, + }); + }).to.throw('pattern must be a regular expression'); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: {}, - parse: function () {} - }) - ).toThrow('pattern must be a regular expression'); + parser: function () {}, + }); + }).to.throw('pattern must be a regular expression'); }); it('should error if parser is not a function', () => { - expect( - StyleDictionaryExtended.registerParser.bind(null, { - pattern: /$.json/ - }) - ).toThrow('parse must be a function'); + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', + pattern: /$.json/, + }); + }).to.throw("Can't register parser; parser.parser must be a function"); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: /$.json/, - parse: 1 - }) - ).toThrow('parse must be a function'); + parser: 1, + }); + }).to.throw("Can't register parser; parser.parser must be a function"); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: /$.json/, - parse: 'name' - }) - ).toThrow('parse must be a function'); + parser: 'name', + }); + }).to.throw("Can't register parser; parser.parser must be a function"); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: /$.json/, - parse: [] - }) - ).toThrow('parse must be a function'); + parser: [], + }); + }).to.throw("Can't register parser; parser.parser must be a function"); - expect( - StyleDictionaryExtended.registerParser.bind(null, { + expect(() => { + StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: /$.json/, - parse: {} - }) - ).toThrow('parse must be a function'); + parser: {}, + }); + }).to.throw("Can't register parser; parser.parser must be a function"); }); it('should work if pattern and parser are good', () => { StyleDictionaryExtended.registerParser({ + name: 'json-parser', pattern: /$.json/, - parse: function() {} + parser: function () {}, }); - expect(typeof StyleDictionaryExtended.parsers[0].parse).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.parsers['json-parser'].parser).to.equal( + 'function', + ); }); - it('should properly pass the registered filter to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(typeof SDE2.parsers[0].parse).toBe('function'); + it('should properly pass the registered filter to instances', async () => { + const SDE2 = await StyleDictionaryExtended.extend({}); + expect(typeof SDE2.hooks.parsers['json-parser'].parser).to.equal('function'); }); - }); }); diff --git a/__tests__/register/preprocessor.test.js b/__tests__/register/preprocessor.test.js new file mode 100644 index 000000000..f3d66d37e --- /dev/null +++ b/__tests__/register/preprocessor.test.js @@ -0,0 +1,166 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; + +registerSuite({ + config: { + preprocessor: () => {}, + }, + registerMethod: 'registerPreprocessor', + prop: 'preprocessors', +}); + +describe('register/transformGroup', async () => { + let StyleDictionaryExtended; + beforeEach(async () => { + StyleDictionary.hooks.preprocessors = {}; + StyleDictionaryExtended = new StyleDictionary({}); + await StyleDictionaryExtended.hasInitialized; + }); + + it('should support registering preprocessor on StyleDictionary class', () => { + StyleDictionary.registerPreprocessor({ + name: 'example-preprocessor', + preprocessor: (dict) => dict, + }); + expect(StyleDictionary.hooks.preprocessors['example-preprocessor']).to.not.be.undefined; + expect(StyleDictionaryExtended.hooks.preprocessors['example-preprocessor']).to.not.be.undefined; + }); + + it('should throw if the preprocessor name is not a string', () => { + expect(() => { + StyleDictionaryExtended.registerPreprocessor({ + name: true, + preprocessor: (dict) => dict, + }); + }).to.throw('Cannot register preprocessor; Preprocessor.name must be a string'); + }); + + it('should throw if the preprocessor is not a function', () => { + expect(() => { + StyleDictionaryExtended.registerPreprocessor({ + name: 'example-preprocessor', + preprocessor: 'foo', + }); + }).to.throw('Cannot register preprocessor; Preprocessor.preprocessor must be a function'); + }); + + it('should preprocess the dictionary as specified', async () => { + StyleDictionary.registerPreprocessor({ + name: 'strip-descriptions', + preprocessor: (dict) => { + // recursively traverse token objects and delete description props + function removeDescription(slice) { + delete slice.description; + Object.values(slice).forEach((value) => { + if (typeof value === 'object') { + removeDescription(value); + } + }); + return slice; + } + return removeDescription(dict); + }, + }); + + StyleDictionaryExtended = new StyleDictionary({ + preprocessors: ['strip-descriptions'], + tokens: { + foo: { + value: '4px', + type: 'dimension', + description: 'Foo description', + }, + description: 'My dictionary', + }, + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql({ + foo: { + value: '4px', + type: 'dimension', + }, + }); + }); + + it('should support async preprocessors', async () => { + StyleDictionary.registerPreprocessor({ + name: 'strip-descriptions', + preprocessor: async (dict) => { + // recursively traverse token objects and delete description props + async function removeDescription(slice) { + // Arbitrary delay, act as though this action is asynchronous and takes some time + await new Promise((resolve) => setTimeout(resolve, 100)); + delete slice.description; + + await Promise.all( + Object.values(slice).map((value) => { + if (typeof value === 'object') { + return removeDescription(value); + } else { + return Promise.resolve(); + } + }), + ); + return slice; + } + return removeDescription(dict); + }, + }); + + StyleDictionaryExtended = new StyleDictionary({ + preprocessors: ['strip-descriptions'], + tokens: { + foo: { + value: '4px', + type: 'dimension', + description: 'Foo description', + }, + description: 'My dictionary', + }, + }); + await StyleDictionaryExtended.hasInitialized; + expect(StyleDictionaryExtended.tokens).to.eql({ + foo: { + value: '4px', + type: 'dimension', + }, + }); + }); + + it('should pass options to preprocessor function as second argument', async () => { + let opts; + StyleDictionary.registerPreprocessor({ + name: 'foo-processor', + preprocessor: async (dict, options) => { + opts = options; + return dict; + }, + }); + + StyleDictionaryExtended = new StyleDictionary({ + preprocessors: ['foo-processor'], + tokens: { + foo: { + $value: '4px', + $type: 'dimension', + $description: 'Foo description', + }, + }, + }); + await StyleDictionaryExtended.hasInitialized; + expect(opts.usesDtcg).to.be.true; + }); +}); diff --git a/__tests__/register/register.suite.js b/__tests__/register/register.suite.js new file mode 100644 index 000000000..8c0d53b3d --- /dev/null +++ b/__tests__/register/register.suite.js @@ -0,0 +1,79 @@ +import StyleDictionary from 'style-dictionary'; +import { expect } from 'chai'; + +export function registerSuite(opts) { + /** + * opts example: { + * config: { transform: () => {} }, + * registerMethod: 'registerTransform', + * prop: 'transform', + * } + * This suite verifies a couple of rules with regards to registering something on class vs instance + */ + const { config, registerMethod, prop, defaultPropVal = {} } = opts; + const configFoo = { ...config, name: 'foo' }; + // same config but under a different name, needed for the third test + const configBar = { ...config, name: 'bar' }; + + describe('Register Test Suite', () => { + const reset = () => { + StyleDictionary.hooks[prop] = defaultPropVal; + }; + beforeEach(() => { + reset(); + }); + afterEach(() => { + reset(); + }); + + describe(`instance vs class registration: ${prop}`, () => { + it(`should allow registering ${prop} on class, affecting all instances`, async () => { + StyleDictionary[registerMethod](configFoo); + + const sd1 = new StyleDictionary(); + const sd2 = new StyleDictionary(); + const sd3 = await sd2.extend(); + expect(sd1.hooks[prop][configFoo.name]).to.not.be.undefined; + expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined; + expect(sd3.hooks[prop][configFoo.name]).to.not.be.undefined; + }); + + it(`should allow registering ${prop} on instance, affecting only that instance`, async () => { + const sd1 = new StyleDictionary(); + const sd2 = new StyleDictionary(); + const sd3 = await sd2.extend(); + + sd2[registerMethod](configFoo); + expect(sd1.hooks[prop][configFoo.name]).to.be.undefined; + expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined; + expect(sd3.hooks[prop][configFoo.name]).to.be.undefined; + }); + + it(`should combine class and instance registrations for ${prop} on the instance`, async () => { + StyleDictionary[registerMethod](configFoo); + + const sd1 = new StyleDictionary(); + const sd2 = new StyleDictionary(); + sd2[registerMethod](configBar); + const sd3 = await sd2.extend(); + + expect(sd1.hooks[prop][configFoo.name]).to.not.be.undefined; + expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined; + expect(sd3.hooks[prop][configFoo.name]).to.not.be.undefined; + // should not be registered on sd1, because we registered only on sd2 + expect(sd1.hooks[prop][configBar.name]).to.be.undefined; + expect(sd2.hooks[prop][configBar.name]).to.not.be.undefined; + // should be registered because sd3 extends sd2 + expect(sd3.hooks[prop][configBar.name]).to.not.be.undefined; + }); + + it(`should allow registering an already existing hook and overriding it`, async () => { + StyleDictionary.hooks[prop][configFoo.name] = { + prop: '_test_', + }; + StyleDictionary[registerMethod](configFoo); + expect(StyleDictionary.hooks[prop][configFoo.name].prop).to.be.undefined; + }); + }); + }); +} diff --git a/__tests__/register/template.test.js b/__tests__/register/template.test.js deleted file mode 100644 index 1aaae8818..000000000 --- a/__tests__/register/template.test.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var StyleDictionary = require('../../index').extend({}); - - -describe('registerTemplate', function() { - it('should error if name is not a string', function() { - expect( - StyleDictionary.registerTemplate.bind(null, {}) - ).toThrow(/Template name must be a string:/); - - expect( - StyleDictionary.registerTemplate.bind(null, { - name: 1, - }) - ).toThrow(/Template name must be a string:/); - - expect( - StyleDictionary.registerTemplate.bind(null, { - name: [], - }) - ).toThrow(/Template name must be a string:/); - - expect( - StyleDictionary.registerTemplate.bind(null, { - name: {}, - }) - ).toThrow(/Template name must be a string:/); - }); - - it('should error if path is not a string', function() { - expect( - StyleDictionary.registerTemplate.bind(null, { - name: 'data', - }) - ).toThrow(/Template path must be a string:/); - - expect( - StyleDictionary.registerTemplate.bind(null, { - name: 'data', - template: 1, - }) - ).toThrow(/Template path must be a string:/); - - expect( - StyleDictionary.registerTemplate.bind(null, { - name: 'data', - template: [], - }) - ).toThrow(/Template path must be a string:/); - - expect( - StyleDictionary.registerTemplate.bind(null, { - name: 'data', - template: {}, - }) - ).toThrow(/Template path must be a string:/); - }); - - it('should error if path is not a file', function() { - expect( - StyleDictionary.registerTemplate.bind(null, { - name: 'data', - template: 'non_existent_file', - }) - ).toThrow(/Can't find template: /); - }); - - it('should return StyleDictionary', function() { - expect( - StyleDictionary.registerTemplate({ - name: 'data', - template: 'index.js', - }) - ).toMatchObject(StyleDictionary); - }); -}); diff --git a/__tests__/register/transform.test.js b/__tests__/register/transform.test.js index c3364e870..e4d60ef25 100644 --- a/__tests__/register/transform.test.js +++ b/__tests__/register/transform.test.js @@ -10,79 +10,241 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; +import transformBuiltins from '../../dist/esm/common/transforms.mjs'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +const transformPxAppender = { + name: 'px-appender', + type: 'value', + transform: (token) => `${token.value}px`, +}; + +const transformValueIncrementer = { + name: 'value-incrementer', + type: 'value', + filter: (token) => typeof token.value === 'number', + transform: (token) => token.value + 1, +}; + +registerSuite({ + config: { + type: 'value', + transform: () => {}, + }, + registerMethod: 'registerTransform', + prop: 'transforms', +}); describe('register', () => { - describe('transform', () => { + beforeEach(() => { + StyleDictionary.hooks.transforms = transformBuiltins; + }); + afterEach(() => { + StyleDictionary.hooks.transforms = transformBuiltins; + }); + + describe('instance vs class registration', () => { + it('should allow registering on class, affecting all instances', async () => { + StyleDictionary.registerTransform(transformPxAppender); + + const baseCfg = { + platforms: { + test: { + transforms: ['px-appender'], + }, + }, + }; + + const sd1 = new StyleDictionary({ + ...baseCfg, + tokens: { + size1: { + value: 1, + type: 'dimension', + }, + }, + }); + const sd2 = new StyleDictionary({ + ...baseCfg, + tokens: { + size2: { + value: 2, + type: 'dimension', + }, + }, + }); + const sd3 = await sd2.extend({ + ...baseCfg, + tokens: { + size3: { + value: 3, + type: 'dimension', + }, + }, + }); + + const [sd1After, sd2After, sd3After] = await Promise.all( + [sd1, sd2, sd3].map((sd) => sd.exportPlatform('test')), + ); + + expect(sd1.hooks.transforms['px-appender']).to.not.be.undefined; + expect(sd2.hooks.transforms['px-appender']).to.not.be.undefined; + expect(sd3.hooks.transforms['px-appender']).to.not.be.undefined; + + expect(sd1After.size1.value).to.equal('1px'); + expect(sd2After.size2.value).to.equal('2px'); + expect(sd3After.size2.value).to.equal('2px'); + expect(sd3After.size3.value).to.equal('3px'); + }); + + it('should allow registering on instance, affecting only that instance', async () => { + const sd1 = new StyleDictionary(); + const sd2 = new StyleDictionary(); + const sd3 = await sd2.extend(); + + sd2.registerTransform(transformPxAppender); + + expect(sd1.hooks.transforms['px-appender']).to.be.undefined; + expect(sd2.hooks.transforms['px-appender']).to.not.be.undefined; + expect(sd3.hooks.transforms['px-appender']).to.be.undefined; + }); + + it('should combine class and instance registrations on the instance', async () => { + StyleDictionary.registerTransform(transformPxAppender); + + const sd1 = new StyleDictionary({ + platforms: { + test: { + transforms: ['px-appender'], + }, + }, + tokens: { + size1: { + value: 1, + type: 'dimension', + }, + }, + }); + + const sd2 = new StyleDictionary({ + platforms: { + test: { + transforms: ['value-incrementer', 'px-appender'], + }, + }, + tokens: { + size2: { + value: 2, + type: 'dimension', + }, + }, + }); + sd2.registerTransform(transformValueIncrementer); + + const sd3 = await sd2.extend({ + tokens: { + size3: { + value: 3, + type: 'dimension', + }, + }, + }); + + const [sd1After, sd2After, sd3After] = await Promise.all( + [sd1, sd2, sd3].map((sd) => sd.exportPlatform('test')), + ); + + expect(sd1.hooks.transforms['px-appender']).to.not.be.undefined; + expect(sd2.hooks.transforms['px-appender']).to.not.be.undefined; + expect(sd3.hooks.transforms['px-appender']).to.not.be.undefined; + // should not be registered on sd1, because we registered only on sd2 + expect(sd1.hooks.transforms['value-incrementer']).to.be.undefined; + expect(sd2.hooks.transforms['value-incrementer']).to.not.be.undefined; + // should be registered because sd3 extends sd2 + expect(sd3.hooks.transforms['value-incrementer']).to.not.be.undefined; + + expect(sd1After.size1.value).to.equal('1px'); + expect(sd2After.size2.value).to.equal('3px'); + expect(sd3After.size2.value).to.equal('3px'); + expect(sd3After.size3.value).to.equal('4px'); + }); + }); + + describe('transform', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); it('should error if type is not a string', () => { - expect( - StyleDictionaryExtended.registerTransform.bind(null, { - type: 3 - }) - ).toThrow('type must be a string'); + expect(() => { + StyleDictionaryExtended.registerTransform({ + type: 3, + }); + }).to.throw('type must be a string'); }); it('should error if type is not a valid type', () => { - expect( - StyleDictionaryExtended.registerTransform.bind(null, { - type: 'foo' - }) - ).toThrow('foo type is not one of: name, value, attribute'); + expect(() => { + StyleDictionaryExtended.registerTransform({ + type: 'foo', + }); + }).to.throw('foo type is not one of: name, value, attribute'); }); it('should error if name is not a string', () => { - expect( - StyleDictionaryExtended.registerTransform.bind(null, { - type: 'name' - }) - ).toThrow('name must be a string'); + expect(() => { + StyleDictionaryExtended.registerTransform({ + type: 'name', + }); + }).to.throw('name must be a string'); }); - it('should error if matcher is not a function', () => { - expect( - StyleDictionaryExtended.registerTransform.bind(null, { + it('should error if filter is not a function', () => { + expect(() => { + StyleDictionaryExtended.registerTransform({ type: 'name', name: 'name', - matcher: 'foo' - }) - ).toThrow('matcher must be a function'); + filter: 'foo', + }); + }).to.throw('filter must be a function'); }); - it('should error if transformer is not a function', () => { - expect( - StyleDictionaryExtended.registerTransform.bind(null, { + it('should error if transform is not a function', () => { + expect(() => { + StyleDictionaryExtended.registerTransform({ type: 'name', name: 'name', - matcher: function() { return true; }, - transformer: 'foo' - }) - ).toThrow('transformer must be a function'); + filter: function () { + return true; + }, + transform: 'foo', + }); + }).to.throw('transform must be a function'); }); - it('should work if type, matcher, and transformer are all proper', () => { + it('should work if type, filter, and transform are all proper', () => { StyleDictionaryExtended.registerTransform({ type: 'name', name: 'foo', - matcher: function() { return true; }, - transformer: function() { return true; } + filter: function () { + return true; + }, + transform: function () { + return true; + }, }); - expect(typeof StyleDictionaryExtended.transform.foo).toBe('object'); - expect(StyleDictionaryExtended).toHaveProperty('transform.foo.type', 'name'); - expect(typeof StyleDictionaryExtended.transform.foo.matcher).toBe('function'); - expect(typeof StyleDictionaryExtended.transform.foo.transformer).toBe('function'); + expect(typeof StyleDictionaryExtended.hooks.transforms.foo).to.equal('object'); + expect(StyleDictionaryExtended).to.have.nested.property('hooks.transforms.foo.type', 'name'); + expect(typeof StyleDictionaryExtended.hooks.transforms.foo.filter).to.equal('function'); + expect(typeof StyleDictionaryExtended.hooks.transforms.foo.transform).to.equal('function'); }); - - it('should properly pass the registered transform to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(typeof SDE2.transform.foo).toBe('object'); - expect(SDE2).toHaveProperty('transform.foo.type', 'name'); - expect(typeof SDE2.transform.foo.matcher).toBe('function'); - expect(typeof SDE2.transform.foo.transformer).toBe('function'); + it('should properly pass the registered transform to instances', async () => { + const SDE2 = await StyleDictionaryExtended.extend({}); + expect(typeof SDE2.hooks.transforms.foo).to.equal('object'); + expect(SDE2).to.have.nested.property('hooks.transforms.foo.type', 'name'); + expect(typeof SDE2.hooks.transforms.foo.filter).to.equal('function'); + expect(typeof SDE2.hooks.transforms.foo.transform).to.equal('function'); }); - }); }); diff --git a/__tests__/register/transformGroup.test.js b/__tests__/register/transformGroup.test.js index 27e05ccbf..9410e273f 100644 --- a/__tests__/register/transformGroup.test.js +++ b/__tests__/register/transformGroup.test.js @@ -10,100 +10,116 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { registerSuite } from './register.suite.js'; -var StyleDictionary = require('../../index'); -var StyleDictionaryExtended = StyleDictionary.extend({}); +const dummyTransformName = 'transformGroup.test.js'; + +registerSuite({ + config: { + transforms: ['size/px'], + }, + registerMethod: 'registerTransformGroup', + prop: 'transformGroups', +}); + +describe('register/transformGroup', async () => { + const StyleDictionaryExtended = new StyleDictionary({}); -describe('register/transformGroup', () => { it('should error if name is not a string', () => { - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { - transforms: ['foo'] - }) - ).toThrow('transform name must be a string'); + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ + transforms: [dummyTransformName], + }); + }).to.throw('transform name must be a string'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: 1, - transforms: ['foo'] - }) - ).toThrow('transform name must be a string'); + transforms: [dummyTransformName], + }); + }).to.throw('transform name must be a string'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: [], - transforms: ['foo'] - }) - ).toThrow('transform name must be a string'); + transforms: [dummyTransformName], + }); + }).to.throw('transform name must be a string'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: {}, - transforms: ['foo'] - }) - ).toThrow('transform name must be a string'); + transforms: [dummyTransformName], + }); + }).to.throw('transform name must be a string'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { - name: function() {}, - transforms: ['foo'] - }) - ).toThrow('transform name must be a string'); + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ + name: function () {}, + transforms: [dummyTransformName], + }); + }).to.throw('transform name must be a string'); }); - it('should error if transforms isnt an array', () => { - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { - name: 'foo' - }) - ).toThrow('transforms must be an array of registered value transforms'); + it("should error if transforms isn't an array", () => { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ + name: 'foo', + }); + }).to.throw('transforms must be an array of registered value transforms'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: 'foo', - transforms: 'foo' - }) - ).toThrow('transforms must be an array of registered value transforms'); + transforms: dummyTransformName, + }); + }).to.throw('transforms must be an array of registered value transforms'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: 'foo', - transforms: {} - }) - ).toThrow('transforms must be an array of registered value transforms'); + transforms: {}, + }); + }).to.throw('transforms must be an array of registered value transforms'); - expect( - StyleDictionaryExtended.registerTransformGroup.bind(null, { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: 'foo', - transforms: function() {} - }) - ).toThrow('transforms must be an array of registered value transforms'); + transforms: function () {}, + }); + }).to.throw('transforms must be an array of registered value transforms'); }); it('should error if transforms arent registered', () => { - expect( - StyleDictionaryExtended.registerTransformGroup.bind(StyleDictionary, - { + expect(() => { + StyleDictionaryExtended.registerTransformGroup({ name: 'foo', - transforms: ['foo'] - }) - ).toThrow('transforms must be an array of registered value transforms'); + transforms: [dummyTransformName], + }); + }).to.throw('transforms must be an array of registered value transforms'); }); it('should work if everything is good', () => { StyleDictionaryExtended.registerTransformGroup({ name: 'foo', - transforms: ['size/px'] + transforms: ['size/px'], }); - expect(Array.isArray(StyleDictionaryExtended.transformGroup.foo)).toBeTruthy(); - expect(typeof StyleDictionaryExtended.transformGroup.foo[0]).toBe('string'); - expect(StyleDictionaryExtended.transformGroup.foo[0]).toBe('size/px'); + expect(Array.isArray(StyleDictionaryExtended.hooks.transformGroups.foo)).to.be.true; + expect(typeof StyleDictionaryExtended.hooks.transformGroups.foo[0]).to.equal('string'); + expect(StyleDictionaryExtended.hooks.transformGroups.foo[0]).to.equal('size/px'); }); - it('should properly pass the registered format to instances', () => { - var SDE2 = StyleDictionaryExtended.extend({}); - expect(Array.isArray(SDE2.transformGroup.foo)).toBeTruthy(); - expect(typeof SDE2.transformGroup.foo[0]).toBe('string'); - expect(SDE2.transformGroup.foo[0]).toBe('size/px'); + it('should properly pass the registered transformGroup to instances when extending', async () => { + const StyleDictionaryBase = new StyleDictionary({}); + StyleDictionaryBase.registerTransformGroup({ + name: 'bar', + transforms: ['size/px'], + }); + const SDE2 = await StyleDictionaryBase.extend({}); + expect(Array.isArray(SDE2.hooks.transformGroups.bar)).to.be.true; + expect(typeof SDE2.hooks.transformGroups.bar[0]).to.equal('string'); + expect(SDE2.hooks.transformGroups.bar[0]).to.equal('size/px'); }); }); diff --git a/__tests__/transform/config.test.js b/__tests__/transform/config.test.js index b3845d56d..96172582b 100644 --- a/__tests__/transform/config.test.js +++ b/__tests__/transform/config.test.js @@ -10,28 +10,32 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var transformConfig = require('../../lib/transform/config'); +import { expect } from 'chai'; +import { restore, stubMethod } from 'hanbi'; +import transformConfig from '../../dist/esm/transform/config.mjs'; +import chalk from 'chalk'; const dictionary = { - transformGroup: { - fooTransformGroup: ['barTransform'] + hooks: { + transforms: { + fooTransform: { + type: 'attribute', + transform: function () { + return { bar: 'foo' }; + }, + }, + }, + transformGroups: { + fooTransformGroup: ['barTransform'], + }, }, - transform: { - fooTransform: { - type: 'attribute', - transformer: function() { - return {bar: 'foo'} - } - } - } }; describe('transform', () => { describe('config', () => { it('Emits error when called with a transformGroup that does not exist in the dictionary', () => { const noTransformGroupCfg = { - transformGroup: 'barTransformGroup' + transformGroup: 'barTransformGroup', }; let err = ` @@ -39,14 +43,12 @@ Unknown transformGroup "barTransformGroup" found in platform "test": "barTransformGroup" does not match the name of a registered transformGroup. `; - expect( - transformConfig.bind(null, noTransformGroupCfg, dictionary, 'test') - ).toThrow(err); + expect(transformConfig.bind(null, noTransformGroupCfg, dictionary, 'test')).to.throw(err); }); it('Emits errors when called with a transform that does not exist', () => { const noTransformCfg = { - transforms: ['fooTransform', 'barTransform', 'bazTransform'] + transforms: ['fooTransform', 'barTransform', 'bazTransform'], }; let err = ` @@ -54,9 +56,109 @@ Unknown transforms "barTransform", "bazTransform" found in platform "test": None of "barTransform", "bazTransform" match the name of a registered transform. `; - expect( - transformConfig.bind(null, noTransformCfg, dictionary, 'test') - ).toThrow(err); + expect(transformConfig.bind(null, noTransformCfg, dictionary, 'test')).to.throw(err); + }); + + it('allows combining transformGroup with transforms', () => { + const cfg = { + hooks: { + transforms: { + fooTransform: { + name: 'fooTransform', + type: 'attribute', + transform: function () { + return { foo: 'foo' }; + }, + }, + barTransform: { + name: 'barTransform', + type: 'attribute', + transform: function () { + return { bar: 'bar' }; + }, + }, + quxTransform: { + name: 'quxTransform', + type: 'attribute', + transform: function () { + return { qux: 'qux' }; + }, + }, + }, + transformGroups: { + foobarTransformGroup: ['fooTransform', 'barTransform'], + }, + }, + }; + + const platformCfg = { + transformGroup: 'foobarTransformGroup', + transforms: ['quxTransform'], + }; + const transformedCfg = transformConfig(platformCfg, cfg, 'test'); + expect(transformedCfg.transforms.map((t) => t.name)).to.eql([ + 'fooTransform', + 'barTransform', + 'quxTransform', + ]); + }); + + it('warns the user if an action is used without a clean function', () => { + const cfg = { + hooks: { + actions: { + foo: {}, + }, + }, + }; + const platformCfg = { + actions: ['foo'], + }; + + const logStub = stubMethod(console, 'log'); + transformConfig(platformCfg, cfg, 'test'); + restore(); + expect(logStub.callCount).to.equal(1); + expect(Array.from(logStub.calls)[0].args[0]).to.equal( + chalk.rgb(255, 140, 0).bold('foo action does not have a clean function!'), + ); + }); + + it('throws if an action is used without a clean function with log.warnings set to error', () => { + const cfg = { + log: { warnings: 'error' }, + hooks: { + actions: { + foo: {}, + }, + }, + }; + const platformCfg = { + actions: ['foo'], + }; + + expect(() => transformConfig(platformCfg, cfg, 'test')).to.throw( + 'foo action does not have a clean function!', + ); + }); + + it('does not warn user at all when log.verbosity silent is used', () => { + const cfg = { + log: { verbosity: 'silent' }, + hooks: { + actions: { + foo: {}, + }, + }, + }; + const platformCfg = { + actions: ['foo'], + }; + + const logStub = stubMethod(console, 'log'); + transformConfig(platformCfg, cfg, 'test'); + restore(); + expect(logStub.callCount).to.equal(0); }); }); }); diff --git a/__tests__/transform/object.test.js b/__tests__/transform/object.test.js index 8618cd429..26b5ad4be 100644 --- a/__tests__/transform/object.test.js +++ b/__tests__/transform/object.test.js @@ -10,114 +10,120 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import transformObject from '../../dist/esm/transform/object.mjs'; -var transformObject = require('../../lib/transform/object'); - -const options = { +const config = { transforms: [ { type: 'attribute', - transformer: function() { - return {foo: 'bar'} - } - }, { + transform: function () { + return { foo: 'bar' }; + }, + }, + { type: 'attribute', - transformer: function() { - return {bar: 'foo'} - } - }, { + // verify async transforms to also work properly + transform: async function () { + await new Promise((resolve) => setTimeout(resolve, 100)); + return { bar: 'foo' }; + }, + }, + { type: 'name', - matcher: function(prop) { - return prop.attributes.foo === 'bar'; + filter: function (token) { + return token.attributes.foo === 'bar'; + }, + // verify async transforms to also work properly + transform: async function () { + await new Promise((resolve) => setTimeout(resolve, 100)); + return 'transform result'; }, - transformer: function() { - return "transformer result"; - } - }, { + }, + { type: 'value', - matcher: function(prop) { - return prop.path[0] === 'spacing'; + filter: function (token) { + return token.path[0] === 'spacing'; }, - transformer: function(val) { + transform: function (val) { return val + 'px'; - } - } - ] + }, + }, + ], }; describe('transform', () => { describe('object', () => { - it('does not crash when called without parameters', () => { - expect(transformObject()).toEqual({}); - }) + it('does not crash when called without parameters', async () => { + expect(await transformObject()).to.eql({}); + }); - it('returns expected result when called with an object without value property', () => { + it('returns expected result when called with an object without value property', async () => { const objectToTransform = { - "color": "#FFFF00" + color: '#FFFF00', }; const expected = { - "color": "#FFFF00" + color: '#FFFF00', }; - const actual = transformObject(objectToTransform, options); - expect(actual).toEqual(expected); - }) + const actual = await transformObject(objectToTransform, config, {}); + expect(actual).to.eql(expected); + }); - it('returns expected result when called with an with value leaf', () => { + it('returns expected result when called with value leaf', async () => { const objectToTransform = { - "font": { - "base": { - "value": "16", - "comment": "the base size of the font" - } - } + font: { + base: { + value: '16', + comment: 'the base size of the font', + }, + }, }; const expected = { - "font": { - "base": { - "attributes": {"bar": "foo", "foo": "bar"}, - "comment": "the base size of the font", - "name": "transformer result", - "original": - { - "comment": "the base size of the font", - "value": "16" + font: { + base: { + attributes: { bar: 'foo', foo: 'bar' }, + comment: 'the base size of the font', + name: 'transform result', + original: { + comment: 'the base size of the font', + value: '16', }, - "path": ["font", "base"], - "value": "16" - } - } + path: ['font', 'base'], + value: '16', + }, + }, }; - const actual = transformObject(objectToTransform, options); - expect(actual).toEqual(expected); + const actual = await transformObject(objectToTransform, config, {}); + expect(actual).to.eql(expected); }); - it('fills the transformationContext with transformed and deferred transforms', () => { + it('fills the transformationContext with transformed and deferred transforms', async () => { const transformedPropRefs = []; const deferredPropValueTransforms = []; const transformationContext = { transformedPropRefs, - deferredPropValueTransforms + deferredPropValueTransforms, }; const objectToTransform = { - "spacing": { - "base": { - "value": "16" + spacing: { + base: { + value: '16', + }, + medium: { + value: '{spacing.base.value}', }, - "medium": { - "value": "{spacing.base.value}" - } - } + }, }; - transformObject(objectToTransform, options, transformationContext); + await transformObject(objectToTransform, config, {}, transformationContext); - expect(transformedPropRefs).toEqual(['spacing.base']); - expect(deferredPropValueTransforms).toEqual(['spacing.medium']); - }) + expect(transformedPropRefs).to.eql(['spacing.base']); + expect(deferredPropValueTransforms).to.eql(['spacing.medium']); + }); }); }); diff --git a/__tests__/transform/property.test.js b/__tests__/transform/property.test.js deleted file mode 100644 index 7b3009f49..000000000 --- a/__tests__/transform/property.test.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var property = require('../../lib/transform/property'); - -var options = { - transforms: [ - { - type: 'attribute', - transformer: function() { - return { - foo: 'bar' - } - } - },{ - type: 'attribute', - transformer: function() { - return {bar: 'foo'} - } - },{ - type: 'name', - matcher: function(prop) { return prop.attributes.foo === 'bar'; }, - transformer: function() { return "hello"; } - } - ] -}; - -describe('transform', () => { - describe('property', () => { - - it('should work', () => { - var test = property({attributes:{baz:'blah'}}, options); - expect(test).toHaveProperty('attributes.bar', 'foo'); - expect(test).toHaveProperty('name', 'hello'); - }); - - // Add more tests - }); -}); diff --git a/__tests__/transform/propertySetup.test.js b/__tests__/transform/propertySetup.test.js deleted file mode 100644 index 837af06b0..000000000 --- a/__tests__/transform/propertySetup.test.js +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -var propertySetup = require('../../lib/transform/propertySetup'); - -describe('transform', () => { - describe('propertySetup', () => { - - it('should error if property is not an object', () => { - expect( - propertySetup.bind(null, null, 'foo', []) - ).toThrow('Property object must be an object'); - }); - - it('should error if name in not a string', () => { - expect( - propertySetup.bind(null, {}, null, []) - ).toThrow('Name must be a string'); - }); - - it('should error path is not an array', () => { - expect( - propertySetup.bind(null, {}, 'name', null) - ).toThrow('Path must be an array'); - }); - - - it('should work if all the args are proper', () => { - var test = propertySetup( - {value: "#fff"}, - "white", - ["color","base"] - ); - expect(typeof test).toBe('object'); - expect(test).toHaveProperty('value'); - expect(test).toHaveProperty('original'); - expect(test).toHaveProperty('attributes'); - expect(test).toHaveProperty('path'); - }); - - - it('should not do anything and return the property if it has been setup previously', () => { - var original = {value: "#fff", original:{}}; - var test = propertySetup( - original, - "white", - ["color","base"] - ); - expect(test).toMatchObject(original); - }); - - it('should use attributes if already set', () => { - var attributes = {"foo":"bar"}; - var test = propertySetup( - {value:"#fff", attributes:attributes}, - "white", - ["color","base"] - ); - expect(test.attributes).toMatchObject(attributes); - }); - - it('should use the name on the property if set', () => { - var name = "name"; - var test = propertySetup( - {value:"#fff", name:name}, - 'white', - ["color","base"] - ); - expect(test).toHaveProperty('name', name); - }); - - it('should use the name passed in if not set on the property', () => { - var test = propertySetup( - {value:"#fff"}, - 'white', - ["color","base"] - ); - expect(test).toHaveProperty('name', 'white'); - }); - - it('should handle objects', () => { - const test = propertySetup({ - value: { - h: 20, s: 50, l: 50 - } - }, 'red', ['color','red']); - expect(test).toHaveProperty('value.h', 20); - expect(test).toHaveProperty('original.value.h', 20); - }) - - }); -}); diff --git a/__tests__/transform/tokenSetup.test.js b/__tests__/transform/tokenSetup.test.js new file mode 100644 index 000000000..99133079e --- /dev/null +++ b/__tests__/transform/tokenSetup.test.js @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import tokenSetup from '../../dist/esm/transform/tokenSetup.mjs'; + +describe('transform', () => { + describe('tokenSetup', () => { + it('should error if property is not an object', () => { + expect(tokenSetup.bind(null, null, 'foo', [])).to.throw( + 'Token object must be of type "object"', + ); + }); + + it('should error if name in not a string', () => { + expect(tokenSetup.bind(null, {}, null, [])).to.throw('Token name must be a string'); + }); + + it('should error path is not an array', () => { + expect(tokenSetup.bind(null, {}, 'name', null)).to.throw('Token path must be an array'); + }); + + it('should work if all the args are proper', () => { + const test = tokenSetup({ value: '#fff' }, 'white', ['color', 'base']); + expect(typeof test).to.equal('object'); + expect(test).to.have.property('value'); + expect(test).to.have.property('original'); + expect(test).to.have.property('attributes'); + expect(test).to.have.property('path'); + }); + + it('should not do anything and return the property if it has been setup previously', () => { + const original = { value: '#fff', original: {} }; + const test = tokenSetup(original, 'white', ['color', 'base']); + expect(test).to.eql(original); + }); + + it('should use attributes if already set', () => { + const attributes = { foo: 'bar' }; + const test = tokenSetup({ value: '#fff', attributes: attributes }, 'white', [ + 'color', + 'base', + ]); + expect(test.attributes).to.eql(attributes); + }); + + it('should use the name on the property if set', () => { + const name = 'name'; + const test = tokenSetup({ value: '#fff', name: name }, 'white', ['color', 'base']); + expect(test).to.have.property('name', name); + }); + + it('should use the name passed in if not set on the property', () => { + const test = tokenSetup({ value: '#fff' }, 'white', ['color', 'base']); + expect(test).to.have.property('name', 'white'); + }); + + it('should handle objects', () => { + const test = tokenSetup( + { + value: { + h: 20, + s: 50, + l: 50, + }, + }, + 'red', + ['color', 'red'], + ); + expect(test).to.have.nested.property('value.h', 20); + expect(test).to.have.nested.property('original.value.h', 20); + }); + }); +}); diff --git a/__tests__/transform/transformToken.test.js b/__tests__/transform/transformToken.test.js new file mode 100644 index 000000000..5a00dd41d --- /dev/null +++ b/__tests__/transform/transformToken.test.js @@ -0,0 +1,80 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import transformToken from '../../dist/esm/transform/token.mjs'; + +const config = { + transforms: [ + { + type: 'attribute', + transform: function () { + return { + foo: 'bar', + }; + }, + }, + { + type: 'attribute', + transform: function () { + return { bar: 'foo' }; + }, + }, + { + type: 'name', + filter: function (prop) { + return prop.attributes.foo === 'bar'; + }, + transform: function () { + return 'hello'; + }, + }, + ], +}; + +describe('transform', () => { + describe('token', () => { + it('transform token and apply transforms', async () => { + const test = await transformToken({ attributes: { baz: 'blah' } }, config, {}); + expect(test).to.have.nested.property('attributes.bar', 'foo'); + expect(test).to.have.property('name', 'hello'); + }); + + // This allows transformObject utility to then consider this token's transformation undefined and thus "deferred" + it('returns a token as undefined if transitive transform dictates that the transformation has to be deferred', async () => { + const result = await transformToken( + { + value: '16', + original: { + value: '16', + }, + }, + { + transforms: [ + { + type: 'value', + transitive: true, + transform: () => { + return undefined; + }, + }, + ], + }, + {}, + ); + + expect(result).to.be.undefined; + }); + + // Add more tests + }); +}); diff --git a/__tests__/utils/combineJSON.test.js b/__tests__/utils/combineJSON.test.js index 69fdee9c5..8091965cb 100644 --- a/__tests__/utils/combineJSON.test.js +++ b/__tests__/utils/combineJSON.test.js @@ -10,104 +10,153 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var combineJSON = require('../../lib/utils/combineJSON'); -var path = require('path'); -var yaml = require('yaml'); +import { expect } from 'chai'; +import { join } from 'path-unified'; +import yaml from 'yaml'; +import { expectThrowsAsync } from '../__helpers.js'; +import { combineJSON } from 'style-dictionary/utils'; describe('utils', () => { describe('combineJSON', () => { - - it('should return an object', () => { - var test = combineJSON(["__tests__/__json_files/*.json"]); - expect(typeof test).toBe('object') + it('should return an object with usesDtcg & tokens prop', async () => { + const test = await combineJSON(['__tests__/__json_files/*.json']); + expect(typeof test).to.equal('object'); + const { tokens, usesDtcg } = test; + expect(typeof tokens).to.equal('object'); + expect(typeof usesDtcg).to.equal('boolean'); }); - it('should handle wildcards', () => { - var test = combineJSON(["__tests__/__json_files/*.json"]); - expect(typeof test).toBe('object') + it('should handle wildcards', async () => { + const test = await combineJSON(['__tests__/__json_files/*.json']); + expect(typeof test).to.equal('object'); + const { tokens, usesDtcg } = test; + expect(typeof tokens).to.equal('object'); + expect(typeof usesDtcg).to.equal('boolean'); }); - it('should handle js modules that export objects', () => { - var absPath = path.join(process.cwd(), 'test', 'json_files', '*.js'); - var relativePath = '__tests__/__json_files/*.js'; - var test = combineJSON([absPath, relativePath]); - expect(typeof test).toBe('object') + it('should handle js modules that export objects', async () => { + const absPath = join('__tests__', '__json_files', '*.js'); + const relativePath = '__tests__/__json_files/*.js'; + const test = await combineJSON([absPath, relativePath]); + expect(typeof test).to.equal('object'); + const { tokens, usesDtcg } = test; + expect(typeof tokens).to.equal('object'); + expect(typeof usesDtcg).to.equal('boolean'); }); - it('should do a deep merge', () => { - var test = combineJSON(["__tests__/__json_files/shallow/*.json"], true); - expect(test).toHaveProperty('a', 2); - expect(test.b).toMatchObject({"a":1, "c":2}) - expect(test).toHaveProperty('d.e.f.g', 1); - expect(test).toHaveProperty('d.e.f.h', 2); + it('should do a deep merge', async () => { + const { tokens } = await combineJSON(['__tests__/__json_files/shallow/*.json'], true); + expect(tokens).to.have.property('a', 2); + expect(tokens.b).to.eql({ a: 1, c: 2 }); + expect(tokens).to.have.nested.property('d.e.f.g', 1); + expect(tokens).to.have.nested.property('d.e.f.h', 2); }); - it('should do a shallow merge', () => { - var test = combineJSON(["__tests__/__json_files/shallow/*.json"]); - expect(test).toHaveProperty('a', 2); - expect(test.b).toMatchObject({"c":2}); - expect(test).toHaveProperty('c', [3,4]); - expect(test).not.toHaveProperty('d.e.f.g'); - expect(test).toHaveProperty('d.e.f.h', 2); + it('should do a shallow merge', async () => { + const { tokens } = await combineJSON(['__tests__/__json_files/shallow/*.json']); + expect(tokens).to.have.property('a', 2); + expect(tokens.b).to.eql({ c: 2 }); + expect(tokens).to.have.deep.property('c', [3, 4]); + expect(tokens).not.to.have.nested.property('d.e.f.g'); + expect(tokens).to.have.nested.property('d.e.f.h', 2); }); - it('should fail on invalid JSON', () => { - expect( - combineJSON.bind(null, ["__tests__/__json_files/broken/*.json"], true) - ).toThrow(/Failed to load or parse/); + it('should fail on invalid JSON', async () => { + await expectThrowsAsync( + () => combineJSON(['__tests__/__json_files/broken/*.json']), + "Failed to load or parse JSON or JS Object: JSON5: invalid character '!' at 2:18", + ); }); - it('should fail if there is a collision and it is passed a collision function', () => { - expect( - combineJSON.bind(null, ["__tests__/__json_files/shallow/*.json"], true, function Collision(opts) { - expect(opts).toHaveProperty('key', 'a'); - expect(opts.target[opts.key]).toBe(1); - expect(opts.copy[opts.key]).toBe(2); - throw new Error('test'); - }, true) - ).toThrow(/test/); + it('should fail if there is a collision and it is passed a collision function', async () => { + await expectThrowsAsync( + () => + combineJSON(['__tests__/__json_files/shallow/*.json'], true, function Collision(opts) { + expect(opts).to.have.property('key', 'a'); + expect(opts.target[opts.key]).to.equal(1); + expect(opts.copy[opts.key]).to.equal(2); + throw new Error('test'); + }), + 'test', + ); }); - it('should support json5', () => { - var test = combineJSON(["__tests__/__json_files/shallow/*.json5"]); - expect(test).toHaveProperty('json5A', 5); - expect(test.d).toHaveProperty('json5e', 1); + it('should support json5', async () => { + const { tokens } = await combineJSON(['__tests__/__json_files/shallow/*.json5']); + expect(tokens).to.have.property('json5A', 5); + expect(tokens.d).to.have.property('json5e', 1); }); - it('should support jsonc', () => { - var test = combineJSON(["__tests__/__json_files/shallow/*.jsonc"]); - expect(test).toHaveProperty('jsonCA', 5); - expect(test.d).toHaveProperty('jsonCe', 1); + it('should support jsonc', async () => { + const { tokens } = await combineJSON(['__tests__/__json_files/shallow/*.jsonc']); + expect(tokens).to.have.property('jsonCA', 5); + expect(tokens.d).to.have.property('jsonCe', 1); }); describe('custom parsers', () => { - it('should support yaml.parse', () => { - const parsers = [{ - pattern: /\.yaml$/, - // yaml.parse function matches the intended function signature - parse: ({contents}) => yaml.parse(contents) - }]; - const output = combineJSON([`__tests__/__json_files/yaml.yaml`], false, null, false, parsers); - expect(output).toHaveProperty('foo', 'bar'); - expect(output).toHaveProperty('bar', '{foo}'); + it('should support yaml.parse', async () => { + const parsers = { + 'yaml-parser': { + pattern: /\.yaml$/, + // yaml.parse function matches the intended function signature + parser: ({ contents }) => yaml.parse(contents), + }, + }; + const { tokens } = await combineJSON( + [`__tests__/__json_files/yaml.yaml`], + false, + null, + false, + parsers, + ); + expect(tokens).to.have.property('foo', 'bar'); + expect(tokens).to.have.property('bar', '{foo}'); }); - it('should multiple parsers on the same file', () => { + it('should multiple parsers on the same file', async () => { const testOutput = { test: 'test' }; - const parsers = [{ - pattern: /.json$/, - parse: () => { - return { test: 'foo' } - } - },{ - pattern: /.json$/, - parse: () => { - return testOutput - } - }]; - const output = combineJSON([`__tests__/__json_files/simple.json`], false, null, false, parsers); - expect(output).toHaveProperty('test', 'test'); + const parsers = { + 'json-foo': { + pattern: /.json$/, + parser: () => { + return { test: 'foo' }; + }, + }, + 'json-return': { + pattern: /.json$/, + parser: () => { + return testOutput; + }, + }, + }; + const { tokens } = await combineJSON( + [`__tests__/__json_files/simple.json`], + false, + null, + false, + parsers, + ); + expect(tokens).to.have.property('test', 'test'); + }); + + it('should support asynchronous parsers', async () => { + const parsers = { + 'json-test': { + pattern: /.json$/, + parser: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + return { test: 'foo' }; + }, + }, + }; + const { tokens } = await combineJSON( + [`__tests__/__json_files/simple.json`], + false, + null, + false, + parsers, + ); + expect(tokens).to.have.property('test', 'foo'); }); }); }); diff --git a/__tests__/utils/convertToBase64.test.js b/__tests__/utils/convertToBase64.test.js index c79005f64..e0981840e 100644 --- a/__tests__/utils/convertToBase64.test.js +++ b/__tests__/utils/convertToBase64.test.js @@ -10,36 +10,39 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var convertToBase64 = require('../../lib/utils/convertToBase64.js'); +import { expect } from 'chai'; +import convertToBase64 from '../../dist/esm/utils/convertToBase64.mjs'; describe('utils', () => { describe('convertToBase64', () => { it('should error if filePath isnt a string', () => { - expect( - convertToBase64.bind(null) - ).toThrow('filePath name must be a string'); - expect( - convertToBase64.bind(null, []) - ).toThrow('filePath name must be a string'); - expect( - convertToBase64.bind(null, {}) - ).toThrow('filePath name must be a string'); + expect(convertToBase64.bind(null)).to.throw('filePath name must be a string'); + expect(convertToBase64.bind(null, [])).to.throw('filePath name must be a string'); + expect(convertToBase64.bind(null, {})).to.throw('filePath name must be a string'); }); it('should error if filePath isnt a file', () => { - expect( - convertToBase64.bind(null, 'foo') - ).toThrow("ENOENT: no such file or directory, open 'foo'"); + let errMessage; + try { + convertToBase64('foo'); + } catch (e) { + errMessage = e.message; + } + // Note: on windows fs.readFileSync ENOENT error puts the full path in the error + // on linux only the name of the filepath "foo" + expect(errMessage).to.satisfy((msg) => + msg.startsWith('ENOENT: no such file or directory, open'), + ); }); it('should return a string', () => { - expect(typeof convertToBase64('__tests__/__configs/test.json')).toBe('string'); + expect(typeof convertToBase64('__tests__/__configs/test.json')).to.equal('string'); }); it('should be a valid base64 string', () => { - expect(convertToBase64('__tests__/__json_files/simple.json')) - .toEqual('ewogICJmb28iOiAiYmFyIiwKICAiYmFyIjogIntmb299Igp9'); + expect(convertToBase64('__tests__/__json_files/simple.json')).to.equal( + 'ewogICJmb28iOiAiYmFyIiwKICAiYmFyIjogIntmb299Igp9', + ); }); }); }); diff --git a/__tests__/utils/convertToDTCG.test.js b/__tests__/utils/convertToDTCG.test.js new file mode 100644 index 000000000..12f4fdde0 --- /dev/null +++ b/__tests__/utils/convertToDTCG.test.js @@ -0,0 +1,521 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { fs } from 'style-dictionary/fs'; +import { hasInitialized } from '../__setup.js'; +import { + convertToDTCG, + convertJSONToDTCG, + convertZIPToDTCG, + readZIP, +} from '../../dist/esm/utils/convertToDTCG.mjs'; + +const paddingsOutput = { + $type: 'dimension', + size: { + padding: { + zero: { + $value: 0, + }, + tiny: { + $value: '3', + }, + small: { + $value: '5', + }, + base: { + $value: '10', + }, + large: { + $value: '15', + }, + xl: { + $value: '20', + }, + xxl: { + $value: '30', + }, + }, + }, +}; + +const fontSizesOutput = { + $type: 'fontSize', + size: { + font: { + tiny: { + $value: '11px', + }, + small: { + $value: '13px', + }, + medium: { + $value: '15px', + }, + large: { + $value: '17px', + }, + xl: { + $value: '21px', + }, + xxl: { + $value: '25px', + }, + xxxl: { + $value: '30px', + }, + base: { + $value: '{size.font.medium}', + }, + }, + }, +}; + +describe('utils', () => { + describe('convertToDTCG', () => { + it('should swap value, type and description to use $ property prefix', () => { + const result = convertToDTCG( + { + colors: { + red: { + value: '#ff0000', + type: 'color', + description: 'A red color', + }, + green: { + value: '#00ff00', + type: 'color', + description: 'A green color', + }, + blue: { + value: '#0000ff', + type: 'color', + description: 'A blue color', + }, + }, + }, + { applyTypesToGroup: false }, + ); + expect(result).to.eql({ + colors: { + red: { + $value: '#ff0000', + $type: 'color', + $description: 'A red color', + }, + green: { + $value: '#00ff00', + $type: 'color', + $description: 'A green color', + }, + blue: { + $value: '#0000ff', + $type: 'color', + $description: 'A blue color', + }, + }, + }); + }); + + it('should apply type to the upper most common ancestor', () => { + const result = convertToDTCG({ + colors: { + red: { + value: '#ff0000', + type: 'color', + }, + green: { + value: '#00ff00', + type: 'color', + }, + blue: { + value: '#0000ff', + type: 'color', + }, + }, + dimensions: { + sm: { + value: '2px', + type: 'dimension', + }, + md: { + value: '8px', + type: 'dimension', + }, + lg: { + value: '16px', + type: 'dimension', + }, + }, + }); + expect(result).to.eql({ + colors: { + $type: 'color', + red: { + $value: '#ff0000', + }, + green: { + $value: '#00ff00', + }, + blue: { + $value: '#0000ff', + }, + }, + dimensions: { + $type: 'dimension', + sm: { + $value: '2px', + }, + md: { + $value: '8px', + }, + lg: { + $value: '16px', + }, + }, + }); + }); + + it('should keep types as is when not shared with all siblings', () => { + const result = convertToDTCG({ + colors: { + red: { + value: '#ff0000', + type: 'color', + }, + green: { + value: '#00ff00', + type: 'color', + }, + blue: { + value: '#0000ff', + type: 'different-type', + }, + }, + dimensions: { + sm: { + value: '2px', + type: 'dimension', + }, + md: { + value: '8px', + type: 'dimension', + }, + lg: { + value: '16px', + type: 'dimension', + }, + }, + }); + expect(result).to.eql({ + colors: { + red: { + $value: '#ff0000', + $type: 'color', + }, + green: { + $value: '#00ff00', + $type: 'color', + }, + blue: { + $value: '#0000ff', + $type: 'different-type', + }, + }, + dimensions: { + $type: 'dimension', + sm: { + $value: '2px', + }, + md: { + $value: '8px', + }, + lg: { + $value: '16px', + }, + }, + }); + }); + + it('should work with any number of nestings', () => { + const result = convertToDTCG({ + colors: { + red: { + value: '#ff0000', + type: 'color', + }, + grey: { + 100: { + value: '#aaaaaa', + type: 'color', + }, + 200: { + deeper: { + value: '#cccccc', + type: 'color', + }, + }, + 400: { + value: '#dddddd', + type: 'color', + }, + 500: { + foo: { + bar: { + qux: { + value: '#eeeeee', + type: 'color', + }, + }, + }, + }, + }, + green: { + value: '#00ff00', + type: 'color', + }, + blue: { + value: '#0000ff', + type: 'color', + }, + }, + }); + expect(result).to.eql({ + $type: 'color', + colors: { + red: { + $value: '#ff0000', + }, + grey: { + 100: { + $value: '#aaaaaa', + }, + 200: { + deeper: { + $value: '#cccccc', + }, + }, + 400: { + $value: '#dddddd', + }, + 500: { + foo: { + bar: { + qux: { + $value: '#eeeeee', + }, + }, + }, + }, + }, + green: { + $value: '#00ff00', + }, + blue: { + $value: '#0000ff', + }, + }, + }); + }); + + it('should handle scenarios where not all types are the same', () => { + const result = convertToDTCG({ + colors: { + red: { + value: '#ff0000', + type: 'color', + }, + grey: { + 100: { + value: '#aaaaaa', + type: 'color', + }, + 200: { + deeper: { + value: '#cccccc', + type: 'color', + }, + }, + 400: { + value: '#dddddd', + type: 'color', + }, + 500: { + foo: { + bar: { + qux: { + value: '#eeeeee', + type: 'different-type', + }, + }, + }, + }, + }, + green: { + value: '#00ff00', + type: 'color', + }, + blue: { + value: '#0000ff', + type: 'color', + }, + }, + }); + expect(result).to.eql({ + colors: { + red: { + $value: '#ff0000', + $type: 'color', + }, + grey: { + 100: { + $value: '#aaaaaa', + $type: 'color', + }, + 200: { + $type: 'color', + deeper: { + $value: '#cccccc', + }, + }, + 400: { + $value: '#dddddd', + $type: 'color', + }, + 500: { + $type: 'different-type', + foo: { + bar: { + qux: { + $value: '#eeeeee', + }, + }, + }, + }, + }, + green: { + $value: '#00ff00', + $type: 'color', + }, + blue: { + $value: '#0000ff', + $type: 'color', + }, + }, + }); + }); + + it('should keep input property key order intact', () => { + const input = { + red: { + type: 'color', + value: '#ff0000', + }, + }; + + const inputKeys = Object.keys(input.red); + const convertedKeys = Object.keys(convertToDTCG(input, { applyTypesToGroup: false }).red); + expect(inputKeys.every((prop, index) => convertedKeys[index] === `$${prop}`)).to.be.true; + }); + + it('should order $type on group as first property', () => { + const input = { + colors: { + red: { + value: '#ff0000', + type: 'color', + }, + green: { + value: '#00ff00', + type: 'color', + }, + blue: { + value: '#0000ff', + type: 'color', + }, + }, + dimensions: { + sm: { + value: '2px', + type: 'dimension', + }, + md: { + value: '8px', + type: 'dimension', + }, + lg: { + value: '16px', + type: 'dimension', + }, + }, + }; + const output = convertToDTCG(input); + const colorsKeys = Object.keys(output.colors); + const dimensionsKeys = Object.keys(output.dimensions); + expect(colorsKeys[0]).to.equal('$type'); + expect(dimensionsKeys[0]).to.equal('$type'); + }); + }); + + describe('convertJSONToDTCG', async () => { + const buf = await fs.promises.readFile('__tests__/__tokens/paddings.json'); + const jsonBlob = new Blob([buf], { type: 'application/json' }); + + it('should allow passing a JSON blob, and converting it to DTCG JSON blob', async () => { + const outputFile = await convertJSONToDTCG(jsonBlob); + const output = JSON.parse(await outputFile.text()); + expect(output).to.eql(paddingsOutput); + }); + + it('should allow passing a JSON filepath, and converting it to DTCG JSON blob', async () => { + const outputFile = await convertJSONToDTCG('__tests__/__tokens/paddings.json'); + const output = JSON.parse(await outputFile.text()); + expect(output).to.eql(paddingsOutput); + }); + + it('should throw when file is not JSON', async () => { + // zip files mirrored to memfs for browser testing takes a while to initialize apparently... + await hasInitialized; + + const buf = await fs.promises.readFile('__tests__/__tokens/tokens.zip'); + const zipBlob = new Blob([buf], { type: 'application/zip' }); + await expect(convertJSONToDTCG(zipBlob)).to.eventually.rejectedWith( + 'File (Blob) is of type application/zip, but a json type blob was expected.', + ); + }); + }); + + describe('convertZIPToDTCG', async () => { + it('should allow passing a ZIP blob, and converting it to DTCG ZIP blob', async () => { + // zip files mirrored to memfs for browser testing takes a while to initialize apparently... + await hasInitialized; + + const buf = await fs.promises.readFile('__tests__/__tokens/tokens.zip'); + const zipBlob = new Blob([buf], { type: 'application/zip' }); + const outputZIP = await convertZIPToDTCG(zipBlob); + const zipObjectWithData = await readZIP(outputZIP); + expect(JSON.parse(zipObjectWithData['font_sizes.json'])).to.eql(fontSizesOutput); + expect(JSON.parse(zipObjectWithData['paddings.json'])).to.eql(paddingsOutput); + }); + + it('should allow passing a ZIP filepath, and converting it to DTCG ZIP blob', async () => { + // zip files mirrored to memfs for browser testing takes a while to initialize apparently... + await hasInitialized; + + const outputZIP = await convertZIPToDTCG('__tests__/__tokens/tokens.zip'); + const zipObjectWithData = await readZIP(outputZIP); + expect(JSON.parse(zipObjectWithData['font_sizes.json'])).to.eql(fontSizesOutput); + expect(JSON.parse(zipObjectWithData['paddings.json'])).to.eql(paddingsOutput); + }); + }); +}); diff --git a/__tests__/utils/deepExtend.test.js b/__tests__/utils/deepExtend.test.js index 16eb847d7..478228066 100644 --- a/__tests__/utils/deepExtend.test.js +++ b/__tests__/utils/deepExtend.test.js @@ -10,69 +10,99 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -var deepExtend = require('../../lib/utils/deepExtend'); +import { expect } from 'chai'; +import deepExtend from '../../dist/esm/utils/deepExtend.mjs'; describe('utils', () => { describe('deepExtend', () => { - it('should return an object', () => { - var test = deepExtend(); - expect(typeof test).toBe('object') + const test = deepExtend(); + expect(typeof test).to.equal('object'); }); - it('should override properties from right to left', () => { - var test = deepExtend([{foo:'bar'}, {foo:'baz'}]); - expect(test).toHaveProperty('foo', 'baz'); + it('should override tokens from right to left', () => { + const test = deepExtend([{ foo: 'bar' }, { foo: 'baz' }]); + expect(test).to.have.property('foo', 'baz'); - var test2 = deepExtend([{foo:'bar'}, {foo:'baz'}, {foo:'blah'}]); - expect(test2).toHaveProperty('foo', 'blah'); + const test2 = deepExtend([{ foo: 'bar' }, { foo: 'baz' }, { foo: 'blah' }]); + expect(test2).to.have.property('foo', 'blah'); }); - it('overrides nested properties', () => { - var test = deepExtend([{foo: {foo:'bar'}}, {foo: {foo:'baz'}}]); - expect(test).toHaveProperty('foo.foo', 'baz'); + it('overrides nested tokens', () => { + const test = deepExtend([{ foo: { foo: 'bar' } }, { foo: { foo: 'baz' } }]); + expect(test).to.have.nested.property('foo.foo', 'baz'); - var test2 = deepExtend([{foo:{foo:'bar'}}, {foo:{foo:'baz'}}, {foo:{foo:'blah'}}]); - expect(test2).toHaveProperty('foo.foo', 'blah'); + const test2 = deepExtend([ + { foo: { foo: 'bar' } }, + { foo: { foo: 'baz' } }, + { foo: { foo: 'blah' } }, + ]); + expect(test2).to.have.nested.property('foo.foo', 'blah'); }); - it('properly merges nested properties', () => { - var test = deepExtend([{foo: {bar:'bar'}}, {foo: {baz:'baz'}}]); - expect(test).toHaveProperty('foo.baz', 'baz'); - expect(test).toHaveProperty('foo.bar', 'bar'); + it('properly merges nested tokens', () => { + const test = deepExtend([{ foo: { bar: 'bar' } }, { foo: { baz: 'baz' } }]); + expect(test).to.have.nested.property('foo.baz', 'baz'); + expect(test).to.have.nested.property('foo.bar', 'bar'); + + const test2 = deepExtend([ + { foo: { bar: 'bar' } }, + { foo: { baz: 'baz' } }, + { foo: { blah: 'blah' } }, + ]); + expect(test2).to.have.nested.property('foo.baz', 'baz'); + expect(test2).to.have.nested.property('foo.bar', 'bar'); + expect(test2).to.have.nested.property('foo.blah', 'blah'); + }); - var test2 = deepExtend([{foo:{bar:'bar'}}, {foo:{baz:'baz'}}, {foo:{blah:'blah'}}]); - expect(test2).toHaveProperty('foo.baz', 'baz'); - expect(test2).toHaveProperty('foo.bar', 'bar'); - expect(test2).toHaveProperty('foo.blah', 'blah'); + it("shouldn't fail loudly if it is a normal deep extend", () => { + const test = deepExtend([{ foo: { bar: 'bar' } }, { foo: { baz: 'baz' } }], { + collision: function () {}, + }); + expect(test).to.have.nested.property('foo.baz', 'baz'); + expect(test).to.have.nested.property('foo.bar', 'bar'); }); - it('shouldn\'t fail loudly if it is a normal deep extend', () => { - var test = deepExtend([{foo: {bar:'bar'}}, {foo: {baz:'baz'}}], function() {}); - expect(test).toHaveProperty('foo.baz', 'baz'); - expect(test).toHaveProperty('foo.bar', 'bar'); + it("shouldn't merge when keys collide that should override rather than merge", () => { + const test = deepExtend( + [{ foo: { value: 'bar', metadata: 'meta' } }, { foo: { value: 'baz' } }], + { collision: function () {}, overrideKeys: ['value'] }, + ); + expect(test).to.have.nested.property('foo.value', 'baz'); + // we do not want to inherit this metadata from the prop we are overriding + expect(test).to.not.have.nested.property('foo.metadata'); + + const testDTCG = deepExtend( + [{ foo: { $value: 'bar', metadata: 'meta' } }, { foo: { $value: 'baz' } }], + { collision: function () {}, overrideKeys: ['$value'] }, + ); + + expect(testDTCG).to.have.nested.property('foo.$value', 'baz'); + expect(testDTCG).to.not.have.nested.property('foo.metadata'); }); describe('collision detection', () => { it('should call the collision function if a collision happens', () => { - expect( - deepExtend.bind(null, [{foo: {bar:'bar'}}, {foo: {bar:'baz'}}], function() { - throw new Error('danger danger. high voltage.'); - }) - ).toThrow('danger danger. high voltage.'); + expect(() => + deepExtend([{ foo: { bar: 'bar' } }, { foo: { bar: 'baz' } }], { + collision: function () { + throw new Error('danger danger. high voltage.'); + }, + }), + ).to.throw('danger danger. high voltage.'); }); it('the collision function should have the proper arguments', () => { - var test = deepExtend([{foo: {bar:'bar'}}, {foo: {bar:'baz'}}], function(opts) { - expect(opts).toHaveProperty('target.bar', 'bar'); - expect(opts).toHaveProperty('copy.bar', 'baz'); - expect(opts.path[0]).toBe('foo'); - expect(opts).toHaveProperty('key', 'bar'); + const test = deepExtend([{ foo: { bar: 'bar' } }, { foo: { bar: 'baz' } }], { + collision: function (opts) { + expect(opts).to.have.nested.property('target.bar', 'bar'); + expect(opts).to.have.nested.property('copy.bar', 'baz'); + expect(opts.path[0]).to.equal('foo'); + expect(opts).to.have.property('key', 'bar'); + }, }); - expect(test).toHaveProperty('foo.bar', 'baz'); + expect(test).to.have.nested.property('foo.bar', 'baz'); }); }); - }); }); diff --git a/__tests__/utils/expandObjectTokens.test.js b/__tests__/utils/expandObjectTokens.test.js new file mode 100644 index 000000000..4e4a4f5eb --- /dev/null +++ b/__tests__/utils/expandObjectTokens.test.js @@ -0,0 +1,568 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { + getTypeFromMap, + expandToken, + expandTokens, +} from '../../dist/esm/utils/expandObjectTokens.mjs'; + +const input = { + border: { + type: 'border', + value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + typography: { + type: 'typography', + value: { + fontWeight: '800', + fontSize: '16px', + fontFamily: 'Arial Black', + }, + }, +}; + +const borderOutput = { + color: { + type: 'color', + value: '#000', + }, + style: { + type: 'strokeStyle', + value: 'solid', + }, + width: { + type: 'dimension', + value: '2px', + }, +}; + +const typographyOutput = { + fontWeight: { + type: 'fontWeight', + value: '800', + }, + fontSize: { + type: 'dimension', + value: '16px', + }, + fontFamily: { + type: 'fontFamily', + value: 'Arial Black', + }, +}; + +describe('utils', () => { + describe('expandObjectTokens', () => { + describe('expandObjectTokens', () => { + describe('getTypeFromMap', () => { + it('should return the type input as output by default', () => { + const output = getTypeFromMap('width', 'foo', {}); + expect(output).to.equal('width'); + }); + + it('should return mapped type, when overriding the base DTCG map', () => { + const output = getTypeFromMap('width', 'border', { + border: { width: 'foo' }, + }); + expect(output).to.equal('foo'); + }); + + it('should return mapped type keyed by the composition type', () => { + const output = getTypeFromMap('width', 'foo', { + foo: { width: 'foo' }, + }); + expect(output).to.equal('foo'); + }); + + it('should prioritise the mapped type keyed by composition type when also available on the top-level', () => { + const output = getTypeFromMap('width', 'foo', { + foo: { width: 'foo' }, + width: 'bar', + }); + expect(output).to.equal('foo'); + }); + }); + + describe('expandToken', () => { + it('should expand a single object value token into multiple tokens', () => { + const expanded = expandToken(input.border, { expand: true, usesDtcg: false }); + expect(expanded).to.eql(borderOutput); + }); + + it('should adjust the path properties of the newly expanded tokens if path prop is already present (platform expand)', () => { + const expanded = expandToken( + { + type: 'border', + value: { + width: '2px', + style: 'solid', + color: '#000', + }, + path: ['input', 'border'], + }, + { expand: true, usesDtcg: false }, + ); + expect(expanded).to.eql({ + color: { + type: 'color', + value: '#000', + path: ['input', 'border', 'color'], + }, + style: { + type: 'strokeStyle', + value: 'solid', + path: ['input', 'border', 'style'], + }, + width: { + type: 'dimension', + value: '2px', + path: ['input', 'border', 'width'], + }, + }); + }); + + it('should handle DTCG spec tokens expansion', () => { + const expanded = expandToken( + { + $type: 'border', + $value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + { expand: true, usesDtcg: true }, + ); + expect(expanded).to.eql({ + color: { + $type: 'color', + $value: '#000', + }, + style: { + $type: 'strokeStyle', + $value: 'solid', + }, + width: { + $type: 'dimension', + $value: '2px', + }, + }); + }); + + it('should handle the expansion of array of objects values', () => { + const expanded = expandToken( + { + type: 'shadow', + value: [ + { + offsetX: '2px', + offsetY: '4px', + blur: '2px', + spread: '0', + color: '#000', + }, + { + offsetX: '10px', + offsetY: '12px', + blur: '4px', + spread: '3px', + color: '#ccc', + }, + ], + }, + { + expand: true, + usesDtcg: false, + }, + ); + + expect(expanded).to.eql({ + 1: { + offsetX: { + type: 'dimension', + value: '2px', + }, + offsetY: { + type: 'dimension', + value: '4px', + }, + blur: { + type: 'dimension', + value: '2px', + }, + spread: { + type: 'dimension', + value: '0', + }, + color: { + type: 'color', + value: '#000', + }, + }, + 2: { + offsetX: { + type: 'dimension', + value: '10px', + }, + offsetY: { + type: 'dimension', + value: '12px', + }, + blur: { + type: 'dimension', + value: '4px', + }, + spread: { + type: 'dimension', + value: '3px', + }, + color: { + type: 'color', + value: '#ccc', + }, + }, + }); + }); + }); + + describe('expandTokens', () => { + it('should not expand tokens when expand is false', () => { + const expanded = expandTokens(input, { + expand: false, + usesDtcg: false, + }); + + expect(expanded).to.eql(input); + }); + + it('should expand tokens when expand is set to true', () => { + const expanded = expandTokens( + { + objectValues: { + nested: input.border, + double: { + nested: input.typography, + }, + }, + }, + { + expand: true, + usesDtcg: false, + }, + ); + + expect(expanded).to.eql({ + objectValues: { + nested: borderOutput, + double: { + nested: typographyOutput, + }, + }, + }); + }); + + it('should allow conditionally expanding tokens by type using include', () => { + const expanded = expandTokens(input, { + expand: { + include: ['typography'], + }, + usesDtcg: false, + }); + + expect(expanded).to.eql({ + border: input.border, + typography: typographyOutput, + }); + }); + + it('should allow conditionally expanding tokens by type using exclude', () => { + const expanded = expandTokens(input, { + expand: { + exclude: ['typography'], + }, + usesDtcg: false, + }); + + expect(expanded).to.eql({ + border: borderOutput, + typography: input.typography, + }); + }); + + it('should allow conditionally expanding tokens by condition function', () => { + const expanded = expandTokens(input, { + expand: (token) => token.value.fontWeight === '800', + usesDtcg: false, + }); + + expect(expanded).to.eql({ + border: input.border, + typography: typographyOutput, + }); + + const expandedInclude = expandTokens(input, { + expand: { include: (token) => token.value.fontWeight === '800' }, + usesDtcg: false, + }); + + expect(expandedInclude).to.eql({ + border: input.border, + typography: typographyOutput, + }); + + const expandedExclude = expandTokens(input, { + expand: { exclude: (token) => token.value.fontWeight === '800' }, + usesDtcg: false, + }); + + expect(expandedExclude).to.eql({ + border: borderOutput, + typography: input.typography, + }); + }); + + it('should also expand tokens that are references to other tokens', () => { + const refInput = { + border: input.border, + borderRef: { + type: 'border', + value: '{border}', + }, + }; + const expanded = expandTokens(refInput, { + expand: true, + usesDtcg: false, + }); + + expect(expanded).to.eql({ + border: borderOutput, + borderRef: borderOutput, + }); + }); + + it('should expand nested composite tokens', () => { + const refInput = { + black: { + value: '#000', + type: 'color', + }, + stroke: { + value: { + dashArray: ['0.5rem', '0.25rem'], + lineCap: 'round', + }, + type: 'strokeStyle', + }, + border: { + value: { + color: '{black}', + width: '3px', + style: '{stroke}', + }, + type: 'border', + }, + }; + + const expanded = expandTokens(refInput, { + expand: true, + usesDtcg: false, + }); + + expect(expanded).to.eql({ + black: { + value: '#000', + type: 'color', + }, + stroke: { + dashArray: { + value: ['0.5rem', '0.25rem'], + type: 'dimension', + }, + lineCap: { + value: 'round', + type: 'lineCap', + }, + }, + border: { + // color can remain unresolved ref because its resolved value is not an object + color: { value: '{black}', type: 'color' }, + width: { value: '3px', type: 'dimension' }, + // style must be its resolved value because it is an object and potentially gets expanded, + // breaking the original reference + style: { + dashArray: { + value: ['0.5rem', '0.25rem'], + type: 'dimension', + }, + lineCap: { + value: 'round', + type: 'lineCap', + }, + }, + }, + }); + }); + + it('should expand shadow tokens', () => { + const refInput = { + shade: { + type: 'shadow', + value: [ + { + offsetX: '2px', + offsetY: '4px', + blur: '2px', + spread: '0', + color: '#000', + }, + { + offsetX: '10px', + offsetY: '12px', + blur: '4px', + spread: '3px', + color: '#ccc', + }, + ], + }, + }; + + const expanded = expandTokens(refInput, { + expand: true, + usesDtcg: false, + }); + + expect(expanded).to.eql({ + shade: { + 1: { + offsetX: { + type: 'dimension', + value: '2px', + }, + offsetY: { + type: 'dimension', + value: '4px', + }, + blur: { + type: 'dimension', + value: '2px', + }, + spread: { + type: 'dimension', + value: '0', + }, + color: { + type: 'color', + value: '#000', + }, + }, + 2: { + offsetX: { + type: 'dimension', + value: '10px', + }, + offsetY: { + type: 'dimension', + value: '12px', + }, + blur: { + type: 'dimension', + value: '4px', + }, + spread: { + type: 'dimension', + value: '3px', + }, + color: { + type: 'color', + value: '#ccc', + }, + }, + }, + }); + }); + + it('should support DTCG format', () => { + const input = { + border: { + $type: 'border', + $value: { + width: '2px', + style: 'solid', + color: '#000', + }, + }, + borderRef: { + $type: 'border', + $value: '{border}', + }, + }; + const expanded = expandTokens(input, { + expand: true, + usesDtcg: true, + }); + + expect(expanded).to.eql({ + border: { + color: { + $type: 'color', + $value: '#000', + }, + style: { + $type: 'strokeStyle', + $value: 'solid', + }, + width: { + $type: 'dimension', + $value: '2px', + }, + }, + borderRef: { + color: { + $type: 'color', + $value: '#000', + }, + style: { + $type: 'strokeStyle', + $value: 'solid', + }, + width: { + $type: 'dimension', + $value: '2px', + }, + }, + }); + }); + + it('should throw an error when include and exclude are combined', () => { + const badFn = () => + expandTokens(input, { + expand: { + include: ['typography'], + exclude: ['border'], + }, + usesDtcg: false, + }); + + expect(badFn).to.throw( + 'expand.include should not be combined with expand.exclude, use one or the other.', + ); + }); + }); + }); + }); +}); diff --git a/__tests__/utils/flattenProperties.test.js b/__tests__/utils/flattenProperties.test.js index cd42bf23a..976d8d5f3 100644 --- a/__tests__/utils/flattenProperties.test.js +++ b/__tests__/utils/flattenProperties.test.js @@ -10,68 +10,62 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import flattenTokens from '../../dist/esm/utils/flattenTokens.mjs'; -var flattenProperties = require('../../lib/utils/flattenProperties'); const sortBy = (key) => { - return (a, b) => (a[key] > b[key]) ? 1 : ((b[key] > a[key]) ? -1 : 0); + return (a, b) => (a[key] > b[key] ? 1 : b[key] > a[key] ? -1 : 0); }; describe('utils', () => { - describe('flattenProperties', () => { - + describe('flattenTokens', () => { it('should return an empty array', () => { - var ret = flattenProperties({}); - expect(ret).toEqual([]); + const ret = flattenTokens({}); + expect(ret).to.eql([]); }); it('should return the same array', () => { - var to_ret = []; - var ret = flattenProperties({}, to_ret); - expect(ret).toBe(ret); + const to_ret = []; + const ret = flattenTokens({}, to_ret); + expect(ret).to.equal(ret); }); it('should return leaf node values as an array', () => { - var properties = { - 'black': { - 'value': '#000000' + const tokens = { + black: { + value: '#000000', + }, + white: { + value: '#FFFFFF', }, - 'white': { - 'value': '#FFFFFF' - } }; - var expected_ret = [ - properties.black, - properties.white - ]; + const expected_ret = [tokens.black, tokens.white]; - var sortedExpectedRet = expected_ret.sort(sortBy('value')); - var ret = flattenProperties(properties); - var sortedRet = ret.sort(sortBy('value')); - expect(sortedRet).toEqual(sortedExpectedRet); + const sortedExpectedRet = expected_ret.sort(sortBy('value')); + const ret = flattenTokens(tokens); + const sortedRet = ret.sort(sortBy('value')); + expect(sortedRet).to.eql(sortedExpectedRet); }); it('should return nested leaf node values as an array', () => { - var properties = { - 'color': { - 'black': { - 'value': '#000000' + const tokens = { + color: { + black: { + value: '#000000', }, - 'white': { - 'value': '#FFFFFF' - } - } + white: { + value: '#FFFFFF', + }, + }, }; - var expected_ret = [ - properties.color.black, - properties.color.white - ]; + const expected_ret = [tokens.color.black, tokens.color.white]; - var sortedExpectedRet = expected_ret.sort(sortBy('value')); - var ret = flattenProperties(properties); - var sortedRet = ret.sort(sortBy('value')); - expect(sortedRet).toEqual(sortedExpectedRet); + const sortedExpectedRet = expected_ret.sort(sortBy('value')); + const ret = flattenTokens(tokens); + const sortedRet = ret.sort(sortBy('value')); + expect(sortedRet).to.eql(sortedExpectedRet); }); }); }); diff --git a/__tests__/utils/groupMessages.test.js b/__tests__/utils/groupMessages.test.js new file mode 100644 index 000000000..82658b9ba --- /dev/null +++ b/__tests__/utils/groupMessages.test.js @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { GroupMessages } from '../../dist/esm/utils/groupMessages.mjs'; + +// TODO: add more tests + +describe('groupMessage', () => { + it('should allow removing messages', () => { + const grpMessages = new GroupMessages(); + const FILTER_WARNINGS = grpMessages.GROUP.FilteredOutputReferences; + grpMessages.add(FILTER_WARNINGS, '{foo.bar}'); + grpMessages.add(FILTER_WARNINGS, '{baz.qux}'); + grpMessages.add(FILTER_WARNINGS, '{another.one}'); + + expect(grpMessages.count(FILTER_WARNINGS)).to.equal(3); + grpMessages.remove(FILTER_WARNINGS, '{baz.qux}'); + expect(grpMessages.count(FILTER_WARNINGS)).to.equal(2); + expect(grpMessages.fetchMessages(FILTER_WARNINGS)).to.eql(['{foo.bar}', '{another.one}']); + }); +}); diff --git a/__tests__/utils/preprocess.test.js b/__tests__/utils/preprocess.test.js new file mode 100644 index 000000000..8149bfae3 --- /dev/null +++ b/__tests__/utils/preprocess.test.js @@ -0,0 +1,68 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { preprocess } from '../../dist/esm/utils/preprocess.mjs'; + +describe('utils', () => { + describe('preprocess', () => { + it('should support multiple preprocessors', async () => { + const output = await preprocess( + { + foo: { + value: '5px', + }, + }, + ['preprocessorA'], + { + preprocessorA: (tokens) => { + tokens.bar = tokens.foo; + return tokens; + }, + }, + ); + expect(output).to.have.property('bar').eql({ + value: '5px', + }); + }); + + it('should support asynchronous preprocessors as well', async () => { + const output = await preprocess( + { + foo: { + value: '5px', + }, + }, + ['preprocessorA', 'preprocessorB', 'preprocessorC'], + { + preprocessorA: (tokens) => { + tokens.bar = tokens.foo; + return tokens; + }, + preprocessorB: async (tokens) => { + await new Promise((resolve) => setTimeout(resolve, 100)); + tokens.baz = tokens.bar; + return tokens; + }, + + preprocessorC: (tokens) => { + tokens.qux = tokens.baz; + return tokens; + }, + }, + ); + expect(output).to.have.property('qux').eql({ + value: '5px', + }); + }); + }); +}); diff --git a/__tests__/utils/reference/getReferences.test.js b/__tests__/utils/reference/getReferences.test.js index 9b96ea103..291ed2473 100644 --- a/__tests__/utils/reference/getReferences.test.js +++ b/__tests__/utils/reference/getReferences.test.js @@ -11,83 +11,103 @@ * and limitations under the License. */ -// `.getReferences` is bound to a dictionary object, so to test it we will -// create a dictionary object and then call `.getReferences` on it. -const createDictionary = require('../../../lib/utils/createDictionary'); +import { expect } from 'chai'; +import { restore, stubMethod } from 'hanbi'; +import { getReferences } from '../../../dist/esm/utils/references/getReferences.mjs'; -const properties = { +const tokens = { color: { - red: { value: "#f00" }, - danger: { value: "{color.red.value}" } + red: { value: '#f00' }, + danger: { value: '{color.red.value}' }, }, size: { - border: { value: "2px" } + border: { value: '2px' }, }, border: { primary: { // getReferences should work on objects like this: value: { - color: "{color.red.value}", - width: "{size.border.value}", - style: "solid" + color: '{color.red.value}', + width: '{size.border.value}', + style: 'solid', }, }, secondary: { // and objects that have a non-string value: { - color: "{color.red.value}", + color: '{color.red.value}', width: 2, - style: "solid" - } + style: 'solid', + }, }, tertiary: { // getReferences should work on interpolated values like this: - value: "{size.border.value} solid {color.red.value}" - } - } -} - -const dictionary = createDictionary({ properties }); + value: '{size.border.value} solid {color.red.value}', + }, + }, +}; describe('utils', () => { describe('reference', () => { describe('getReferences()', () => { + describe('public API', () => { + beforeEach(() => { + restore(); + }); + + it('should not collect errors but rather throw immediately when using public API', () => { + expect(() => getReferences('{foo.bar}', tokens)).to.throw( + `Tries to reference foo.bar, which is not defined.`, + ); + }); + + it('should not collect errors but rather throw immediately when using public API', async () => { + const badFn = () => getReferences('{foo.bar}', tokens); + expect(badFn).to.throw(`Tries to reference foo.bar, which is not defined.`); + }); + + it('should allow warning immediately when references are filtered out', async () => { + const stub = stubMethod(console, 'warn'); + const clonedTokens = structuredClone(tokens); + delete clonedTokens.color.red; + getReferences('{color.red}', clonedTokens, { + unfilteredTokens: tokens, + warnImmediately: true, + }); + expect(stub.firstCall.args[0]).to.equal( + `Filtered out token references were found: color.red`, + ); + }); + }); + it(`should return an empty array if the value has no references`, () => { - expect(dictionary.getReferences(properties.color.red.value)).toEqual([]); + expect(getReferences(tokens.color.red.value, tokens)).to.eql([]); }); it(`should work with a single reference`, () => { - expect(dictionary.getReferences(properties.color.danger.value)).toEqual( - expect.arrayContaining([ - {value: "#f00"} - ]) - ); + expect(getReferences(tokens.color.danger.value, tokens)).to.eql([ + { ref: ['color', 'red'], value: '#f00' }, + ]); }); it(`should work with object values`, () => { - expect(dictionary.getReferences(properties.border.primary.value)).toEqual( - expect.arrayContaining([ - {value: "2px"}, - {value: "#f00"} - ]) - ); + expect(getReferences(tokens.border.primary.value, tokens)).to.eql([ + { ref: ['color', 'red'], value: '#f00' }, + { ref: ['size', 'border'], value: '2px' }, + ]); }); it(`should work with objects that have numbers`, () => { - expect(dictionary.getReferences(properties.border.secondary.value)).toEqual( - expect.arrayContaining([ - {value: "#f00"} - ]) - ); + expect(getReferences(tokens.border.secondary.value, tokens)).to.eql([ + { ref: ['color', 'red'], value: '#f00' }, + ]); }); it(`should work with interpolated values`, () => { - expect(dictionary.getReferences(properties.border.tertiary.value)).toEqual( - expect.arrayContaining([ - {value: "2px"}, - {value: "#f00"} - ]) - ); + expect(getReferences(tokens.border.tertiary.value, tokens)).to.eql([ + { ref: ['size', 'border'], value: '2px' }, + { ref: ['color', 'red'], value: '#f00' }, + ]); }); }); }); diff --git a/__tests__/utils/reference/resolveReference.test.js b/__tests__/utils/reference/getValueByPath.test.js similarity index 51% rename from __tests__/utils/reference/resolveReference.test.js rename to __tests__/utils/reference/getValueByPath.test.js index f3b2e4290..eac74f58f 100644 --- a/__tests__/utils/reference/resolveReference.test.js +++ b/__tests__/utils/reference/getValueByPath.test.js @@ -10,55 +10,46 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ - -const resolveReference = require('../../../lib/utils/references/resolveReference'); +import { expect } from 'chai'; +import getValueByPath from '../../../dist/esm/utils/references/getValueByPath.mjs'; const dictionary = { color: { palette: { neutral: { - 0: { value: "#ffffff" }, - 5: { value: "#f2f3f4" } - } + 0: { value: '#ffffff' }, + 5: { value: '#f2f3f4' }, + }, }, background: { - primary: { value: "{color.palette.neutral.0.value}" } - } + primary: { value: '{color.palette.neutral.0.value}' }, + }, }, - arr: [ - 'one', - 'two' - ] -} + arr: ['one', 'two'], +}; -describe('resolveReference()', () => { +describe('getValueByPath()', () => { it(`returns undefined for non-strings`, () => { - expect(resolveReference(42, dictionary)).toBe(undefined); + expect(getValueByPath(42, dictionary)).to.be.undefined; }); it(`returns undefined if it does not find the path in the object`, () => { - expect(resolveReference(['color','foo'], dictionary)).toBe(undefined); - expect(resolveReference(['color','foo','bar'], dictionary)).toBe(undefined); + expect(getValueByPath(['color', 'foo'], dictionary)).to.be.undefined; + expect(getValueByPath(['color', 'foo', 'bar'], dictionary)).to.be.undefined; }); it(`returns the part of the object if referenced path exists`, () => { - expect( - resolveReference(['color','palette','neutral','0','value'], dictionary) - ).toEqual(dictionary.color.palette.neutral['0'].value); - expect( - resolveReference(['color'], dictionary) - ).toEqual(dictionary.color); + expect(getValueByPath(['color', 'palette', 'neutral', '0', 'value'], dictionary)).to.equal( + dictionary.color.palette.neutral['0'].value, + ); + expect(getValueByPath(['color'], dictionary)).to.equal(dictionary.color); }); it(`works with arrays`, () => { - expect( - resolveReference(['arr'], dictionary) - ).toEqual(dictionary.arr); + expect(getValueByPath(['arr'], dictionary)).to.equal(dictionary.arr); }); it(`works with array indices`, () => { - expect( - resolveReference(['arr','0'], dictionary) - ).toEqual(dictionary.arr[0]); + expect(getValueByPath(['arr', '0'], dictionary)).to.equal(dictionary.arr[0]); }); }); diff --git a/__tests__/utils/reference/resolveReferences.test.js b/__tests__/utils/reference/resolveReferences.test.js new file mode 100644 index 000000000..1fd9a19a0 --- /dev/null +++ b/__tests__/utils/reference/resolveReferences.test.js @@ -0,0 +1,247 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { restore } from 'hanbi'; +import { fileToJSON } from '../../__helpers.js'; +import { + _resolveReferences as resolveReferences, + resolveReferences as publicResolveReferences, +} from '../../../dist/esm/utils/references/resolveReferences.mjs'; +import GroupMessages from '../../../dist/esm/utils/groupMessages.mjs'; + +const PROPERTY_REFERENCE_WARNINGS = GroupMessages.GROUP.PropertyReferenceWarnings; + +describe('utils', () => { + describe('references', () => { + describe('resolveReferences', () => { + beforeEach(() => { + GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); + restore(); + }); + + describe('public API', () => { + it('should not collect errors but rather throw immediately when using public API', () => { + const obj = fileToJSON('__tests__/__json_files/multiple_reference_errors.json'); + expect(() => publicResolveReferences(obj.a.b, obj)).to.throw( + `tries to reference b.a, which is not defined.`, + ); + expect(() => publicResolveReferences(obj.a.c, obj)).to.throw( + `tries to reference b.c, which is not defined.`, + ); + expect(() => publicResolveReferences(obj.a.d, obj)).to.throw( + `tries to reference d, which is not defined.`, + ); + }); + }); + + it('should do simple references', () => { + const test = resolveReferences('{foo}', fileToJSON('__tests__/__json_files/simple.json')); + expect(test).to.equal('bar'); + }); + + it('should do simple interpolation for both strings and numbers', () => { + const obj = fileToJSON('__tests__/__json_files/interpolation.json'); + expect(resolveReferences(obj.c, obj)).to.equal('test1 value text after'); + expect(resolveReferences(obj.d, obj)).to.equal('text before test1 value'); + expect(resolveReferences(obj.e, obj)).to.equal('text before test1 value text after'); + expect(resolveReferences(obj.f, obj)).to.equal('123 text after'); + expect(resolveReferences(obj.g, obj)).to.equal('text before 123'); + expect(resolveReferences(obj.h, obj)).to.equal('text before 123 text after'); + }); + + it('should do nested references', () => { + const obj = fileToJSON('__tests__/__json_files/nested_references.json'); + expect(resolveReferences(obj.i, obj)).to.equal(2); + expect(resolveReferences(obj.a.b.d, obj)).to.equal(2); + expect(resolveReferences(obj.e.f.h, obj)).to.equal(1); + }); + + it('should handle nested pointers', () => { + const obj = fileToJSON('__tests__/__json_files/nested_pointers.json'); + expect(resolveReferences(obj.b, obj)).to.equal(1); + expect(resolveReferences(obj.c, obj)).to.equal(1); + }); + + it('should handle deep nested pointers', () => { + const obj = fileToJSON('__tests__/__json_files/nested_pointers_2.json'); + expect(resolveReferences(obj.a, obj)).to.equal(1); + expect(resolveReferences(obj.b, obj)).to.equal(1); + expect(resolveReferences(obj.c, obj)).to.equal(1); + expect(resolveReferences(obj.d, obj)).to.equal(1); + expect(resolveReferences(obj.e, obj)).to.equal(1); + expect(resolveReferences(obj.f, obj)).to.equal(1); + }); + + it('should handle deep nested pointers with string interpolation', () => { + const obj = fileToJSON('__tests__/__json_files/nested_pointers_3.json'); + expect(resolveReferences(obj.a, obj)).to.equal('foo bon bee bae boo bla baz bar'); + expect(resolveReferences(obj.b, obj)).to.equal('foo bon bee bae boo bla baz'); + expect(resolveReferences(obj.c, obj)).to.equal('foo bon bee bae boo bla'); + expect(resolveReferences(obj.d, obj)).to.equal('foo bon bee bae boo'); + expect(resolveReferences(obj.e, obj)).to.equal('foo bon bee bae'); + expect(resolveReferences(obj.f, obj)).to.equal('foo bon bee'); + expect(resolveReferences(obj.g, obj)).to.equal('foo bon'); + }); + + it('should handle deep nested pointers and nested references', () => { + const obj = fileToJSON('__tests__/__json_files/nested_pointers_4.json'); + expect(resolveReferences(obj.a.a.a, obj)).to.equal(1); + expect(resolveReferences(obj.b.b.b, obj)).to.equal(1); + expect(resolveReferences(obj.c.c.c, obj)).to.equal(1); + expect(resolveReferences(obj.d.d.d, obj)).to.equal(1); + expect(resolveReferences(obj.e.e.e, obj)).to.equal(1); + expect(resolveReferences(obj.f.f.f, obj)).to.equal(1); + }); + + it('should keep the type of the referenced property', () => { + const obj = fileToJSON('__tests__/__json_files/reference_type.json'); + expect(resolveReferences(obj.d, obj)).to.equal(1); + expect(typeof resolveReferences(obj.d, obj)).to.equal('number'); + expect(typeof resolveReferences(obj.e, obj)).to.equal('object'); + expect(resolveReferences(obj.e, obj)).to.eql({ c: 2 }); + expect(resolveReferences(obj.g, obj)).to.eql([1, 2, 3]); + }); + + it('should handle and evaluate items in an array', () => { + const obj = fileToJSON('__tests__/__json_files/array.json'); + expect(resolveReferences(obj.d[0], obj)).to.equal(2); + expect(resolveReferences(obj.d[1], obj)).to.equal(1); + expect(resolveReferences(obj.e[0].a, obj)).to.equal(1); + expect(resolveReferences(obj.e[1].a, obj)).to.equal(2); + }); + + it('should collect reference errors when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/non_existent.json'); + expect(resolveReferences(obj.foo, obj, { warnImmediately: false })).to.be.undefined; + expect(resolveReferences(obj.error, obj, { warnImmediately: false })).to.be.undefined; + expect(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS)).to.eql([ + 'tries to reference bar, which is not defined.', + 'tries to reference a.b.d, which is not defined.', + ]); + }); + + it('should gracefully handle basic circular references, collect warnings when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/circular.json'); + expect(resolveReferences(obj.a, obj, { warnImmediately: false })).to.equal('{b}'); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: b, c, d, a, b']), + ); + }); + + it('should gracefully handle basic and nested circular references, collect warnings when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/circular_2.json'); + expect(resolveReferences(obj.j, obj, { warnImmediately: false })).to.equal('{a.b.c}'); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a.b.c, j, a.b.c']), + ); + }); + + it('should gracefully handle nested circular references, collect warnings when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/circular_3.json'); + expect(resolveReferences(obj.c.d.e, obj, { warnImmediately: false })).to.equal('{a.b}'); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a.b, c.d.e, a.b']), + ); + }); + + it('should gracefully handle multiple nested circular references, collect warnings when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/circular_4.json'); + expect(resolveReferences(obj.h.i, obj, { warnImmediately: false })).to.equal('{a.b.c.d}'); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a.b.c.d, e.f.g, h.i, a.b.c.d']), + ); + }); + + it('should gracefully handle down-chain circular references, collect warnings when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/circular_5.json'); + expect(resolveReferences(obj.n, obj, { warnImmediately: false })).to.equal('{l}'); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: l, m, l']), + ); + }); + + it('should correctly resolve multiple references without reference errors', function () { + const obj = fileToJSON('__tests__/__json_files/not_circular.json'); + expect(resolveReferences(obj.prop8.value, obj, { warnImmediately: false })).to.equal(5); + expect(resolveReferences(obj.prop12.value, obj, { warnImmediately: false })).to.equal( + 'test1 value, test2 value and some extra stuff', + ); + expect(resolveReferences(obj.prop124.value, obj, { warnImmediately: false })).to.equal( + 'test1 value, test2 value and test1 value', + ); + expect(resolveReferences(obj.prop15.value, obj, { warnImmediately: false })).to.equal( + 'test1 value, 5 and some extra stuff', + ); + expect(resolveReferences(obj.prop156.value, obj, { warnImmediately: false })).to.equal( + 'test1 value, 5 and 6', + ); + expect(resolveReferences(obj.prop1568.value, obj, { warnImmediately: false })).to.equal( + 'test1 value, 5, 6 and 5', + ); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(0); + }); + + describe('ignorePaths', () => { + it('should not resolve values containing constiables in ignored paths', () => { + const obj = { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + }, + }; + const test = resolveReferences(obj.bar.value, obj, { ignorePaths: ['foo.value'] }); + expect(test).to.equal('{foo.value}'); + }); + }); + + it('should handle spaces', () => { + const obj = { + foo: { value: 'foo' }, + bar: { value: '{ foo.value }' }, + }; + const test = resolveReferences(obj.bar.value, obj); + expect(test).to.equal('foo'); + }); + + it('should collect multiple reference errors when warnImmediately is set to false', () => { + const obj = fileToJSON('__tests__/__json_files/multiple_reference_errors.json'); + expect(resolveReferences(obj.a.b, obj, { warnImmediately: false })).to.be.undefined; + expect(resolveReferences(obj.a.c, obj, { warnImmediately: false })).to.be.undefined; + expect(resolveReferences(obj.a.d, obj, { warnImmediately: false })).to.be.undefined; + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(3); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify([ + 'tries to reference b.a, which is not defined.', + 'tries to reference b.c, which is not defined.', + 'tries to reference d, which is not defined.', + ]), + ); + }); + + it('should handle 0', () => { + const obj = { + test: { value: '{zero.value}' }, + zero: { value: 0 }, + }; + const test = resolveReferences(obj.test.value, obj, { warnImmediately: false }); + expect(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS).length).to.equal(0); + expect(test).to.equal(0); + }); + }); + }); +}); diff --git a/__tests__/utils/reference/usesReference.test.js b/__tests__/utils/reference/usesReferences.test.js similarity index 62% rename from __tests__/utils/reference/usesReference.test.js rename to __tests__/utils/reference/usesReferences.test.js index d64af1af0..8979a4efa 100644 --- a/__tests__/utils/reference/usesReference.test.js +++ b/__tests__/utils/reference/usesReferences.test.js @@ -10,55 +10,55 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import usesReferences from '../../../dist/esm/utils/references/usesReferences.mjs'; -const usesReference = require('../../../lib/utils/references/usesReference'); - -describe('usesReference()', () => { +describe('usesReferences()', () => { it(`returns false for non-strings`, () => { - expect(usesReference(42)).toBe(false); + expect(usesReferences(42)).to.be.false; }); it(`returns false if value uses no reference`, () => { - expect(usesReference('foo.bar')).toBe(false); + expect(usesReferences('foo.bar')).to.be.false; }); it(`returns true if value is a reference`, () => { - expect(usesReference('{foo.bar}')).toBe(true); + expect(usesReferences('{foo.bar}')).to.be.true; }); it(`should return true if value uses a reference`, () => { - expect(usesReference('baz {foo.bar}')).toBe(true); + expect(usesReferences('baz {foo.bar}')).to.be.true; }); it(`returns true if an object uses a reference`, () => { - expect(usesReference({foo: '{bar}'})).toBe(true); + expect(usesReferences({ foo: '{bar}' })).to.be.true; }); it(`returns false if an object doesn't have a reference`, () => { - expect(usesReference({foo: 'bar'})).toBe(false); + expect(usesReferences({ foo: 'bar' })).to.be.false; }); it(`returns true if a nested object has a reference`, () => { - expect(usesReference({foo: {bar: '{bar}'}})).toBe(true); + expect(usesReferences({ foo: { bar: '{bar}' } })).to.be.true; }); it(`returns true if an array uses a reference`, () => { - expect(usesReference(["foo", "{bar}"])).toBe(true); + expect(usesReferences(['foo', '{bar}'])).to.be.true; }); it(`returns false if an array doesn't use a reference`, () => { - expect(usesReference(["foo", "bar"])).toBe(false); + expect(usesReferences(['foo', 'bar'])).to.be.false; }); describe(`with custom options`, () => { - test(`returns true if value is reference`, () => { + it(`returns true if value is reference`, () => { const customOpts = { opening_character: '(', closing_character: ')', - separator: '|' + separator: '|', }; - expect(usesReference('(foo|bar)', customOpts)).toBe(true); + expect(usesReferences('(foo|bar)', customOpts)).to.be.true; }); }); }); diff --git a/__tests__/utils/resolveObject.test.js b/__tests__/utils/resolveObject.test.js index a1359e45a..378d025a9 100644 --- a/__tests__/utils/resolveObject.test.js +++ b/__tests__/utils/resolveObject.test.js @@ -10,329 +10,345 @@ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ +import { expect } from 'chai'; +import { fileToJSON } from '../__helpers.js'; +import resolveObject from '../../dist/esm/utils/resolveObject.mjs'; +import GroupMessages from '../../dist/esm/utils/groupMessages.mjs'; -var resolveObject = require('../../lib/utils/resolveObject'); -var helpers = require('../__helpers'); -var GroupMessages = require('../../lib/utils/groupMessages'); - -var PROPERTY_REFERENCE_WARNINGS = GroupMessages.GROUP.PropertyReferenceWarnings; +const PROPERTY_REFERENCE_WARNINGS = GroupMessages.GROUP.PropertyReferenceWarnings; describe('utils', () => { describe('resolveObject', () => { + beforeEach(() => { + GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); + }); + afterEach(() => { + GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); + }); it('should error on non-objects', () => { - expect( - resolveObject.bind(null) - ).toThrow('Please pass an object in'); - expect( - resolveObject.bind(null, 'foo') - ).toThrow('Please pass an object in'); - expect( - resolveObject.bind(null, 0) - ).toThrow('Please pass an object in'); + expect(resolveObject.bind(null)).to.throw('Please pass an object in'); + expect(resolveObject.bind(null, 'foo')).to.throw('Please pass an object in'); + expect(resolveObject.bind(null, 0)).to.throw('Please pass an object in'); }); it('should not mutate the original object', () => { - var original = helpers.fileToJSON(__dirname + '/../__json_files/nested_references.json'); - var test = resolveObject( original ); - expect(original).toHaveProperty('a.b.d', '{e.f.g}'); - expect(test).toHaveProperty('a.b.d', 2); + const original = fileToJSON('__tests__/__json_files/nested_references.json'); + const test = resolveObject(original); + expect(original).to.have.nested.property('a.b.d', '{e.f.g}'); + expect(test).to.have.nested.property('a.b.d', 2); }); it('should do simple references', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/simple.json') ); - expect(test).toHaveProperty('bar', 'bar'); + const test = resolveObject(fileToJSON('__tests__/__json_files/simple.json')); + expect(test).to.have.property('bar', 'bar'); }); - + it('should do simple interpolation for both strings and numbers', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/interpolation.json') ); - expect(test).toHaveProperty('c', 'test1 value text after'); - expect(test).toHaveProperty('d', 'text before test1 value'); - expect(test).toHaveProperty('e', 'text before test1 value text after'); - expect(test).toHaveProperty('f', '123 text after'); - expect(test).toHaveProperty('g', 'text before 123'); - expect(test).toHaveProperty('h', 'text before 123 text after'); + const test = resolveObject(fileToJSON('__tests__/__json_files/interpolation.json')); + expect(test).to.have.property('c', 'test1 value text after'); + expect(test).to.have.property('d', 'text before test1 value'); + expect(test).to.have.property('e', 'text before test1 value text after'); + expect(test).to.have.property('f', '123 text after'); + expect(test).to.have.property('g', 'text before 123'); + expect(test).to.have.property('h', 'text before 123 text after'); }); it('should do nested references', () => { - var obj = helpers.fileToJSON(__dirname + '/../__json_files/nested_references.json'); - var test = resolveObject( obj ); - expect(test).toHaveProperty('i', 2); - expect(test).toHaveProperty('a.b.d', 2); - expect(test).toHaveProperty('e.f.h', 1); + const obj = fileToJSON('__tests__/__json_files/nested_references.json'); + const test = resolveObject(obj); + expect(test).to.have.property('i', 2); + expect(test).to.have.nested.property('a.b.d', 2); + expect(test).to.have.nested.property('e.f.h', 1); }); it('should handle nested pointers', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/nested_pointers.json') ); - expect(test).toHaveProperty('b', 1); - expect(test).toHaveProperty('c', 1); + const test = resolveObject(fileToJSON('__tests__/__json_files/nested_pointers.json')); + expect(test).to.have.property('b', 1); + expect(test).to.have.property('c', 1); }); it('should handle deep nested pointers', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/nested_pointers_2.json') ); - expect(test).toHaveProperty('a', 1); - expect(test).toHaveProperty('b', 1); - expect(test).toHaveProperty('c', 1); - expect(test).toHaveProperty('d', 1); - expect(test).toHaveProperty('e', 1); - expect(test).toHaveProperty('f', 1); - expect(test).toHaveProperty('g', 1); + const test = resolveObject(fileToJSON('__tests__/__json_files/nested_pointers_2.json')); + expect(test).to.have.property('a', 1); + expect(test).to.have.property('b', 1); + expect(test).to.have.property('c', 1); + expect(test).to.have.property('d', 1); + expect(test).to.have.property('e', 1); + expect(test).to.have.property('f', 1); + expect(test).to.have.property('g', 1); }); it('should handle deep nested pointers with string interpolation', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/nested_pointers_3.json') ); - expect(test).toHaveProperty('a', 'foo bon bee bae boo bla baz bar'); - expect(test).toHaveProperty('b', 'foo bon bee bae boo bla baz'); - expect(test).toHaveProperty('c', 'foo bon bee bae boo bla'); - expect(test).toHaveProperty('d', 'foo bon bee bae boo'); - expect(test).toHaveProperty('e', 'foo bon bee bae'); - expect(test).toHaveProperty('f', 'foo bon bee'); - expect(test).toHaveProperty('g', 'foo bon'); - } - ); + const test = resolveObject(fileToJSON('__tests__/__json_files/nested_pointers_3.json')); + expect(test).to.have.property('a', 'foo bon bee bae boo bla baz bar'); + expect(test).to.have.property('b', 'foo bon bee bae boo bla baz'); + expect(test).to.have.property('c', 'foo bon bee bae boo bla'); + expect(test).to.have.property('d', 'foo bon bee bae boo'); + expect(test).to.have.property('e', 'foo bon bee bae'); + expect(test).to.have.property('f', 'foo bon bee'); + expect(test).to.have.property('g', 'foo bon'); + }); it('should handle deep nested pointers and nested references', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/nested_pointers_4.json') ); - expect(test).toHaveProperty('a.a.a', 1); - expect(test).toHaveProperty('b.b.b', 1); - expect(test).toHaveProperty('c.c.c', 1); - expect(test).toHaveProperty('d.d.d', 1); - expect(test).toHaveProperty('e.e.e', 1); - expect(test).toHaveProperty('f.f.f', 1); - expect(test).toHaveProperty('g.g.g', 1); + const test = resolveObject(fileToJSON('__tests__/__json_files/nested_pointers_4.json')); + expect(test).to.have.nested.property('a.a.a', 1); + expect(test).to.have.nested.property('b.b.b', 1); + expect(test).to.have.nested.property('c.c.c', 1); + expect(test).to.have.nested.property('d.d.d', 1); + expect(test).to.have.nested.property('e.e.e', 1); + expect(test).to.have.nested.property('f.f.f', 1); + expect(test).to.have.nested.property('g.g.g', 1); }); - it('should keep the type of the referenced property', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/reference_type.json') ); - expect(test).toHaveProperty('d', 1); - expect(typeof test.d).toBe('number'); - expect(typeof test.e).toBe('object'); - expect(Array.isArray(test.f)).toBeTruthy(); - expect(test).toHaveProperty('e.c', 2); + const test = resolveObject(fileToJSON('__tests__/__json_files/reference_type.json')); + expect(test).to.have.property('d', 1); + expect(typeof test.d).to.equal('number'); + expect(typeof test.e).to.equal('object'); + expect(Array.isArray(test.f)).to.be.true; + expect(test).to.have.nested.property('e.c', 2); }); it('should handle and evaluate items in an array', () => { - var test = resolveObject( helpers.fileToJSON(__dirname + '/../__json_files/array.json') ); - expect(test.d[0]).toBe(2); - expect(test.d[1]).toBe(1); - expect(test.e[0].a).toBe(1); - expect(test.e[1].a).toBe(2); + const test = resolveObject(fileToJSON('__tests__/__json_files/array.json')); + expect(test.d[0]).to.equal(2); + expect(test.d[1]).to.equal(1); + expect(test.e[0].a).to.equal(1); + expect(test.e[1].a).to.equal(2); }); - it('should throw if pointers don\'t exist', () => { - expect( - resolveObject.bind( helpers.fileToJSON(__dirname + '/../__json_files/non_existent.json')) - ).toThrow(); + it("should throw if pointers don't exist", () => { + expect(resolveObject.bind(fileToJSON('__tests__/__json_files/non_existent.json'))).to.throw(); }); it('should gracefully handle basic circular references', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/circular.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(1); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).toBe(JSON.stringify([ - 'Circular definition cycle: a, b, c, d, a' - ])); + resolveObject(fileToJSON('__tests__/__json_files/circular.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a, b, c, d, a']), + ); }); it('should gracefully handle basic and nested circular references', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/circular_2.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(1); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).toBe(JSON.stringify([ - 'Circular definition cycle: a.b.c, j, a.b.c' - ])); + resolveObject(fileToJSON('__tests__/__json_files/circular_2.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a.b.c, j, a.b.c']), + ); }); it('should gracefully handle nested circular references', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/circular_3.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(1); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).toBe(JSON.stringify([ - 'Circular definition cycle: a.b, c.d.e, a.b' - ])); + resolveObject(fileToJSON('__tests__/__json_files/circular_3.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a.b, c.d.e, a.b']), + ); }); it('should gracefully handle multiple nested circular references', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/circular_4.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(1); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).toBe(JSON.stringify([ - 'Circular definition cycle: a.b.c.d, e.f.g, h.i, a.b.c.d', - ])); + resolveObject(fileToJSON('__tests__/__json_files/circular_4.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: a.b.c.d, e.f.g, h.i, a.b.c.d']), + ); }); it('should gracefully handle down-chain circular references', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/circular_5.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(1); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).toBe(JSON.stringify([ - 'Circular definition cycle: l, m, l', - ])); + resolveObject(fileToJSON('__tests__/__json_files/circular_5.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(1); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify(['Circular definition cycle: l, m, l']), + ); }); - it('should correctly replace multiple references without reference errors', function() { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - var obj = resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/not_circular.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(0); - expect(JSON.stringify(obj)).toBe(JSON.stringify({ - prop1: { value: 'test1 value' }, - prop2: { value: 'test2 value' }, - prop3: { value: 'test1 value' }, - prop4: { value: 'test1 value' }, - prop5: { value: 5 }, - prop6: { value: 6 }, - prop7: { value: 5 }, - prop8: { value: 5 }, - prop12: { value: 'test1 value, test2 value and some extra stuff' }, - prop124: { value: 'test1 value, test2 value and test1 value' }, - prop15 : { value: 'test1 value, 5 and some extra stuff' }, - prop156 : { value: 'test1 value, 5 and 6' }, - prop1568 : { value: 'test1 value, 5, 6 and 5' } - })); + it('should correctly replace multiple references without reference errors', function () { + const obj = resolveObject(fileToJSON('__tests__/__json_files/not_circular.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(0); + expect(JSON.stringify(obj)).to.equal( + JSON.stringify({ + prop1: { value: 'test1 value' }, + prop2: { value: 'test2 value' }, + prop3: { value: 'test1 value' }, + prop4: { value: 'test1 value' }, + prop5: { value: 5 }, + prop6: { value: 6 }, + prop7: { value: 5 }, + prop8: { value: 5 }, + prop12: { value: 'test1 value, test2 value and some extra stuff' }, + prop124: { value: 'test1 value, test2 value and test1 value' }, + prop15: { value: 'test1 value, 5 and some extra stuff' }, + prop156: { value: 'test1 value, 5 and 6' }, + prop1568: { value: 'test1 value, 5, 6 and 5' }, + }), + ); }); describe('ignorePaths', () => { - it('should not resolve values containing variables in ignored paths', () => { - const test = resolveObject({ - foo: { value: 'bar' }, - bar: { - value: '{foo.value}' - } - }, {ignorePaths: ['foo.value']}); + it('should not resolve values containing constiables in ignored paths', () => { + const test = resolveObject( + { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + }, + }, + { ignorePaths: ['foo.value'] }, + ); - expect(test).toHaveProperty ('bar.value', '{foo.value}'); + expect(test).to.have.nested.property('bar.value', '{foo.value}'); }); }); describe('ignoreKeys', () => { it('should handle default value of original', () => { - var test = resolveObject({ + const test = resolveObject({ foo: { value: 'bar' }, bar: { value: '{foo.value}', - original: '{foo.value}' - } + original: '{foo.value}', + }, }); - expect(test).toHaveProperty ('bar.original', '{foo.value}'); + expect(test).to.have.nested.property('bar.original', '{foo.value}'); }); it('should handle any nested keys under the ignoreKey', () => { - var test = resolveObject({ + const test = resolveObject({ foo: { value: 'bar' }, bar: { value: '{foo.value}', original: { value: '{foo.value}', foo: { - bar: '{foo.value}' - } - } - } + bar: '{foo.value}', + }, + }, + }, }); - expect(test).toHaveProperty ('bar.original.value', '{foo.value}'); - expect(test).toHaveProperty ('bar.original.foo.bar', '{foo.value}'); + expect(test).to.have.nested.property('bar.original.value', '{foo.value}'); + expect(test).to.have.nested.property('bar.original.foo.bar', '{foo.value}'); }); it('should handle passing in custom ignoreKeys', () => { - var test = resolveObject({ - foo: { value: 'bar' }, - bar: { - value: '{foo.value}', - baz: '{foo.value}' - } - }, { - ignoreKeys: ['baz'] - }); - expect(test).toHaveProperty ('bar.baz', '{foo.value}'); + const test = resolveObject( + { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + baz: '{foo.value}', + }, + }, + { + ignoreKeys: ['baz'], + }, + ); + expect(test).to.have.nested.property('bar.baz', '{foo.value}'); }); it('should handle multiple keys', () => { - var test = resolveObject({ - foo: { value: 'bar' }, - bar: { - value: '{foo.value}', - original: '{foo.value}', - baz: '{foo.value}' - } - },{ - ignoreKeys: ['baz','original'] - }); - expect(test).toHaveProperty ('bar.original', '{foo.value}'); - expect(test).toHaveProperty ('bar.baz', '{foo.value}'); + const test = resolveObject( + { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + original: '{foo.value}', + baz: '{foo.value}', + }, + }, + { + ignoreKeys: ['baz', 'original'], + }, + ); + expect(test).to.have.nested.property('bar.original', '{foo.value}'); + expect(test).to.have.nested.property('bar.baz', '{foo.value}'); }); it('should not ignore anything if set to null or empty array', () => { - var test = resolveObject({ - foo: { value: 'bar' }, - bar: { - value: '{foo.value}', - original: '{foo.value}' - } - },{ - ignoreKeys: [] - }); - expect(test).toHaveProperty ('bar.original', 'bar'); - - var test2 = resolveObject({ - foo: { value: 'bar' }, - bar: { - value: '{foo.value}', - original: '{foo.value}' - } - },{ - ignoreKeys: null - }); - expect(test2).toHaveProperty ('bar.original', 'bar'); - - var test3 = resolveObject({ - foo: { value: 'bar' }, - bar: { - value: '{foo.value}', - original: '{foo.value}' - } - },{ - ignoreKeys: undefined - }); - expect(test3).toHaveProperty ('bar.original', 'bar'); + const test = resolveObject( + { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + original: '{foo.value}', + }, + }, + { + ignoreKeys: [], + }, + ); + expect(test).to.have.nested.property('bar.original', 'bar'); + + const test2 = resolveObject( + { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + original: '{foo.value}', + }, + }, + { + ignoreKeys: null, + }, + ); + expect(test2).to.have.nested.property('bar.original', 'bar'); + + const test3 = resolveObject( + { + foo: { value: 'bar' }, + bar: { + value: '{foo.value}', + original: '{foo.value}', + }, + }, + { + ignoreKeys: undefined, + }, + ); + expect(test3).to.have.nested.property('bar.original', 'bar'); }); }); it('should handle spaces', () => { - var test = resolveObject({ + const test = resolveObject({ foo: { value: 'bar' }, - bar: { value: '{ foo.value }'} + bar: { value: '{ foo.value }' }, }); - expect(test).toHaveProperty ('foo.value', test.bar.value); + expect(test).to.have.nested.property('foo.value', test.bar.value); }); it('should collect multiple reference errors', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - - resolveObject(helpers.fileToJSON(__dirname + '/../__json_files/multiple_reference_errors.json')); - expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).toBe(3); - expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).toBe(JSON.stringify([ - "Reference doesn't exist: a.b tries to reference b.a, which is not defined", - "Reference doesn't exist: a.c tries to reference b.c, which is not defined", - "Reference doesn't exist: a.d tries to reference d, which is not defined" - ])); + resolveObject(fileToJSON('__tests__/__json_files/multiple_reference_errors.json')); + expect(GroupMessages.count(PROPERTY_REFERENCE_WARNINGS)).to.equal(3); + expect(JSON.stringify(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS))).to.equal( + JSON.stringify([ + 'a.b tries to reference b.a, which is not defined.', + 'a.c tries to reference b.c, which is not defined.', + 'a.d tries to reference d, which is not defined.', + ]), + ); }); it('should handle 0', () => { - GroupMessages.clear(PROPERTY_REFERENCE_WARNINGS); - var test = resolveObject({ - "test": { "value": "{zero.value}" }, - "zero": { "value": 0} + const test = resolveObject({ + test: { value: '{zero.value}' }, + zero: { value: 0 }, }); - expect(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS).length).toBe(0); - expect(test.test.value).toBe(0); + expect(GroupMessages.fetchMessages(PROPERTY_REFERENCE_WARNINGS).length).to.equal(0); + expect(test.test.value).to.equal(0); }); + it('should support DTCG format', () => { + const test = resolveObject( + { + test: { $value: '{zero.$value}' }, + zero: { $value: 0 }, + test2: { $value: '{one}' }, + one: { $value: 1 }, + }, + { usesDtcg: true }, + ); + expect(test.test.$value).to.equal(0); + expect(test.test2.$value).to.equal(1); + }); }); }); diff --git a/__tests__/utils/typeDtcgDelegate.test.js b/__tests__/utils/typeDtcgDelegate.test.js new file mode 100644 index 000000000..14ef8fa88 --- /dev/null +++ b/__tests__/utils/typeDtcgDelegate.test.js @@ -0,0 +1,174 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import { typeDtcgDelegate } from '../../dist/esm/utils/typeDtcgDelegate.mjs'; + +describe('utils', () => { + describe('typeDtcgDelegate', () => { + it('should correctly let tokens inherit the $type property while respecting local overrides', () => { + const tokens = { + dimension: { + $type: 'dimension', + scale: { + $value: '2', + $type: 'math', + }, + xs: { + $value: '4', + }, + nested: { + deep: { + deeper: { + $value: '12', + }, + }, + deep2: { + $type: 'math', + deeper: { + $type: 'other', + evenDeeper: { + $value: '12', + $type: 'math', + }, + evenDeeper2: { + $value: '12', + }, + }, + }, + }, + sm: { + $value: '8', + }, + }, + }; + + expect(typeDtcgDelegate(tokens)).to.eql({ + dimension: { + $type: 'dimension', + scale: { + $value: '2', + $type: 'math', + }, + xs: { + $value: '4', + $type: 'dimension', + }, + nested: { + deep: { + deeper: { + $value: '12', + $type: 'dimension', + }, + }, + deep2: { + $type: 'math', + deeper: { + $type: 'other', + evenDeeper: { + $value: '12', + $type: 'math', + }, + evenDeeper2: { + $value: '12', + $type: 'other', + }, + }, + }, + }, + sm: { + $value: '8', + $type: 'dimension', + }, + }, + }); + }); + + it('should work regardless at which position the $type property sits', () => { + const tokens = { + dimension: { + scale: { + $value: '2', + $type: 'math', + }, + xs: { + $value: '4', + }, + nested: { + deep: { + deeper: { + $value: '12', + }, + }, + deep2: { + $type: 'math', + deeper: { + $type: 'other', + evenDeeper: { + $value: '12', + $type: 'math', + }, + evenDeeper2: { + $value: '12', + }, + }, + }, + }, + sm: { + $value: '8', + }, + $type: 'dimension', + }, + }; + + expect(typeDtcgDelegate(tokens)).to.eql({ + dimension: { + $type: 'dimension', + scale: { + $value: '2', + $type: 'math', + }, + xs: { + $value: '4', + $type: 'dimension', + }, + nested: { + deep: { + deeper: { + $value: '12', + $type: 'dimension', + }, + }, + deep2: { + $type: 'math', + deeper: { + $type: 'other', + evenDeeper: { + $value: '12', + $type: 'math', + }, + evenDeeper2: { + $value: '12', + $type: 'other', + }, + }, + }, + }, + sm: { + $value: '8', + $type: 'dimension', + }, + }, + }); + }); + }); +}); diff --git a/bin/style-dictionary b/bin/style-dictionary deleted file mode 100755 index 3e1f79ffa..000000000 --- a/bin/style-dictionary +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var fs = require('fs-extra'), - program = require('commander'), - path = require('path'), - StyleDictionary = require('..'), - pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')), - chalk = require('chalk'); - -function collect(val, arr) { - arr.push(val); - return arr; -} - -function getConfigPath(options) { - var configPath = options.config; - - if(!configPath) { - if(fs.existsSync('./config.json')) { - configPath = './config.json'; - } - else if(fs.existsSync('./config.js')) { - configPath = './config.js'; - } - else { - console.error('Build failed; unable to find config file.'); - process.exit(1); - } - } - - return configPath; -} - -program - .version(pkg.version) - .description(pkg.description) - .usage('[command] [options]'); - - -program - .command('build') - .description('Builds a style dictionary package from the current directory.') - .option('-c, --config ', 'set config path. defaults to ./config.json') - .option('-p, --platform [platform]', 'only build specific platforms. Must be defined in the config', collect, []) - .action(styleDictionaryBuild); - -program - .command('clean') - .description('Removes files specified in the config of the style dictionary package of the current directory.') - .option('-c, --config ', 'set config path. defaults to ./config.json') - .option('-p, --platform [platform]', 'only clean specific platform(s). Must be defined in the config', collect, []) - .action(styleDictionaryClean); - -program - .command('init ') - .description('Generates a starter style dictionary') - .action(function(type){ - var types = ['basic', 'complete']; - if (types.indexOf(type) < 0) { - console.error('Please supply 1 type of project from: ' + types.join(', ')); - process.exit(1); - } - - console.log('Copying starter files...\n'); - fs.copySync(path.join(__dirname, '..', 'examples', type), process.cwd()); - console.log('Source style dictionary starter files created!\n'); - console.log('Running `style-dictionary build` for the first time to generate build artifacts.\n'); - styleDictionaryBuild(); - }); - -// error on unknown commands -program.on('command:*', function () { - console.error('Invalid command: %s\nSee --help for a list of available commands.', process.argv.slice(2).join(' ')); - process.exit(1); -}); - -function styleDictionaryBuild(options) { - options = options || {}; - var configPath = getConfigPath(options); - - // Create a style dictionary object with the config - var styleDictionary = StyleDictionary.extend( configPath ); - - if (options.platform && options.platform.length > 0) { - options.platform.forEach(function(platform) { - styleDictionary.buildPlatform( platform ); - }); - } else { - styleDictionary.buildAllPlatforms(); - } -} - -function styleDictionaryClean(options) { - options = options || {}; - var configPath = getConfigPath(options); - - // Create a style dictionary object with the config - var styleDictionary = StyleDictionary.extend( configPath ); - - if (options.platform && options.platform.length > 0) { - options.platform.forEach(function(platform) { - styleDictionary.cleanPlatform( platform ); - }); - } else { - styleDictionary.cleanAllPlatforms(); - } -} - -program.parse(process.argv); - -// show help on no command -if (!process.argv.slice(2).length) { - program.outputHelp(); -} diff --git a/bin/style-dictionary.js b/bin/style-dictionary.js new file mode 100755 index 000000000..92c2a2ebd --- /dev/null +++ b/bin/style-dictionary.js @@ -0,0 +1,152 @@ +#!/usr/bin/env node + +'use strict'; + +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import node_fs from 'node:fs'; +import JSON5 from 'json5'; +import program from 'commander'; +// usually also node:fs in this context, but can be customized by user +import { fs } from 'style-dictionary/fs'; +import StyleDictionary from 'style-dictionary'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const pkg = JSON5.parse(node_fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); + +function collect(val, arr) { + arr.push(val); + return arr; +} + +function getConfigPath(options) { + let configPath = options.config; + + if (!configPath) { + if (fs.existsSync('./config.json')) { + configPath = './config.json'; + } else if (fs.existsSync('./config.js')) { + configPath = './config.js'; + } else { + console.error('Build failed; unable to find config file.'); + process.exit(1); + } + } + + return configPath; +} + +program.version(pkg.version).description(pkg.description).usage('[command] [options]'); + +program + .command('build') + .description('Builds a style dictionary package from the current directory.') + .option('-c, --config ', 'set config path. defaults to ./config.json') + .option( + '-v, --verbose', + 'enable verbose logging for reference errors, token collisions and filtered tokens with outputReferences', + ) + .option('-n, --no-warn', 'disable all warnings, only success logs and fatal errors shown') + .option('-s, --silent', 'silence all logging, except for fatal errors') + .option( + '-p, --platform [platform]', + 'only build specific platforms. Must be defined in the config', + collect, + [], + ) + .action(styleDictionaryBuild); + +program + .command('clean') + .description( + 'Removes files specified in the config of the style dictionary package of the current directory.', + ) + .option('-c, --config ', 'set config path. defaults to ./config.json') + .option( + '-v, --verbose', + 'enable verbose logging for reference errors, token collisions and filtered tokens with outputReferences', + ) + .option('-n, --no-warn', 'disable all warnings, only success logs and fatal errors shown') + .option('-s, --silent', 'silence all logging, except for fatal errors') + .option( + '-p, --platform [platform]', + 'only clean specific platform(s). Must be defined in the config', + collect, + [], + ) + .action(styleDictionaryClean); + +program + .command('init ') + .description('Generates a starter style dictionary') + .action(function (type) { + const types = ['basic', 'complete']; + if (types.indexOf(type) < 0) { + console.error('Please supply 1 type of project from: ' + types.join(', ')); + process.exit(1); + } + /* eslint-disable no-console */ + console.log('Copying starter files...\n'); + node_fs.cpSync(path.join(__dirname, '..', 'examples', type), process.cwd(), { + recursive: true, + }); + console.log('Source style dictionary starter files created!\n'); + console.log( + 'Running `style-dictionary build` for the first time to generate build artifacts.\n', + ); + /* eslint-disable no-console */ + styleDictionaryBuild(); + }); + +// error on unknown commands +program.on('command:*', function () { + console.error( + 'Invalid command: %s\nSee --help for a list of available commands.', + process.argv.slice(2).join(' '), + ); + process.exit(1); +}); + +function getSD(configPath, options) { + let verbosity; + let warnings; + if (options.verbose || options.silent) { + verbosity = options.verbose ? 'verbose' : 'silent'; + } + if (options.warn === false) { + warnings = 'disabled'; + } + return new StyleDictionary(configPath, { verbosity, warnings }); +} + +async function styleDictionaryBuild(options) { + options = options || {}; + const configPath = getConfigPath(options); + const sd = getSD(configPath, options); + + if (options.platform && options.platform.length > 0) { + return Promise.all(options.platforms.map((platform) => sd.buildPlatform(platform))); + } else { + return sd.buildAllPlatforms(); + } +} + +async function styleDictionaryClean(options) { + options = options || {}; + const configPath = getConfigPath(options); + const sd = getSD(configPath, options); + + if (options.platform && options.platform.length > 0) { + return Promise.all(options.platforms.map((platform) => sd.cleanPlatform(platform))); + } else { + return sd.cleanAllPlatforms(); + } +} + +program.parse(process.argv); + +// show help on no command +if (!process.argv.slice(2).length) { + program.outputHelp(); +} diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 736129b4b..000000000 --- a/docs/README.md +++ /dev/null @@ -1,56 +0,0 @@ -[What's new in Style Dictionary 3.0!](version_3.md) - -Style Dictionary logo - -[![npm version](https://img.shields.io/npm/v/style-dictionary.svg?style=flat-square)](https://badge.fury.io/js/style-dictionary) -![license](https://img.shields.io/npm/l/style-dictionary.svg?style=flat-square) -[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md#submitting-pull-requests) -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/amzn/style-dictionary/Test?style=flat-square)](https://github.com/amzn/style-dictionary/actions/workflows/test.yml) -[![downloads](https://img.shields.io/npm/dm/style-dictionary.svg?style=flat-square)](https://www.npmjs.com/package/style-dictionary) - -# Style Dictionary -> *Style once, use everywhere.* - -A Style Dictionary is a system that allows you to define styles once, in a way for any platform or language to consume. A single place to create and edit your styles, and a single command exports these rules to all the places you need them - iOS, Android, CSS, JS, HTML, sketch files, style documentation, etc. It is available as a [CLI](using_the_cli.md) through npm, but can also be used like any normal [npm module](using_the_npm_module.md) if you want to [extend](extending.md) its functionality. - -When you are managing user experiences, it can be quite challenging to keep styles consistent and synchronized across multiple development platforms and devices. At the same time, designers, developers, PMs and others must be able to have consistent and up-to-date style documentation to enable effective work and communication. Even then, mistakes inevitably happen and the design may not be implemented accurately. Style Dictionary solves this by automatically generating style definitions across all platforms from a single source - removing roadblocks, errors, and inefficiencies across your workflow. - -## Watch the Demo on Youtube -[![Watch the video](assets/fake_player.png)](http://youtu.be/1HREvonfqhY) - -## Experiment in the playground -Try the browser-based Style Dictionary playground: [https://www.style-dictionary-play.dev/](https://www.style-dictionary-play.dev/), built by the folks at [\RIOTS](https://divriots.com/). - -## Examples -[See examples of Style Dictionary here](examples.md) - -## The Basics -__A style dictionary consists of:__ -1. [Design tokens](tokens.md), organized in JSON, JSONC, JSON5, or JS files -1. Static assets (e.g. fonts, icons, images, sounds, etc.), organized into folders -1. [Configuration](config.md), defining the [transformation](transforms.md) and [formatting](formats.md) of the tokens and assets for each output platform - -__What a style dictionary does:__ -1. Transforms design tokens and assets into platform specific deliverables -1. Creates human readable artifacts (e.g. documentation, design libraries, etc) - -__Things you can build with a style dictionary:__ -1. Styling files for any platform -1. Images and graphics -1. Sketch files -1. Documentation website -1. _Literally anything you want styles or style data in_ - -**The value of using Style Dictionary to build all of these is that they are all consistent and up to date.** - -The Style Dictionary framework is fully extensible and modular. You can create any type of file from a style dictionary. If there is a new language, platform, or file type you need, you can easily [extend](extending.md) the style dictionary framework to create the necessary files. - - -## Contributing - -Please help make this framework better. For more information take a look at [CONTRIBUTING.md](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) - - -## License - -[Apache 2.0](https://github.com/amzn/style-dictionary/blob/main/LICENSE) diff --git a/docs/_coverpage.md b/docs/_coverpage.md deleted file mode 100644 index 00aae4947..000000000 --- a/docs/_coverpage.md +++ /dev/null @@ -1,14 +0,0 @@ -![logo](assets/logo.png) - -# Style Dictionary - -> Style once, use everywhere. - -**Style Dictionary** is a build system that allows you to define styles once, in a way for any platform or language to consume. A single place to create and edit your styles, and a single command exports these rules to all the places you need them - iOS, Android, CSS, JS, HTML, sketch files, style documentation, or anything you can think of. It is available as a CLI through npm, but can also be used like any normal node module if you want to extend its functionality. - -[GitHub](https://github.com/amzn/style-dictionary) -[Get Started](README.md) - -[See what's new in 3.0!](version_3.md) - -![color](#D9F8F5) diff --git a/docs/_sidebar.md b/docs/_sidebar.md deleted file mode 100644 index 3a7677e86..000000000 --- a/docs/_sidebar.md +++ /dev/null @@ -1,21 +0,0 @@ -- Getting started - - [Overview](README.md) - - [What's new in 3.0](version_3.md) - - [Quick Start](quick_start.md) - - [Examples](examples.md) - - [Config](config.md) - - [Tokens](tokens.md) - - [Package structure](package_structure.md) - - [Extending](extending.md) - -- Reference - - [Architecture](architecture.md) - - [Using the CLI](using_the_cli.md) - - [Using the NPM Module](using_the_npm_module.md) - - [API](api.md) - - [Parsers](parsers.md) - - [Transforms](transforms.md) - - [Transform groups](transform_groups.md) - - [Formats](formats.md) - - [Templates](templates.md) - - [Actions](actions.md) diff --git a/docs/api.md b/docs/api.md deleted file mode 100644 index 709032849..000000000 --- a/docs/api.md +++ /dev/null @@ -1,387 +0,0 @@ - -# API - -### buildAllPlatforms -> StyleDictionary.buildAllPlatforms() ⇒ [style-dictionary](#module_style-dictionary) - - - - -The only top-level method that needs to be called -to build the Style Dictionary. - -**Example** -```js -const StyleDictionary = require('style-dictionary').extend('config.json'); -StyleDictionary.buildAllPlatforms(); -``` - -* * * - -### buildPlatform -> StyleDictionary.buildPlatform(platform) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Takes a platform and performs all transforms to -the tokens object (non-mutative) then -builds all the files and performs any actions. This is useful if you only want to -build the artifacts of one platform to speed up the build process. - -This method is also used internally in [buildAllPlatforms](#buildAllPlatforms) to -build each platform defined in the config. - - -| Param | Type | Description | -| --- | --- | --- | -| platform | String | Name of the platform you want to build. | - -**Example** -```js -StyleDictionary.buildPlatform('web'); -``` -```bash -$ style-dictionary build --platform web -``` - -* * * - -### cleanAllPlatforms -> StyleDictionary.cleanAllPlatforms() ⇒ [style-dictionary](#module_style-dictionary) - - - - -Does the reverse of [buildAllPlatforms](#buildAllPlatforms) by -performing a clean on each platform. This removes all the files -defined in the platform and calls the undo method on any actions. - - -* * * - -### cleanPlatform -> StyleDictionary.cleanPlatform(platform) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Takes a platform and performs all transforms to -the tokens object (non-mutative) then -cleans all the files and performs the undo method of any [actions](actions.md). - - -| Param | Type | -| --- | --- | -| platform | String | - - -* * * - -### exportPlatform -> StyleDictionary.exportPlatform(platform) ⇒ Object - - - - -Exports a tokens object with applied -platform transforms. - -This is useful if you want to use a style -dictionary in JS build tools like webpack. - - -| Param | Type | Description | -| --- | --- | --- | -| platform | String | The platform to be exported. Must be defined on the style dictionary. | - - -* * * - -### extend -> StyleDictionary.extend(config) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Create a Style Dictionary - - -| Param | Type | Description | -| --- | --- | --- | -| config | [Config](#Config) | Configuration options to build your style dictionary. If you pass a string, it will be used as a path to a JSON config file. You can also pass an object with the configuration. | - -**Example** -```js -const StyleDictionary = require('style-dictionary').extend('config.json'); - -const StyleDictionary = require('style-dictionary').extend({ - source: ['tokens/*.json'], - platforms: { - scss: { - transformGroup: 'scss', - buildPath: 'build/', - files: [{ - destination: 'variables.scss', - format: 'scss/variables' - }] - } - // ... - } -}); -``` - -* * * - -### registerAction -> StyleDictionary.registerAction(action) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Adds a custom action to Style Dictionary. Custom -actions can do whatever you need, such as: copying files, -base64'ing files, running other build scripts, etc. -After you register a custom action, you then use that -action in a platform your config.json - -You can perform operations on files generated by the style dictionary -as actions run after these files are generated. -Actions are run sequentially, if you write synchronous code then -it will block other actions, or if you use asynchronous code like Promises -it will not block. - - -| Param | Type | Description | -| --- | --- | --- | -| action | Object | | -| action.name | String | The name of the action | -| action.do | function | The action in the form of a function. | -| [action.undo] | function | A function that undoes the action. | - -**Example** -```js -StyleDictionary.registerAction({ - name: 'copy_assets', - do: function(dictionary, config) { - console.log('Copying assets directory'); - fs.copySync('assets', config.buildPath + 'assets'); - }, - undo: function(dictionary, config) { - console.log('Cleaning assets directory'); - fs.removeSync(config.buildPath + 'assets'); - } -}); -``` - -* * * - -### registerFileHeader -> StyleDictionary.registerFileHeader(options) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Add a custom file header to the style dictionary. File headers are used in -formats to display some information about how the file was built in a comment. - - -| Param | Type | Description | -| --- | --- | --- | -| options | Object | | -| options.name | String | Name of the format to be referenced in your config.json | -| options.fileHeader | function | Function that returns an array of strings, which will be mapped to comment lines. It takes a single argument which is the default message array. See [file headers](formats.md#file-headers) for more information. | - -**Example** -```js -StyleDictionary.registerFileHeader({ - name: 'myCustomHeader', - fileHeader: function(defaultMessage) { - return [ - ...defaultMessage, - `hello, world!` - ]; - } -}) -``` - -* * * - -### registerFilter -> StyleDictionary.registerFilter(filter) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Add a custom filter to the style dictionary - - -| Param | Type | Description | -| --- | --- | --- | -| filter | Object | | -| filter.name | String | Name of the filter to be referenced in your config.json | -| filter.matcher | function | Matcher function, return boolean if the token should be included. | - -**Example** -```js -StyleDictionary.registerFilter({ - name: 'isColor', - matcher: function(token) { - return token.attributes.category === 'color'; - } -}) -``` - -* * * - -### registerFormat -> StyleDictionary.registerFormat(format) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Add a custom format to the style dictionary - - -| Param | Type | Description | -| --- | --- | --- | -| format | Object | | -| format.name | String | Name of the format to be referenced in your config.json | -| format.formatter | function | Function to perform the format. Takes a single argument. See [creating custom formats](formats.md#creating-formats) Must return a string, which is then written to a file. | - -**Example** -```js -StyleDictionary.registerFormat({ - name: 'json', - formatter: function({dictionary, platform, options, file}) { - return JSON.stringify(dictionary.tokens, null, 2); - } -}) -``` - -* * * - -### registerParser -> StyleDictionary.registerParser(pattern, parse) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Adds a custom parser to parse style dictionary files - - -| Param | Type | Description | -| --- | --- | --- | -| pattern | Regex | A file path regular expression to match which files this parser should be be used on. This is similar to how webpack loaders work. `/\.json$/` will match any file ending in '.json', for example. | -| parse | function | Function to parse the file contents. Takes 1 argument, which is an object with 2 attributes: contents wich is the string of the file contents and filePath. The function should return a plain Javascript object. | - -**Example** -```js -StyleDictionary.registerParser({ - pattern: /\.json$/, - parse: ({contents, filePath}) => { - return JSON.parse(contents); - } -}) -``` - -* * * - -### registerTemplate -> ~~StyleDictionary.registerTemplate(template) ⇒ [style-dictionary](#module_style-dictionary)~~ - - - - -***Deprecated*** - -Add a custom template to the Style Dictionary - - -| Param | Type | Description | -| --- | --- | --- | -| template | Object | | -| template.name | String | The name of your template. You will refer to this in your config.json file. | -| template.template | String | Path to your lodash template | - -**Example** -```js -StyleDictionary.registerTemplate({ - name: 'Swift/colors', - template: __dirname + '/templates/swift/colors.template' -}); -``` - -* * * - -### registerTransform -> StyleDictionary.registerTransform(transform) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Add a custom transform to the Style Dictionary -Transforms can manipulate a token's name, value, or attributes - - -| Param | Type | Description | -| --- | --- | --- | -| transform | Object | Transform object | -| transform.type | String | Type of transform, can be: name, attribute, or value | -| transform.name | String | Name of the transformer (used by transformGroup to call a list of transforms). | -| transform.transitive | Boolean | If the value transform should be applied transitively, i.e. should be applied to referenced values as well as absolute values. | -| [transform.matcher] | function | Matcher function, return boolean if transform should be applied. If you omit the matcher function, it will match all tokens. | -| transform.transformer | function | Modifies a design token object. The transformer function will receive the token and the platform configuration as its arguments. The transformer function should return a string for name transforms, an object for attribute transforms, and same type of value for a value transform. | - -**Example** -```js -StyleDictionary.registerTransform({ - name: 'time/seconds', - type: 'value', - matcher: function(token) { - return token.attributes.category === 'time'; - }, - transformer: function(token) { - // Note the use of prop.original.value, - // before any transforms are performed, the build system - // clones the original token to the 'original' attribute. - return (parseInt(token.original.value) / 1000).toString() + 's'; - } -}); -``` - -* * * - -### registerTransformGroup -> StyleDictionary.registerTransformGroup(transformGroup) ⇒ [style-dictionary](#module_style-dictionary) - - - - -Add a custom transformGroup to the Style Dictionary, which is a -group of transforms. - - -| Param | Type | Description | -| --- | --- | --- | -| transformGroup | Object | | -| transformGroup.name | String | Name of the transform group that will be referenced in config.json | -| transformGroup.transforms | Array.<String> | Array of strings that reference the name of transforms to be applied in order. Transforms must be defined and match the name or there will be an error at build time. | - -**Example** -```js -StyleDictionary.registerTransformGroup({ - name: 'Swift', - transforms: [ - 'attribute/cti', - 'size/pt', - 'name/cti' - ] -}); -``` - -* * * - diff --git a/docs/architecture.md b/docs/architecture.md deleted file mode 100644 index 28bad20e6..000000000 --- a/docs/architecture.md +++ /dev/null @@ -1,45 +0,0 @@ -# Architecture - -This is how Style Dictionary works under the hood. - -![build structure](assets/build-diagram.png) - -Let's take a closer look into each of these steps. - -## 1. Parse the config - -Style Dictionary is a configuration based framework, you tell it what to do in a configuration file. Style Dictionary first parses this [configuration](config.md) to know what to do. - -## 2. Find all token files - -In your [config](config.md) file can define `include` and `source`, which are arrays of file path globs. These tell Style Dictionary where to find your token files. You can have them anywhere and in any folder structure as long as you tell Style Dictionary where to find them. - -If there are [custom parsers](parsers.md) defined, Style Dictionary will run those on files the parsers match. - -## 3. Deep merge token files - -Style Dictionary takes all the files it found and performs a deep merge. This allows you to split your token files in any way you like, without worrying about accidentally overriding groups of tokens. This gives Style Dictionary a single, complete token object to work from. - -## 4. Iterate over the platforms - -For each platform defined in your [config](config.md), Style Dictionary will do a few steps to get it ready to be consumed on that platform. You don't need to worry about one platform affecting another because everything that happens in a platform is non-destructive. - -## 4a. Transform the tokens - -Style Dictionary now traverses over the whole token object and looks for design tokens. It does this by looking for anything with a `value` key. When it comes across a design token, it then performs all the [transforms](transforms.md) defined in your [config](config.md) in order. - -Value transforms, transforms that modify a token's value, are skipped if the token references another token. Starting in 3.0, you can define a [transitive transform](transforms.md#transitive-transforms) that will transform a value that references another token after that reference has been resolved. - -## 4b. Resolve aliases / references to other values - -After all the tokens have been transformed, it then does another pass over the token object looking for aliases, which look like `"{size.font.base.value}"`. When it finds these, it then replaces the reference with the transformed value. Because Style Dictionary merges all token files into a single object, aliases can be in any token file and still work. - -## 4c. Format the tokens into files - -Now all the design tokens are ready to be written to a file. Style Dictionary takes the whole transformed and resolved token object and for each file defined in the platform it [formats](formats.md) the token object and write the output to a file. Internally, Style Dictionary creates a flat array of all the design tokens it finds in addition to the token object. This is how you can output a flat SCSS variables file. - -## 4d. Run actions - -[Actions](actions.md) are custom code that run in a platform after the files are generated. They are useful for things like copying assets to specific build directories or generating images. - -After Style Dictionary does steps 4a-4d for each platform, you will have all your output files that are ready to consume in each platform and codebase. diff --git a/docs/assets/styles.css b/docs/assets/styles.css deleted file mode 100644 index fa97f2d2c..000000000 --- a/docs/assets/styles.css +++ /dev/null @@ -1,430 +0,0 @@ -:root { - --theme-color: #1FC5BF; - --theme-color-light: #99EBE2; - --theme-color-dark: #00B3AC; - --theme-color-secondary: #6A5096; - --theme-color-secondary-dark: #3F1C77; - --theme-color-secondary-light: #C4B2E1; - - --text-color-base: #2E2E46; - --text-color-secondary: #646473; - --text-color-tertiary: #81818E; -} - - -::selection { - background: var(--theme-color-light); -} - -body { - font-size: 100%; - line-height: 1.5; - font-family: 'Source Sans Pro','Open Sans','Helvetica Neue',Arial,sans-serif; - color: var(--text-color-base); -} - -* { - text-decoration: none !important; -} - -a { - transition: all 0.3s linear; -} - -div.search { - border-bottom: 2px solid #787881; - border: none; - background-color: var(--theme-color-secondary-light); - padding: 0; -} - -.sidebar .search input { - background: none; - background-color: rgba(255,255,255,0.5); - padding: 1rem; - transition: background-color 0.3s ease; -} - -.sidebar .search input:focus { - background-color: rgba(255,255,255,1); -} - -aside.sidebar { - border: none; - background-color: var(--theme-color-secondary); - color: #fff; -} - -.sidebar ul li a { - color: rgba(255,255,255,0.8); - color: var(--theme-color-light); - font-size: 1rem; -} - -.sidebar ul li.active>a { - border-width: 0.1rem; -} - -.sidebar ul li a:hover { - text-decoration: none; - color: rgba(255,255,255,1); -} - -.sidebar .sidebar-nav ul li.active>a { - color: #fff; - border-right: 0.2rem solid var(--theme-color-secondary-light,#29D0CA); -} - -.search .results-panel.show { - background-color: #05827E; - background-color: #fff; - color: #000; -} - -.sidebar .search .matching-post { - padding: 0; - border-bottom: 0.2rem solid #E4E4E6; -} - -.sidebar .search .matching-post:first-child { - border-top: 0.2rem solid #E4E4E6; -} - -.search a { - padding: 1rem; - display: block; - transition: background-color 0.3s ease; -} - -.search a:hover { - color: var(--theme-color-dark); -} - -.search p.empty { - margin: 0; - padding: 1rem; - background-color: #F1F1F2; -} - -.sidebar > h1 { - font-size: 2rem; -} - -.sidebar-logo { - display: block; - width: 4rem; - vertical-align: bottom; - line-height: 1.6; - height: 4rem; - margin: 0 auto; -} - -body .sidebar-toggle { - background: none; - bottom: 0; - left: 0; - cursor: pointer; - padding: 1rem; -} - -body .sidebar-toggle-button { - position: relative; - width: 1.5rem; - height: 1.5rem; -} - -body .sidebar-toggle span { - transition: all 0.3s linear; - background-color: var(--theme-color); - height: 0.25rem; - width: 1.5rem; - position: absolute; - left: 0; - margin: 0; - transform-origin: 0; -} - -body.close .sidebar-toggle span { - transform-origin: center; -} - -body .sidebar-toggle span:nth-child(1) { top:0; } -body .sidebar-toggle span:nth-child(2) { top:0.65rem; } -body .sidebar-toggle span:nth-child(3) { top:1.25rem; } - -.sidebar-toggle .sidebar-toggle-button:hover { opacity: 1; } - -.sidebar-toggle:hover span:nth-child(1) { transform: rotate(45deg); width: 1.75rem; } -.sidebar-toggle:hover span:nth-child(2) { opacity: 0; } -.sidebar-toggle:hover span:nth-child(3) { transform: rotate(-45deg); width: 1.75rem; } - -.close .sidebar-toggle:hover span:nth-child(1) { transform:rotate(0); width:1.5rem; top:0.65rem; } -.close .sidebar-toggle:hover span:nth-child(2) { opacity: 1; transform:rotate(90deg); } -.close .sidebar-toggle:hover span:nth-child(3) { transform:rotate(0); width:1.5rem; top:0.65rem; } - -th { - text-align: left; -} - -.markdown-section blockquote { - margin: 1em 0; -} - -.markdown-section em, -.markdown-section blockquote { - color: var(--text-color-tertiary); -} - -.cover-main img { - max-width: 10rem; - max-height: 10rem; -} - -section.cover p { - line-height: inherit; -} - -section.cover .cover-main a { - font-weight: 600; -} - -section.cover .cover-main a::before { - display: none; -} - -section.cover .cover-main blockquote { - font-style: italic; - color: #868C91; -} - -section.cover.show div.cover-main > p a { - border-style: solid; - border-radius: 2rem; - box-sizing: border-box; - display: inline-block; - font-size: 1.05rem; - letter-spacing: .1rem; - margin: .5rem 1rem; - padding: .75em 2rem; - text-decoration: none; - transition: all .15s ease; - - border-width: 0.2rem; - color: var(--theme-color-secondary); - border-color: var(--theme-color-secondary); -} - -section.cover.show div.cover-main>p a:last-child { - background-color: var(--theme-color-secondary); - border-color: var(--theme-color-secondary); - color: #fff; -} - -section.cover.show div.cover-main>p a:hover { - color: var(--theme-color-secondary-dark); - border-color: var(--theme-color-secondary-dark); - opacity: 1; -} - -section.cover.show div.cover-main>p a:last-child:hover { - background-color: var(--theme-color-secondary-dark); - border-color: var(--theme-color-secondary-dark); - color: #fff; - opacity: 1; -} - -.anchor { - position: relative; -} - -.anchor::before { - content: '\1F449'; - position: absolute; - top: 0; - left: -1.25em; - opacity: 0; - font-size: 0.875em; -} - -.anchor:hover::before { - opacity: 1; -} - -section.cover .cover-main { - margin: 20vh 20vw; -} - -.app-name-link { - white-space: nowrap; -} - -.app-sub-sidebar li:before { - display: none; -} - -.markdown-section pre, -.markdown-section pre > code { - background-color: #2E2E46; - color: rgba(255,255,255,0.75); - font-size: 1em; - line-height: 1.5; -} - -.markdown-section code { - display: inline-block; - font-family: 'Source Code Pro', monospace; -} - -.markdown-section pre { - padding: 2rem; -} - -.markdown-section pre > code { - padding: 0; -} - -.markdown-section hr { - width: 25%; - border-bottom: 5px solid #F1F1F2; -} - -.token.punctuation { - color: #585967; -} - -.token.comment, -.token.block-comment, -.token.prolog, -.token.doctype, -.token.cdata{color:#999999;} -.token.property, -.token.number, -.token.function-name, -.token.constant, -.token.symbol, -.token.deleted{color:#5a9bcf;}.token.boolean{color:#ff8b50;}.token.tag{color:#fc929e;}.token.string{color:#8dc891;}.token.punctuation{color:#5FB3B3;} -.token.selector, -.token.char, -.token.builtin, -.token.inserted{color:#D8DEE9;}.token.function{color:#79b6f2;} -.token.operator, -.token.entity, -.token.url, -.token.variable{color:#d7deea;}.token.attr-value{color:#8dc891;}.token.keyword{color:#c5a5c5;} - -.lang-scss .token.variable { - color: #8dc891; -} - -.markdown-section ol, .markdown-section p, .markdown-section ul { - line-height: inherit; -} - -.markdown-section code { - color: inherit; - border-radius: 0; - font-size: 0.9em; - padding: 6px 10px; - /* color: #111; */ -} - -.markdown-section table { - display: table; -} - -.markdown-section table tr { - border-width: 0.2rem 0; - border-style: solid; - border-color: #F1F1F2; -} - -.markdown-section table tr:nth-child(2n) { - background-color: transparent; -} - -.markdown-section table td, -.markdown-section table th { - border: none; - padding: 1.5rem 0.5rem; - text-align: left; -} - -.markdown-section table td p { - margin: 0; -} - -.markdown-section a { - text-decoration: none; - border-bottom: 0.1rem solid var(--theme-color-light); - transition: all 0.3s ease; -} - -.markdown-section a:hover { - border-color: var(--theme-color); - color: var(--theme-color-dark); -} - -.alert { - padding: 2rem; - border: 0.1rem solid var(--theme-color-secondary-light); -} - - -/* Badges */ -.markdown-section > p:first-child > a { - border: none; -} - -.docsify-copy-code-button { - background: var(--theme-color); -} - -.sidebar::-webkit-scrollbar { - width:0; -} - -@media screen and (max-width: 768px) { - section.cover { - height: auto; - } - section.cover .cover-main { - margin: 0 5vw; - } - .cover-main img { - max-width: 100px; - max-height: 100px; - } - - body .sidebar-toggle { background-color: #fff; } - body.close .sidebar-toggle { - background-color: transparent; - padding: 1rem; - } - - .sidebar-toggle:hover span:nth-child(1) { transform:rotate(0); width:1.5rem; top:0.65rem; } - .sidebar-toggle:hover span:nth-child(2) { opacity: 1; transform:rotate(90deg); transform-origin: center; } - .sidebar-toggle:hover span:nth-child(3) { transform:rotate(0); width:1.5rem; top:0.65rem; } - - .close .sidebar-toggle:hover span:nth-child(1) { transform: rotate(45deg); width: 1.75rem; } - .close .sidebar-toggle:hover span:nth-child(2) { opacity: 0; } - .close .sidebar-toggle:hover span:nth-child(3) { transform: rotate(-45deg); width: 1.75rem; } -} - -@media screen and (min-width: 769px) { - .markdown-section { - max-width: 75rem; - padding: 1rem 3rem; - } -} - -@media (min-width: 1200px) { - body { - font-size: 112.5%; - } -} - -@media (min-width: 1400px) { - body { - font-size: 125%; - } -} diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs new file mode 100644 index 000000000..9aeef1e34 --- /dev/null +++ b/docs/astro.config.mjs @@ -0,0 +1,29 @@ +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; +import { remarkPlayground } from './src/remark-playground'; +import starlightConfig from './starlight-config'; + +// https://astro.build/config +export default defineConfig({ + integrations: [starlight(starlightConfig)], + markdown: { + remarkPlugins: [remarkPlayground], + }, + site: 'https://style-dictionary-v4.netlify.app', + vite: { + force: true, + server: { + force: true, + }, + optimizeDeps: { + // coz we're doing monkeypatching deps quite often at this stage of this POC + force: true, + // due to WASM bindings + exclude: ['@rollup/browser'], + esbuildOptions: { + // to support top-level-await + target: 'esnext', + }, + }, + }, +}); diff --git a/docs/config.md b/docs/config.md deleted file mode 100644 index 93a8f2cd3..000000000 --- a/docs/config.md +++ /dev/null @@ -1,178 +0,0 @@ -# Configuration - -Style dictionaries are configuration driven. Your configuration lets Style Dictionary know: - -1. Where to find your [design tokens](tokens.md) -1. How to transform and format them to generate output files - -Here is an example configuration: - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "scss": { - "transformGroup": "scss", - "prefix": "sd", - "buildPath": "build/scss/", - "files": [{ - "destination": "_variables.scss", - "format": "scss/variables" - }], - "actions": ["copy_assets"] - }, - "android": { - "transforms": ["attribute/cti", "name/cti/snake", "color/hex", "size/remToSp", "size/remToDp"], - "buildPath": "build/android/src/main/res/values/", - "files": [{ - "destination": "style_dictionary_colors.xml", - "format": "android/colors" - }] - } - } -} -``` - -## Configuration file formats - -Style Dictionary supports configuration files in these file formats: - -* JSON -* JSONC -* JSON5 -* Javascript (CommonJS) - -Here is an example using a CommonJS module for configuration: - -```javascript -// config.js -module.exports = { - source: [`tokens/**/*.json`], - // If you don't want to call the registerTransform method a bunch of times - // you can override the whole transform object directly. This works because - // the .extend method copies everything in the config - // to itself, allowing you to override things. It's also doing a deep merge - // to protect from accidentally overriding nested attributes. - transform: { - // Now we can use the transform 'myTransform' below - myTransform: { - type: 'name', - transformer: (token) => token.path.join('_').toUpperCase() - } - }, - // Same with formats, you can now write them directly to this config - // object. The name of the format is the key. - format: { - myFormat: ({dictionary, platform}) => { - return dictionary.allTokens.map(token => `${token.name}: ${token.value}`).join('\n'); - } - }, - platforms: { - // ... - } -} -``` - -Some interesting things you can do in a CommonJS file that you cannot do in a JSON file: - -* Add custom transforms, formats, filters, actions, and parsers -* Programmatically generate your configuration - - ----- - - -## Using configuration files - -By default, the Style Dictionary [CLI](using_the_cli.md) looks for a `config.json` or `config.js` file in the root of your package. - -```json5 -// package.json -"scripts": { - "build": "style-dictionary build" -} -``` - -You can also specify a custom location when you use the [CLI](using_the_cli.md) with the `--config` parameter. - -```json5 -// package.json -"scripts": { - "build": "style-dictionary build --config ./sd.config.js" -} -``` - -## Using in Node - -You can also use Style Dictionary as an [npm module](using_the_npm_module.md) and further customize how Style Dictionary is run, for example running Style Dictionary multiple times with different configurations. To do this you would create a Javascript file that imports the Style Dictionary npm module and calls the [`.extend`](api.md#extend) and [`.buildAllPlatforms`](api.md#buildallplatforms) functions. - -```javascript -// build.js -const StyleDictionary = require('style-dictionary'); - -const myStyleDictionary = StyleDictionary.extend({ - // configuration -}); - -myStyleDictionary.buildAllPlatforms(); - -// You can also extend Style Dictionary multiple times: -const myOtherStyleDictionary = myStyleDictionary.extend({ - // new configuration -}); - -myOtherStyleDictionary.buildAllPlatforms(); -``` - -You would then change your npm script or CLI command to run that file with Node: - -```json5 -// package.json -"scripts": { - "build": "node build.js" -} -``` - ----- - - -## Attributes - -| Attribute | Type | Description | -| :--- | :--- | :--- | -| transform | Object (optional) | Custom [transforms](transforms.md) you can include inline rather than using `.registerTransform`. The keys in this object will be the transform's name, the value should be an object with `type` -| format | Object (optional) | Custom [formats](formats.md) you can include inline in the configuration rather than using `.registerFormat`. The keys in this object will be for format's name and value should be the formatter function. -| action | Object (optional) | Custom inline [actions](actions.md). The keys in this object will be the action's name and the value should be an object containing `do` and `undo` methods. -| parsers | Array[Parser] (optional) | Custom [file parsers](parsers.md) to run on input files | -| include | Array[String] (optional) | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files that contain default styles. Style Dictionary uses this as a base collection of design tokens. The tokens found using the "source" attribute will overwrite tokens found using include. | -| source | Array[String] | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files. Style Dictionary will do a deep merge of all of the token files, allowing you to organize your files however you want. | -| tokens | Object | The tokens object is a way to include inline design tokens as opposed to using the `source` and `include` arrays. -| properties | Object | **DEPRECATED** The properties object has been renamed to `tokens`. Using the `properties` object will still work for backwards compatibility. -| platforms | Object[Platform] | An object containing [platform](#platform) config objects that describe how the Style Dictionary should build for that platform. You can add any arbitrary attributes on this object that will get passed to formats and actions (more on these in a bit). This is useful for things like build paths, name prefixes, variable names, etc. - -### Platform - -A platform is a build target that tells Style Dictionary how to properly transform and format your design tokens for output to a specific platform. You can have as many platforms as you need and you can name them anything, there are no restrictions. - -| Attribute | Type | Description | -| :--- | :--- | :--- | -| transforms | Array[String] (optional) | An array of [transforms](transforms.md) to be performed on the design tokens. These will transform the tokens in a non-destructive way, allowing each platform to transform the tokens. Transforms to apply sequentially to all tokens. Can be a built-in one or you can create your own. -| transformGroup | String (optional) | A string that maps to an array of transforms. This makes it easier to reference transforms by grouping them together. You must either define this or [transforms](transforms.md). -| buildPath | String (optional) | Base path to build the files, must end with a trailing slash. -| options | Object (optional) | Options that apply to all files in the platform, for example `outputReferences` and `showFileHeader` -| files | Array[File] (optional) | [Files](#file) to be generated for this platform. -| actions | Array[String] (optional) | [Actions](actions.md) to be performed after the files are built for that platform. Actions can be any arbitrary code you want to run like copying files, generating assets, etc. You can use pre-defined actions or create custom actions. - -### File - -A File configuration object represents a single output file. The `options` object on the file configuration will take precedence over the `options` object defined at the platform level. - -| Attribute | Type | Description | -| :--- | :--- | :--- | -| destination | String | Location to build the file, will be appended to the buildPath. | -| format | String (optional) | [Format](formats.md) used to generate the file. Can be a built-in one or you can create your own via [registerFormat](api.md#registerformat). | -| filter | String/Function/Object (optional) | A function, string or object used to filter the tokens that will be included in the file. If a function is provided, each design token will be passed to the function and the result (true or false) will determine whether the design token is included. If an object is provided, each design token will be matched against the object using a partial deep comparison. If a match is found, the design token is included. If a string is passed, is considered a custom filter registered via [registerFilter](api.md#registerfilter) | -| options | Object (optional) | A set of extra options associated with the file. Includes `showFileHeader` and `outputReferences`. | -| options.showFileHeader | Boolean | If the generated file should have a comment at the top about being generated. The default fileHeader comment has "Do not edit + Timestamp". By default is "true". | -| options.fileHeader | String/Function (optional) | A custom fileHeader that can be either a name of a registered file header (string) or an inline [fileHeader](formats.md#customfileheader) function. -| options.outputReferences | Boolean | If the file should keep token [references](formats.md#references-in-output-files). By default this is "false". diff --git a/docs/expressive-code-plugin-language-class.ts b/docs/expressive-code-plugin-language-class.ts new file mode 100644 index 000000000..81b4aa17f --- /dev/null +++ b/docs/expressive-code-plugin-language-class.ts @@ -0,0 +1,31 @@ +import type { ExpressiveCodePlugin } from '@expressive-code/core'; + +export function pluginLanguageClass(): ExpressiveCodePlugin { + return { + name: 'PluginLanguageClass', + hooks: { + postprocessRenderedBlock: (opts) => { + if (opts.codeBlock.language === 'mermaid') { + const pre = opts.renderData.blockAst.children.find( + (child) => child.type === 'element' && child.tagName === 'pre', + ); + if (pre && pre.type === 'element') { + // add the mermaid language class so mermaid can pick this up + pre.properties = { + class: `${opts.codeBlock.language} hidden`, + }; + + // replace the AST that expressive code has made and put back the simple text + // otherwise mermaid gets confused by all of the generated HTML syntax + pre.children = [ + { + value: opts.codeBlock.code, + type: 'text', + }, + ]; + } + } + }, + }, + }; +} diff --git a/docs/extending.md b/docs/extending.md deleted file mode 100644 index 361902c85..000000000 --- a/docs/extending.md +++ /dev/null @@ -1,52 +0,0 @@ -# Extending - -There is a straightforward way to extend Style Dictionary to meet your needs - since we don't know exactly how everyone will want to use style dictionaries in their project, we created custom transforms and formats as a manner to add your desired functionality. - -## Extension Functions in the API -* [registerTransform](api.md#registertransform) -* [registerTransformGroup](api.md#registertransformgroup) -* [registerFilter](api.md#registerfilter) -* [registerFormat](api.md#registerformat) -* [registerTemplate](api.md#registertemplate) (deprecated) -* [registerAction](api.md#registeraction) -* [registerParser](api.md#registerparser) - -## Extension Examples -Importing a configuration, defining a new `time/seconds` transform, and building the style dictionary. - -```javascript -const StyleDictionary = require('style-dictionary').extend('config.json'); - -StyleDictionary.registerTransform({ - name: 'time/seconds', - type: 'value', - matcher: function(token) { - return token.attributes.category === 'time'; - }, - transformer: function(token) { - return (parseInt(token.original.value) / 1000).toString() + 's'; - } -}); - -StyleDictionary.buildAllPlatforms(); -``` - - -Export your extended style dictionary as a node module (without building) if you need other projects to depend on it. - -```javascript -// package a -const StyleDictionary = require('style-dictionary').extend('config.json'); -StyleDictionary.registerTransform({ - name: 'name/uppercase', - type: 'name', - transformer: function(token) { - return token.path.join('_').toUpperCase(); - } -}); - -module.exports = StyleDictionary; - -// package b -const StyleDictionary = require('package-a'); -``` diff --git a/docs/formats.md b/docs/formats.md deleted file mode 100644 index 5d922ce78..000000000 --- a/docs/formats.md +++ /dev/null @@ -1,1844 +0,0 @@ - -# Formats - -Formats define the output of your created files. For example, to use your styles in CSS -you use the `css/variables` format. This will create a CSS file containing the variables from -your style dictionary. - -## Using formats - -You use formats in your config file under platforms > [platform] > files > [file] > format - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "css": { - "transformGroup": "css", - "files": [ - { - "format": "css/variables", - "destination": "variables.css" - } - ] - } - } -} -``` - -There is an extensive (but not exhaustive) list of [included formats](#pre-defined-formats) available in Style Dictionary. - -## Format configuration - -Formats can take configuration to make them more flexible. This allows you to re-use the same format multiple times with different configurations or to allow the format to use data not defined in the tokens themselves. To configure a format, add extra attributes on the file object in your configuration like the following: - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "scss": { - "transformGroup": "scss", - "files": [{ - "destination": "map.scss", - "format": "scss/map-deep", - "mapName": "my-tokens" - }] - } - } -} -``` - -In this example we are adding the `mapName` configuration to the `scss/map-deep` format. This will change the name of the SCSS map in the output. Not all formats have the configuration options; format configuration is defined by the format itself. To see the configuration options of a format, take a look at the documentation of the [specific format](#pre-defined-formats) - -## Filtering tokens - -A special file configuration is `filter`, which will filter the tokens before they get to the format. This allows you to re-use the same format to generate multiple files with different sets of tokens. Filtering tokens works by adding a `filter` attribute on the file object, where `filter` is: - -* An object which gets passed to [Lodash's filter method](https://lodash.com/docs/4.17.14#filter). -* A string that references the name of a registered filter, using the [`registerFilter`](api.md#registerfilter) method -* A function that takes a token and returns a boolean if the token should be included (true) or excluded (false). **This is only available if you are defining your configuration in Javascript.** - -```javascript -{ - "destination": "destination", - "format": "myCustomFormat", - "filter": "myCustomFilter", // a named filter defined with .registerFilter - "filter": function(token) {}, // an inline function - "filter": {} // an object pass to lodash's filter method -} -``` - -The design token that is passed to the filter function has already been [transformed](transforms.md) and has [default metadata](tokens.md?id=default-design-token-metadata) added by Style Dictionary. - -## References in output files - -Starting with version 3.0, some formats can keep the references in the output. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens: - -```json5 -// tokens.json -{ - "color": { - "red": { "value": "#ff0000" }, - "danger": { "value": "{color.red.value}" }, - "error": { "value": "{color.danger.value}" } - } -} -``` - -With this configuration: - -```json5 -// config.json -{ - "source": ["tokens.json"] - "platforms": { - "css": { - "transformGroup": "css", - "files": [{ - "destination": "variables.css", - "format": "css/variables", - "options": { - // Look here 👇 - "outputReferences": true - } - }] - } - } -} -``` - -This would be the output: - -```css -:root { - --color-red: #ff0000; - --color-danger: var(--color-red); - --color-error: var(--color-danger); -} -``` - -The css variables file now keeps the references you have in your Style Dictionary! This is useful for outputting themeable and dynamic code. - -Without `outputReferences: true` Style Dictionary would resolve all references and the output would be: - -```css -:root { - --color-red: #ff0000; - --color-danger: #ff0000; - --color-error: #ff0000; -} -``` - -Not all formats use the `outputReferences` option because that file format might not support it (like JSON for example). The current list of formats that handle `outputReferences`: - -* [css/variables](#cssvariables) -* [scss/variables](#scssvariables) -* [less/variables](#lessvariables) -* [android/resources](#androidresources) -* [compose/object](#composeobject) -* [ios-swift/class.swift](#ios-swiftclassswift) -* [flutter/class.dart](#flutterclassdart) - -You can create custom formats that output references as well. See the [Custom format with output references](#custom-format-with-output-references) section. - -## File headers - -By default Style Dictionary adds a file header comment in the top of files built using built-in formats like this: - -```js -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT -``` - -You can remove these comments with the option: `showFileHeader: false` if you do not want them in your generated files. You can also create your own file header or extend the default one. This could be useful if you want to put a version number or hash of the source files rather than a timestamp. - -Custom file headers can be added the same way you would add a custom format, either by using the [`registerFileHeader`](api.md#registerfileheader) function or adding the fileHeader object directly in the Style Dictionary [configuration](config.md). Your custom file header can be used in built-in formats as well as custom formats. To use a custom file header in a custom format see the [`fileHeader`](formats.md#fileheader) format helper method. - -```js -const StyleDictionary = require('style-dictionary'); -StyleDictionary.registerFileHeader({ - name: 'myCustomHeader', - fileHeader: (defaultMessage) => { - // defaultMessage are the 2 lines above that appear in the default file header - // you can use this to add a message before or after the default message 👇 - - // the fileHeader function should return an array of strings - // which will be formatted in the proper comment style for a given format - return [ - ...defaultMessage, - `hello?`, - `is it me you're looking for?`, - ] - } -}); -``` - -Then you can use your custom file header in a file similar to a custom format: - -```json5 -{ - source: ['tokens/**/*.json'], - platforms: { - css: { - transformGroup: 'css', - files: [{ - destination: 'variables.css', - format: 'css/variables', - options: { - fileHeader: 'myCustomHeader' - } - }] - } - } -} -``` - -Which should output a file that will start like this: - -```css -/** - * Do not edit directly - * Generated on Thu, 18 Mar 2021 21:30:47 GMT - * hello? - * is it me you're looking for? - */ -``` - -For an in-depth example see the [custom-file-header](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) example. - -## Custom formats - -You can create custom formats using the [`registerFormat`](api.md#registerformat) function or by directly including them in your [configuration](config.md). A format has a name and a formatter function, which takes an object as the argument and should return a string which is then written to a file. - -### formatter -> format.formatter(args) ⇒ String - -The formatter function that is called when Style Dictionary builds files. - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParamTypeDescription
argsObject

A single argument to support named parameters and destructuring.

-
args.dictionaryObject

The transformed and resolved dictionary object

-
args.dictionary.tokensObject

Object structure of the tokens that has been transformed and references resolved.

-
args.dictionary.allTokensArray

Flattened array of all the tokens. This makes it easy to output a list, like a list of SCSS variables.

-
args.dictionary.usesReferencefunction

Use this function to see if a token's value uses a reference. This is the same function style dictionary uses internally to detect a reference.

-
args.dictionary.getReferencesfunction

Use this function to get the tokens that it references. You can use this to output a reference in your custom format. For example: dictionary.getReferences(token.original.value) // returns an array of the referenced token objects

-
args.platformObject

The platform configuration this format is being called in.

-
args.fileObject

The file configuration this format is being called in.

-
args.optionsObject

Merged options object that combines platform level configuration and file level configuration. File options take precedence.

-
- -**Example** -```js -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({dictionary, platform, options, file}) { - return JSON.stringify(dictionary.tokens, null, 2); - } -}) -``` - -* * * - - -To use your custom format, you call it by name in the file configuration object: - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "css": { - "options": { - "showFileHeader": true - }, - "transformGroup": "css", - "files": [{ - "destination": "destination", - "format": "myCustomFormat", - "options": { - "showFileHeader": false - } - }] - } - } -} -``` - -It is recommended for any configuration needed for your custom format to use the `options` object. Style Dictionary will merge platform and file options so that in your Style Dictionary configuration you can specify options at a platform or file level. In the configuration above, the `options` object passed to the formatter would have `showFileHeader: false`. - -
-Note: to support legacy ways of defining custom formats, this in the formatter function is bound to the file object and when Style Dictionary calls the formatter function it passes 3 arguments: dictionary, platform, and file. Starting in 3.0 all data the formatter needs is in the first argument as shown above to make it easier to grab the arguments by name rather than by position. We recommend not using this or the positional arguments in your custom format. -
- -## Custom format with output references - -To take advantage of outputting references in your custom formats there are 2 helper methods in the `dictionary` argument passed to your formatter function: `usesReference(value)` and `getReferences(value)`. Here is an example using those: - -```javascript -StyleDictionary.registerFormat({ - name: `es6WithReferences`, - formatter: function({dictionary}) { - return dictionary.allTokens.map(token => { - let value = JSON.stringify(token.value); - // the `dictionary` object now has `usesReference()` and - // `getReferences()` methods. `usesReference()` will return true if - // the value has a reference in it. `getReferences()` will return - // an array of references to the whole tokens so that you can access their - // names or any other attributes. - if (dictionary.usesReference(token.original.value)) { - // Note: make sure to use `token.original.value` because - // `token.value` is already resolved at this point. - const refs = dictionary.getReferences(token.original.value); - refs.forEach(ref => { - value = value.replace(ref.value, function() { - return `${ref.name}`; - }); - }); - } - return `export const ${token.name} = ${value};` - }).join(`\n`) - } -}); -``` - -## Custom format helpers - -We provide some helper methods we use internally in some of the built-in formats to make building custom formats a bit easier. They are accessible at `StyleDictionary.formatHelpers`. - -```javascript -const StyleDictionary = require('style-dictionary'); - -const { fileHeader, formattedVariables } = StyleDictionary.formatHelpers; - -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({dictionary, file, options}) { - const { outputReferences } = options; - return fileHeader({file}) + - ':root {\n' + - formattedVariables({format: 'css', dictionary, outputReferences}) + - '\n}\n'; - } -}); -``` - -Here are the available format helper methods: - -### createPropertyFormatter -> formatHelpers.createPropertyFormatter(options) ⇒ function - -Creates a function that can be used to format a property. This can be useful -to use as the function on `dictionary.allTokens.map`. The formatting -is configurable either by supplying a `format` option or a `formatting` object -which uses: prefix, indentation, separator, suffix, and commentStyle. - - - - - - - - - - - - - - - - - - - - - - - -
ParamTypeDescription
optionsObject
options.outputReferencesBoolean

Whether or not to output references. You will want to pass this from the options object sent to the formatter function.

-
options.outputReferenceFallbacksBoolean

Whether or not to output css variable fallback values when using output references. You will want to pass this from the options object sent to the formatter function.

-
options.dictionaryDictionary

The dictionary object sent to the formatter function

-
options.formatString

Available formats are: 'css', 'sass', 'less', and 'stylus'. If you want to customize the format and can't use one of those predefined formats, use the formatting option

-
options.formattingObject

Custom formatting properties that define parts of a declaration line in code. The configurable strings are: prefix, indentation, separator, suffix, and commentStyle. Those are used to generate a line like this: ${indentation}${prefix}${prop.name}${separator} ${prop.value}${suffix}

-
options.themeableBoolean

[false] - Whether tokens should default to being themeable.

-
- -**Example** -```javascript -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary, options }) { - const { outputReferences } = options; - const formatProperty = createPropertyFormatter({ - outputReferences, - dictionary, - format: 'css' - }); - return dictionary.allTokens.map(formatProperty).join('\n'); - } -}); -``` - -* * * - -### fileHeader -> formatHelpers.fileHeader(options) ⇒ String - -This is for creating the comment at the top of generated files with the generated at date. -It will use the custom file header if defined on the configuration, or use the -default file header. - - - - - - - - - - - - - - - - - -
ParamTypeDescription
optionsObject
options.fileFile

The file object that is passed to the formatter.

-
options.commentStyleString

The only options are 'short' and 'xml', which will use the // or <!-- --> style comments respectively. Anything else will use /* style comments.

-
options.formattingObject

Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer.

-
- -**Example** -```js -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary, file }) { - return fileHeader({file, commentStyle: 'short'}) + - dictionary.allTokens.map(token => `${token.name} = ${token.value}`) - .join('\n'); - } -}); -``` - -* * * - -### formattedVariables -> formatHelpers.formattedVariables(options) ⇒ String - -This is used to create lists of variables like Sass variables or CSS custom properties - - - - - - - - - - - - - - - - - - - - - -
ParamTypeDescription
optionsObject
options.formatString

What type of variables to output. Options are: css, sass, less, and stylus

-
options.dictionaryObject

The dictionary object that gets passed to the formatter method.

-
options.outputReferencesBoolean

Whether or not to output references

-
options.formattingObject

Custom formatting properties that define parts of a declaration line in code. This will get passed to formatHelpers.createPropertyFormatter and used for the lineSeparator between lines of code.

-
options.themeableBoolean

[false] - Whether tokens should default to being themeable.

-
- -**Example** -```js -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary, options }) { - return formattedVariables({ - format: 'less', - dictionary, - outputReferences: options.outputReferences - }); - } -}); -``` - -* * * - -### getTypeScriptType -> formatHelpers.getTypeScriptType(value, options) ⇒ String - -Given some value, returns a basic valid TypeScript type for that value. -Supports numbers, strings, booleans, arrays and objects of any of those types. - -**Returns**: String - A valid name for a TypeScript type. - - - - - - - - - - - - - - -
ParamTypeDescription
value*

A value to check the type of.

-
optionsObject
options.outputStringLiteralsBoolean

Whether or not to output literal types for string values

-
- -**Example** -```javascript -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary, options }) { - return dictionary.allProperties.map(function(prop) { - var to_ret_prop = 'export const ' + prop.name + ' : ' + getTypeScriptType(prop.value) + ';'; - if (prop.comment) - to_ret_prop = to_ret_prop.concat(' // ' + prop.comment); - return to_ret_prop; - }).join('\n'); - } -}); -``` - -* * * - -### iconsWithPrefix -> formatHelpers.iconsWithPrefix(prefix, allTokens, options) ⇒ String - -This is used to create CSS (and CSS pre-processor) lists of icons. It assumes you are -using an icon font and creates helper classes with the :before pseudo-selector to add -a unicode character. -__You probably don't need this.__ - - - - - - - - - - - - - - - -
ParamTypeDescription
prefixString

Character to prefix variable names, like '$' for Sass

-
allTokensArray.<Token>

allTokens array on the dictionary object passed to the formatter function.

-
optionsObject

options object passed to the formatter function.

-
- -**Example** -```js -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary, options }) { - return iconsWithPrefix('$', dictionary.allTokens, options); - } -}); -``` - -* * * - -### minifyDictionary -> formatHelpers.minifyDictionary(obj) ⇒ Object - -Outputs an object stripping out everything except values - - - - - - - - - - - -
ParamTypeDescription
objObject

The object to minify. You will most likely pass dictionary.tokens to it.

-
- -**Example** -```js -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary }) { - return JSON.stringify(minifyDictionary(dictionary.tokens)); - } -}); -``` - -* * * - -### setComposeObjectProperties -> formatHelpers.setComposeObjectProperties(options) ⇒ Object - -Outputs an object for compose format configurations. Sets import. - - - - - - - - - - - -
ParamTypeDescription
optionsObject

The options object declared at configuration

-
- - -* * * - -### setSwiftFileProperties -> formatHelpers.setSwiftFileProperties(options, objectType, transformGroup) ⇒ Object - -Outputs an object with swift format configurations. Sets import, object type and access control. - - - - - - - - - - - - - - - -
ParamTypeDescription
optionsObject

The options object declared at configuration

-
objectTypeString

The type of the object in the final file. Could be a class, enum, struct, etc.

-
transformGroupString

The transformGroup of the file, so it can be applied proper import

-
- - -* * * - -### sortByName -> formatHelpers.sortByName(a, b) ⇒ Integer - -A sorting function to be used when iterating over `dictionary.allTokens` in -a format. - -**Returns**: Integer - -1 or 1 depending on which element should come first based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort - - - - - - - - - - - - -
ParamTypeDescription
a*

first element for comparison

-
b*

second element for comparison

-
- -**Example** -```javascript -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({ dictionary, options }) { - return dictionary.allTokens.sort(sortByName) - .map(token => `${token.name} = ${token.value}`) - .join('\n'); - } -}); -``` - -* * * - -### sortByReference -> formatHelpers.sortByReference(dictionary) ⇒ function - -A function that returns a sorting function to be used with Array.sort that -will sort the allTokens array based on references. This is to make sure -if you use output references that you never use a reference before it is -defined. - - - - - - - - - - - -
ParamType
dictionaryDictionary
- -**Example** -```javascript -dictionary.allTokens.sort(sortByReference(dictionary)) -``` - -* * * - - -## Using a template / templating engine to create a format - -Formatters are functions and created easily with most templating engines. Formats can be built using templates if there is a lot of boilerplate code to insert (e.g. ObjectiveC files). If the output consists of only the values (e.g. a flat SCSS variables file), writing a formatter function directly may be easier. - -Any templating language can work as long as there is a node module for it. All you need to do is register a format that calls your template and returns a string. - -Here is a quick example for Lodash. - -```js -const styleDictionary = require('style-dictionary').extend('config.json'); -const _ = require('lodash'); - -const template = _.template( fs.readFileSync('templates/myFormat.template') ); - -styleDictionary.registerFormat({ - name: 'my/format', - formatter: template -}); - -// format: 'my/format' is now available for use... -``` - -And another example for Handlebars. - -```js -const styleDictionary = require('style-dictionary').extend('config.json'); -const Handlebars = require('handlebars'); - -const template = Handlebars.compile( fs.readFileSync('templates/MyTemplate.hbs').toString() ); - -styleDictionary.registerFormat({ - name: 'my/format', - formatter: function({dictionary, platform}) { - return template({ - tokens: dictionary.tokens, - options: platform - }); - } -}); - -// format: 'my/format' is now available for use... -``` - ----- - -## Pre-defined Formats - -These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/formats.js) - -Want a format? [You can request it here](https://github.com/amzn/style-dictionary/issues). - -You created a format and think it should be included? [Send us a PR](https://github.com/amzn/style-dictionary/pulls). - - -### css/variables - - -Creates a CSS file with variable definitions based on the style dictionary - - - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
[options.selector]string

Override the root css selector

-
- -**Example** -```css -:root { - --color-background-base: #f0f0f0; - --color-background-alt: #eeeeee; -} -``` - -* * * - -### scss/map-flat - - -Creates a SCSS file with a flat map based on the style dictionary - -Name the map by adding a 'mapName' attribute on the file object in your config. - -**Example** -```scss -$tokens: ( - 'color-background-base': #f0f0f0; - 'color-background-alt': #eeeeee; -) -``` - -* * * - -### scss/map-deep - - -Creates a SCSS file with a deep map based on the style dictionary. - -Name the map by adding a 'mapName' attribute on the file object in your config. - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
[options.themeable]Booleantrue

Whether or not tokens should default to being themeable, if not otherwise specified per token.

-
- -**Example** -```scss -$color-background-base: #f0f0f0 !default; -$color-background-alt: #eeeeee !default; - -$tokens: { - 'color': ( - 'background': ( - 'base': $color-background-base, - 'alt': $color-background-alt - ) - ) -) -``` - -* * * - -### scss/variables - - -Creates a SCSS file with variable definitions based on the style dictionary. - -Add `!default` to any variable by setting a `themeable: true` attribute in the token's definition. - - - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
[options.themeable]Booleanfalse

Whether or not tokens should default to being themeable, if not otherwise specified per token.

-
- -**Example** -```scss -$color-background-base: #f0f0f0; -$color-background-alt: #eeeeee !default; -``` - -* * * - -### scss/icons - - -Creates a SCSS file with variable definitions and helper classes for icons - -**Example** -```scss -$content-icon-email: '\E001'; -.icon.email:before { content:$content-icon-email; } -``` - -* * * - -### less/variables - - -Creates a LESS file with variable definitions based on the style dictionary - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```less -@color-background-base: #f0f0f0; -@color-background-alt: #eeeeee; -``` - -* * * - -### less/icons - - -Creates a LESS file with variable definitions and helper classes for icons - -**Example** -```less -@content-icon-email: '\E001'; -.icon.email:before { content:@content-icon-email; } -``` - -* * * - -### stylus/variables - - -Creates a Stylus file with variable definitions based on the style dictionary - -**Example** -```stylus -$color-background-base= #f0f0f0; -$color-background-alt= #eeeeee; -``` - -* * * - -### javascript/module - - -Creates a CommonJS module with the whole style dictionary - -**Example** -```js -module.exports = { - color: { - base: { - red: { - value: '#ff0000' - } - } - } -} -``` - -* * * - -### javascript/module-flat - - -Creates a CommonJS module with the whole style dictionary flattened to a single level. - -**Example** -```js -module.exports = { - "ColorBaseRed": "#ff0000" -} -``` - -* * * - -### javascript/object - - -Creates a JS file a global var that is a plain javascript object of the style dictionary. -Name the variable by adding a 'name' attribute on the file object in your config. - -**Example** -```js -var StyleDictionary = { - color: { - base: { - red: { - value: '#ff0000' - } - } - } -} -``` - -* * * - -### javascript/umd - - -Creates a [UMD](https://github.com/umdjs/umd) module of the style -dictionary. Name the module by adding a 'name' attribute on the file object -in your config. - -**Example** -```js -(function(root, factory) { - if (typeof module === "object" && module.exports) { - module.exports = factory(); - } else if (typeof exports === "object") { - exports["_styleDictionary"] = factory(); - } else if (typeof define === "function" && define.amd) { - define([], factory); - } else { - root["_styleDictionary"] = factory(); - } -}(this, function() { - return { - "color": { - "red": { - "value": "#FF0000" - } - } - }; -})) -``` - -* * * - -### javascript/es6 - - -Creates a ES6 module of the style dictionary. - -```json -{ - "platforms": { - "js": { - "transformGroup": "js", - "files": [ - { - "format": "javascript/es6", - "destination": "colors.js", - "filter": { - "attributes": { - "category": "color" - } - } - } - ] - } - } -} -``` - -**Example** -```js -export const ColorBackgroundBase = '#ffffff'; -export const ColorBackgroundAlt = '#fcfcfcfc'; -``` - -* * * - -### typescript/es6-declarations - - -Creates TypeScript declarations for ES6 modules - -```json -{ - "platforms": { - "ts": { - "transformGroup": "js", - "files": [ - { - "format": "javascript/es6", - "destination": "colors.js" - }, - { - "format": "typescript/es6-declarations", - "destination": "colors.d.ts" - } - ] - } - } -} -``` - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.outputStringLiterals]Booleanfalse

Whether or not to output literal types for string values

-
- -**Example** -```typescript -export const ColorBackgroundBase : string; -export const ColorBackgroundAlt : string; -``` - -* * * - -### typescript/module-declarations - - -Creates TypeScript declarations for CommonJS module - -```json -{ - "platforms": { - "ts": { - "transformGroup": "js", - "files": [ - { - "format": "javascript/module", - "destination": "colors.js" - }, - { - "format": "typescript/module-declarations", - "destination": "colors.d.ts" - } - ] - } - } -} -``` - -**Example** -```typescript -export default tokens; -declare interface DesignToken { value: string; name?: string; path?: string[]; comment?: string; attributes?: any; original?: any; } -declare const tokens: { - "color": { - "red": DesignToken - } -} -``` - -As you can see above example output this does not generate 100% accurate d.ts. -This is a compromise between of what style-dictionary can do to help and not bloating the library with rarely used dependencies. - -Thankfully you can extend style-dictionary very easily: - -```js -const JsonToTS = require('json-to-ts'); -StyleDictionaryPackage.registerFormat({ - name: 'typescript/accurate-module-declarations', - formatter: function({ dictionary }) { - return 'declare const root: RootObject\n' + - 'export default root\n' + - JsonToTS(dictionary.properties).join('\n'); - }, -}); -``` - -* * * - -### android/resources - - -Creates a [resource](https://developer.android.com/guide/topics/resources/providing-resources) xml file. It is recommended to use a filter with this format -as it is generally best practice in Android development to have resource files -organized by type (color, dimension, string, etc.). However, a resource file -with mixed resources will still work. - -This format will try to use the proper resource type for each token based on -the category (color => color, size => dimen, etc.). However if you want to -force a particular resource type you can provide a 'resourceType' attribute -on the file configuration. You can also provide a 'resourceMap' if you -don't use Style Dictionary's built-in CTI structure. - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```xml - - - #fffaf3f2 - #fff0cccc - 14sp -``` - -* * * - -### android/colors - - -Creates a color resource xml file with all the colors in your style dictionary. - -It is recommended to use the 'android/resources' format with a custom filter -instead of this format: - -```javascript -format: 'android/resources', -filter: { - attributes: { category: 'color' } -} -``` - -**Example** -```xml - - - #fffaf3f2 - #fff0cccc - #ffe19d9c -``` - -* * * - -### android/dimens - - -Creates a dimen resource xml file with all the sizes in your style dictionary. - -It is recommended to use the 'android/resources' format with a custom filter -instead of this format: - -```javascript -format: 'android/resources', -filter: { - attributes: { category: 'size' } -} -``` - -**Example** -```xml - - - 5.00dp - 10.00dp - 15.00dp -``` - -* * * - -### android/fontDimens - - -Creates a dimen resource xml file with all the font sizes in your style dictionary. - -It is recommended to use the 'android/resources' format with a custom filter -instead of this format: - -```javascript -format: 'android/resources', -filter: { - attributes: { category: 'size' } -} -``` - -**Example** -```xml - - - 10.00sp - 13.00sp - 15.00sp -``` - -* * * - -### android/integers - - -Creates a resource xml file with all the integers in your style dictionary. It filters your -design tokens by `token.attributes.category === 'time'` - -It is recommended to use the 'android/resources' format with a custom filter -instead of this format: - -```javascript -format: 'android/resources', -filter: { - attributes: { category: 'time' } -} -``` - -**Todo** - -- Update the filter on this. - -**Example** -```xml - - - 1000 - 2000 - 4000 -``` - -* * * - -### android/strings - - -Creates a resource xml file with all the strings in your style dictionary. Filters your -design tokens by `token.attributes.category === 'content'` - -It is recommended to use the 'android/resources' format with a custom filter -instead of this format: - -```javascript -format: 'android/resources', -filter: { - attributes: { category: 'content' } -} -``` - -**Example** -```xml - - - - - -``` - -* * * - -### compose/object - - -Creates a Kotlin file for Compose containing an object with a `val` for each property. - - - - - - - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
classNameString

The name of the generated Kotlin object

-
packageNameString

The package for the generated Kotlin object

-
optionsObject
[options.import]Array.<String>['androidx.compose.ui.graphics.Color', 'androidx.compose.ui.unit.*']

Modules to import. Can be a string or array of strings

-
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```kotlin -package com.example.tokens; - -import androidx.compose.ui.graphics.Color - -object StyleDictionary { - val colorBaseRed5 = Color(0xFFFAF3F2) -} -``` - -* * * - -### ios/macros - - -Creates an Objective-C header file with macros for design tokens - -**Example** -```objectivec -#import -#import - -#define ColorFontLink [UIColor colorWithRed:0.00f green:0.47f blue:0.80f alpha:1.00f] -#define SizeFontTiny 176.00f -``` - -* * * - -### ios/plist - - -Creates an Objective-C plist file - -**Todo** - -- Fix this template and add example and usage - - -* * * - -### ios/singleton.m - - -Creates an Objective-C implementation file of a style dictionary singleton class - -**Todo** - -- Add example and usage - - -* * * - -### ios/singleton.h - - -Creates an Objective-C header file of a style dictionary singleton class - -**Todo** - -- Add example and usage - - -* * * - -### ios/static.h - - -Creates an Objective-C header file of a static style dictionary class - -**Todo** - -- Add example and usage - - -* * * - -### ios/static.m - - -Creates an Objective-C implementation file of a static style dictionary class - -**Todo** - -- Add example and usage - - -* * * - -### ios/colors.h - - -Creates an Objective-C header file of a color class - -**Todo** - -- Add example and usage - - -* * * - -### ios/colors.m - - -Creates an Objective-C implementation file of a color class - -**Todo** - -- Add example and usage - - -* * * - -### ios/strings.h - - -Creates an Objective-C header file of strings - -**Todo** - -- Add example and usage - - -* * * - -### ios/strings.m - - -Creates an Objective-C implementation file of strings - -**Todo** - -- Add example and usage - - -* * * - -### ios-swift/class.swift - - -Creates a Swift implementation file of a class with values. It adds default `class` object type, `public` access control and `UIKit` import. - - - - - - - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.accessControl]Stringpublic

Level of access of the generated swift object

-
[options.import]Array.<String>UIKit

Modules to import. Can be a string or array of strings

-
[options.className]String

The name of the generated Swift class

-
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```swift -public class StyleDictionary { - public static let colorBackgroundDanger = UIColor(red: 1.000, green: 0.918, blue: 0.914, alpha: 1) -} -``` - -* * * - -### ios-swift/enum.swift - - -Creates a Swift implementation file of an enum with values. It adds default `enum` object type, `public` access control and `UIKit` import. - - - - - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.accessControl]Stringpublic

Level of access of the generated swift object

-
[options.import]Array.<String>UIKit

Modules to import. Can be a string or array of strings

-
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```swift -public enum StyleDictionary { - public static let colorBackgroundDanger = UIColor(red: 1.000, green: 0.918, blue: 0.914, alpha: 1) -} -``` - -* * * - -### ios-swift/any.swift - - -Creates a Swift implementation file of any given type with values. It has by default `class` object type, `public` access control and `UIKit` import. - -```javascript -format: 'ios-swift/any.swift', -import: ['UIKit', 'AnotherModule'], -objectType: 'struct', -accessControl: 'internal', -``` - - - - - - - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.accessControl]Stringpublic

Level of access of the generated swift object

-
[options.import]Array.<String>UIKit

Modules to import. Can be a string or array of strings

-
[options.objectType]Stringclass

The type of the generated Swift object

-
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```swift -import UIKit -import AnotherModule - -internal struct StyleDictionary { - internal static let colorBackgroundDanger = UIColor(red: 1.000, green: 0.918, blue: 0.914, alpha: 1) -} -``` - -* * * - -### css/fonts.css - - -Creates CSS file with @font-face declarations - -**Todo** - -- Add example and usage - - -* * * - -### json - - -Creates a JSON file of the style dictionary. - -**Example** -```json -{ - "color": { - "base": { - "red": { - "value": "#ff0000" - } - } - } -} -``` - -* * * - -### json/asset - - -Creates a JSON file of the assets defined in the style dictionary. - -**Example** -```js -{ - "asset": { - "image": { - "logo": { - "value": "assets/logo.png" - } - } - } -} -``` - -* * * - -### json/nested - - -Creates a JSON nested file of the style dictionary. - -**Example** -```json -{ - "color": { - "base": { - "red": "#ff0000" - } - } -} -``` - -* * * - -### json/flat - - -Creates a JSON flat file of the style dictionary. - -**Example** -```json -{ - "color-base-red": "#ff0000" -} -``` - -* * * - -### sketch/palette - - -Creates a sketchpalette file of all the base colors - -**Example** -```json -{ - "compatibleVersion": "1.0", - "pluginVersion": "1.1", - "colors": [ - "#ffffff", - "#ff0000", - "#fcfcfc" - ] -} -``` - -* * * - -### sketch/palette/v2 - - -Creates a sketchpalette file compatible with version 2 of -the sketchpalette plugin. To use this you should use the -'color/sketch' transform to get the correct value for the colors. - -**Example** -```json -{ - "compatibleVersion": "2.0", - "pluginVersion": "2.2", - "colors": [ - {name: "red", r: 1.0, g: 0.0, b: 0.0, a: 1.0}, - {name: "green", r: 0.0, g: 1.0, b: 0.0, a: 1.0}, - {name: "blue", r: 0.0, g: 0.0, b: 1.0, a: 1.0} - ] -} -``` - -* * * - -### flutter/class.dart - - -Creates a Dart implementation file of a class with values - - - - - - - - - - - - - - - -
ParamTypeDefaultDescription
optionsObject
[options.showFileHeader]Booleantrue

Whether or not to include a comment that has the build date

-
[options.outputReferences]Booleanfalse

Whether or not to keep references (a -> b -> c) in the output.

-
- -**Example** -```dart -import 'package:flutter/material.dart'; - -class StyleDictionary { - StyleDictionary._(); - - static const colorBrandPrimary = Color(0x00ff5fff); - static const sizeFontSizeMedium = 16.00; - static const contentFontFamily1 = "NewJune"; -``` - -* * * - - diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 39192fad6..000000000 --- a/docs/index.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - Style Dictionary - Style once, use everywhere. A build system for creating cross-platform styles. - - - - - - - - - -
- - - - - - - - - - - - - diff --git a/docs/package_structure.md b/docs/package_structure.md deleted file mode 100644 index 44e55990d..000000000 --- a/docs/package_structure.md +++ /dev/null @@ -1,33 +0,0 @@ -# Package Structure - -Style dictionaries are configuration driven. A style dictionary package must contain a configuration and reference a path to design token files. You can optionally include assets in your package. - -Here is a basic example of what a style dictionary package looks like. - -``` -├── config.json -├── tokens/ -│ ├── size/ -│ ├── font.json -│ ├── color/ -│ ├── font.json -│ ... -├── assets/ -│ ├── fonts/ -│ ├── images/ -``` - - -| Name | Description | -| :--- | :--- | -| config.json | This is where the [configuration](config.md) for the style dictionary lives, where you define what happens when Style Dictionary runs | -| design token files | [Design tokens](tokens.md) are saved as a collection of JSON or JS module files. You can put them wherever you like - the path to them should be in the `source` attribute on your `config.json` file. | -| assets (optional) | Assets can be included in your style dictionary package, allowing you to keep them in your style dictionary as a single source of truth. | - - -## Assets - -Assets are not required, but can be useful to include in your style dictionary. If you don't want to manage having assets like images, -vectors, font files, etc. in multiple locations, you can keep them in your style dictionary as a single source of truth. - -> Coming soon: how to generate image assets based on your style dictionary diff --git a/docs/parsers.md b/docs/parsers.md deleted file mode 100644 index 465b822d9..000000000 --- a/docs/parsers.md +++ /dev/null @@ -1,71 +0,0 @@ -# Parsers - -Starting in version 3.0, you can define custom parsers to parse design token files. This allows you to define your design token files in *any* language you like as long as you can write a parser for it. - -A custom parser matches design token files based on a file path regular expression. It will get the contents of a file as a string and should return an object of the data. - -Custom parsers can be used to keep design token files in other languages like YAML, but they can also be used to add extra metadata or modify the design tokens themselves before they get to Style Dictionary. For example, you could modify the token object based on its file path or programmatically generate tokens based on the data in certain files. - - ----- - - -## Parser structure - -A parser has 2 parts: a pattern which is a regular expression to match against a file path, and a parse function which takes the file path and contents of the file and is expected to return a function. - -```javascript -const myParser = { - pattern: /\.json$/, - parse: ({ filePath, contents }) => { - return JSON.parse(contents); - } -} -``` - - ----- - - -## Using parsers - -First you will need to tell Style Dictionary about your parser. You can do this in two ways: - -1. Using the `.registerParser` method -1. Inline in the [configuration](config.md) - -### .registerParser - -```javascript -const StyleDictionary = require('style-dictionary'); - -StyleDictionary.registerParser({ - pattern: /\.json$/, - parse: ({ filePath, contents }) => { - return JSON.parse(contents); - } -}); -``` - -### Inline - -```javascript -module.exports = { - parsers: [{ - pattern: /\.json$/, - parse: ({ filePath, contents }) => { - return JSON.parse(contents); - } - }], - // ... the rest of the configuration -} -``` - - ----- - - -## Parser examples - -* [More in-depth custom parser example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) -* [Using custom parsers to support YAML design token files](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) diff --git a/docs/public/demo-tokens.json b/docs/public/demo-tokens.json new file mode 100644 index 000000000..ffdbfa8c1 --- /dev/null +++ b/docs/public/demo-tokens.json @@ -0,0 +1,237 @@ +{ + "colors": { + "$type": "color", + "black": { + "$value": "#000000" + }, + "white": { + "$value": "#ffffff" + }, + "orange": { + "100": { + "$value": "#fffaf0" + }, + "200": { + "$value": "#feebc8" + }, + "300": { + "$value": "#fbd38d" + }, + "400": { + "$value": "#f6ad55" + }, + "500": { + "$value": "#ed8936" + }, + "600": { + "$value": "#dd6b20" + }, + "700": { + "$value": "#c05621" + }, + "800": { + "$value": "#9c4221" + }, + "900": { + "$value": "#7b341e" + } + } + }, + "dimensions": { + "$type": "dimension", + "0": { + "$value": "0px" + }, + "1": { + "$value": "4px" + }, + "2": { + "$value": "8px" + }, + "3": { + "$value": "12px" + }, + "4": { + "$value": "16px" + }, + "5": { + "$value": "20px" + }, + "6": { + "$value": "24px" + }, + "7": { + "$value": "28px" + }, + "8": { + "$value": "32px" + }, + "9": { + "$value": "36px" + }, + "10": { + "$value": "40px" + }, + "11": { + "$value": "44px" + }, + "12": { + "$value": "48px" + }, + "13": { + "$value": "52px" + }, + "14": { + "$value": "56px" + }, + "15": { + "$value": "60px" + }, + "max": { + "$value": "9999px" + } + }, + "text": { + "fonts": { + "$type": "fontFamily", + "serif": { + "$value": "Times New Roman, serif" + }, + "sans": { + "$value": "Open Sans, sans-serif" + } + }, + "weights": { + "$type": "fontWeight", + "light": { + "$value": "thin" + }, + "regular": { + "$value": "regular" + }, + "bold": { + "$value": "extra-bold" + } + }, + "lineHeights": { + "$type": "number", + "normal": { + "$value": 1.2 + }, + "large": { + "$value": 1.8 + } + }, + "typography": { + "$type": "typography", + "heading": { + "$value": { + "fontFamily": "{text.fonts.sans}", + "fontWeight": "{text.weights.bold}", + "fontSize": "{dimensions.7}", + "lineHeight": "{text.lineHeights.large}" + } + }, + "body": { + "$value": { + "fontFamily": "{text.fonts.serif}", + "fontWeight": "{text.weights.regular}", + "fontSize": "{dimensions.4}", + "lineHeight": "{text.lineHeights.normal}" + } + } + } + }, + "transitions": { + "$type": "transition", + "emphasis": { + "$value": { + "duration": "{transitions.durations.medium}", + "delay": "{transitions.durations.instant}", + "timingFunction": "{transitions.easingFunctions.accelerate}" + } + }, + "fade": { + "$value": { + "duration": "{transitions.durations.long}", + "delay": "{transitions.durations.instant}", + "timingFunction": "{transitions.easingFunctions.decelerate}" + } + }, + "easingFunctions": { + "$type": "cubicBezier", + "accelerate": { + "$value": [0.5, 0, 1, 1] + }, + "decelerate": { + "$value": [0, 0, 0.5, 1] + } + }, + "durations": { + "$type": "duration", + "instant": { + "$value": "0ms" + }, + "short": { + "$value": "100ms" + }, + "medium": { + "$value": "300ms" + }, + "long": { + "$value": "600ms" + } + } + }, + "borders": { + "$type": "border", + "heavy": { + "$value": { + "color": "{colors.black}", + "width": "{dimensions.1}", + "style": "{borders.styles.solid}" + } + }, + "wireframe": { + "$value": { + "color": "{colors.orange.600}", + "width": "{dimensions.2}", + "style": "{borders.styles.dashed}" + } + }, + "styles": { + "$type": "strokeStyle", + "solid": { + "$value": "solid" + }, + "dashed": { + "$value": { + "dashArray": ["0.5rem", "0.25rem"], + "lineCap": "round" + } + } + } + }, + "shadows": { + "$type": "shadow", + "sm": { + "$value": { + "color": "{colors.black}", + "offsetX": "{dimensions.0}", + "offsetY": "{dimensions.1}", + "blur": "{dimensions.3}" + } + }, + "lg": { + "$value": { + "color": "{colors.black}", + "offsetX": "{dimensions.0}", + "offsetY": "{dimensions.2}", + "blur": "{dimensions.4}" + } + }, + "multi": { + "$value": ["{shadows.sm}", "{shadows.lg}"] + } + } +} diff --git a/docs/assets/favicon.png b/docs/public/favicon.png similarity index 100% rename from docs/assets/favicon.png rename to docs/public/favicon.png diff --git a/docs/public/meta-img.png b/docs/public/meta-img.png new file mode 100644 index 000000000..e2af27d72 Binary files /dev/null and b/docs/public/meta-img.png differ diff --git a/docs/assets/build-diagram.png b/docs/src/assets/build-diagram.png similarity index 100% rename from docs/assets/build-diagram.png rename to docs/src/assets/build-diagram.png diff --git a/docs/assets/cti.png b/docs/src/assets/cti.png similarity index 100% rename from docs/assets/cti.png rename to docs/src/assets/cti.png diff --git a/docs/assets/fake_player.png b/docs/src/assets/fake_player.png similarity index 100% rename from docs/assets/fake_player.png rename to docs/src/assets/fake_player.png diff --git a/docs/src/assets/favicon.png b/docs/src/assets/favicon.png new file mode 100644 index 000000000..ca8c5ee4a Binary files /dev/null and b/docs/src/assets/favicon.png differ diff --git a/docs/src/assets/houston.webp b/docs/src/assets/houston.webp new file mode 100644 index 000000000..930c16497 Binary files /dev/null and b/docs/src/assets/houston.webp differ diff --git a/docs/assets/logo.png b/docs/src/assets/logo.png similarity index 100% rename from docs/assets/logo.png rename to docs/src/assets/logo.png diff --git a/docs/src/assets/meta-img.png b/docs/src/assets/meta-img.png new file mode 100644 index 000000000..e2af27d72 Binary files /dev/null and b/docs/src/assets/meta-img.png differ diff --git a/docs/assets/property-definitions.png b/docs/src/assets/property-definitions.png similarity index 100% rename from docs/assets/property-definitions.png rename to docs/src/assets/property-definitions.png diff --git a/docs/src/components/Head.astro b/docs/src/components/Head.astro new file mode 100644 index 000000000..5b699633d --- /dev/null +++ b/docs/src/components/Head.astro @@ -0,0 +1,8 @@ +--- +import Default from '@astrojs/starlight/components/Head.astro'; +import type { Props } from '@astrojs/starlight/props'; +--- + + + + \ No newline at end of file diff --git a/docs/src/components/sd-dtcg-convert.ts b/docs/src/components/sd-dtcg-convert.ts new file mode 100644 index 000000000..ad5e78d02 --- /dev/null +++ b/docs/src/components/sd-dtcg-convert.ts @@ -0,0 +1,65 @@ +import { LitElement, css, html } from 'lit'; +import { ref, createRef } from 'lit/directives/ref.js'; +import '@shoelace-style/shoelace/dist/components/button/button.js'; +import { convertJSONToDTCG, convertZIPToDTCG } from '../../../lib/utils/convertToDTCG.js'; +import { downloadJSON, downloadZIP } from '../../../lib/utils/downloadFile.js'; + +class SdDtcgConvert extends LitElement { + fileInputRef = createRef(); + + static get styles() { + return [ + css` + :host { + display: block; + } + `, + ]; + } + + render() { + return html` + Convert tokens to DTCG + + `; + } + + triggerUpload() { + const fileInput = this.fileInputRef.value; + if (fileInput) { + fileInput.dispatchEvent(new MouseEvent('click')); + } + } + + async upload(ev: Event) { + if (ev.target instanceof HTMLInputElement) { + const file = ev.target.files?.[0]; + if (file) { + const today = new Date(Date.now()); + const filename = `dtcg-tokens_${today.getFullYear()}-${today.getMonth()}-${( + '0' + today.getDate() + ).slice(-2)}`; + + if (file.type.includes('zip')) { + const zipBlob = await convertZIPToDTCG(file); + await downloadZIP(zipBlob, `${filename}.zip`); + } else if (file.type.includes('json')) { + const jsonBlob = await convertJSONToDTCG(file); + await downloadJSON(jsonBlob, `${filename}.json`); + } else { + throw new Error('Only ZIP and JSON type uploads are supported.'); + } + } + } + } +} + +customElements.define('sd-dtcg-convert', SdDtcgConvert); diff --git a/docs/src/components/sd-playground.ts b/docs/src/components/sd-playground.ts new file mode 100644 index 000000000..db8351944 --- /dev/null +++ b/docs/src/components/sd-playground.ts @@ -0,0 +1,471 @@ +import StyleDictionary from 'style-dictionary'; +import type { Config } from 'style-dictionary/types'; +import memfs from '@bundled-es-modules/memfs'; +import type { fs as VolumeType } from 'memfs'; +import { LitElement, html, css } from 'lit'; +import { posix as path } from 'path-unified'; +import '@shoelace-style/shoelace/dist/components/radio-button/radio-button.js'; +import '@shoelace-style/shoelace/dist/components/radio-group/radio-group.js'; +import '@shoelace-style/shoelace/dist/components/select/select.js'; +import '@shoelace-style/shoelace/dist/components/option/option.js'; +import { bundle } from '../utils/rollup-bundle.ts'; +import { changeLang, init, monaco } from '../monaco/monaco.ts'; +import { analyzeDependencies } from '../utils/analyzeDependencies.ts'; +import { downloadZIP } from '../../../lib/utils/downloadFile.js'; +import type SlRadioGroup from '@shoelace-style/shoelace/dist/components/radio-group/radio-group.js'; + +const { Volume } = memfs; + +const defaults = { + tokens: { + colors: { + red: { + value: '#ff0000', + type: 'color', + }, + }, + }, + config: { + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'vars.css', + format: 'css/variables', + }, + ], + }, + }, + }, + script: "import StyleDictionary from 'style-dictionary';", +}; + +const getLang = (lang: string) => { + const langMap = { + h: 'objective-c', + } as Record; + + let foundMonacoLanguage; + const langs = monaco?.languages?.getLanguages(); + if (langs) { + foundMonacoLanguage = langs.find((l) => l.extensions?.includes(`.${lang}`))?.id; + } + + return langMap[lang] ?? foundMonacoLanguage ?? lang; +}; + +declare type Files = 'tokens' | 'config' | 'script' | 'output'; +const files: Files[] = ['tokens', 'config', 'script', 'output']; + +export const registeredComponents: SdPlayground[] = []; + +class SdPlayground extends LitElement { + static get styles() { + return css` + sl-radio-group { + margin-bottom: 4px; + margin-top: 16px; + } + + .output-select::part(combobox) { + height: 28px; + min-height: 28px; + margin-left: 10px; + } + + /** screen-reader only CSS */ + sl-select::part(form-control-label) { + border: 0 !important; + clip: rect(1px, 1px, 1px, 1px) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + height: 1px !important; + margin: -1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; + } + + @media (max-width: 550px) { + ::part(button-group) { + display: block; + } + ::part(button-group__base) { + flex-direction: column; + } + + sl-radio-button[data-sl-button-group__button--first]::part(button) { + border-top-left-radius: var(--sl-input-border-radius-medium); + border-top-right-radius: var(--sl-input-border-radius-medium); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + sl-radio-button[data-sl-button-group__button--last]::part(button) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: var(--sl-input-border-radius-medium); + border-bottom-right-radius: var(--sl-input-border-radius-medium); + } + } + + sl-option::part(label) { + flex-grow: 0; + } + + sl-option::part(base) { + min-width: 100%; + } + + sl-option::part(base), + sl-select::part(listbox) { + width: max-content; + } + `; + } + + static get properties() { + return { + tokens: { + reflect: true, + type: String, + }, + config: { + reflect: true, + type: String, + }, + script: { + reflect: true, + type: String, + }, + outputFiles: { + state: true, + }, + defaultSelected: { + type: String, + attribute: 'default-selected', + reflect: true, + }, + }; + } + + get currentFile(): Files { + return this._currentFile; + } + + set currentFile(v: Files) { + this._currentFile = v; + this.fileSwitch(v); + this.updateComplete.then(() => { + const radio = this.shadowRoot?.querySelector( + `sl-radio-button[value="${v}"]`, + ) as HTMLInputElement; + radio.click(); + }); + } + + declare tokens: string; + declare config: string; + declare script: string; + declare output: string; + declare defaultSelected: Files; + declare outputFiles: string[]; + declare _currentFile: Files; + declare editor: any; + declare volume: typeof VolumeType; + declare hasInitialized: Promise; + declare hasInitializedResolve: (value: void) => void; + + constructor() { + super(); + this.tokens = '{}'; + this.config = '{}'; + this.script = '{}'; + this.output = '{}'; + this.defaultSelected = 'config'; + this.outputFiles = []; + this.editor = undefined; + this.hasInitialized = new Promise((resolve) => { + this.hasInitializedResolve = resolve; + }); + registeredComponents.push(this); + } + + connectedCallback() { + super.connectedCallback(); + this.init(); + } + + render() { + return html` + { + if ((ev.target as SlRadioGroup).value === 'eject') { + return; + } + this.currentFile = (ev.target as HTMLInputElement).value as Files; + }} + name="file-switch" + > + ${files.map( + (file) => html` + + ${file.slice(0, 1).toUpperCase()}${file.slice(1)} + ${file === 'output' + ? html` + { + ev.stopPropagation(); + this.changeOutputs((ev.target as HTMLSelectElement).value, true); + }} + > + ${this.outputFiles.map( + (file) => html` ${file} `, + )} + + ` + : html``} + + `, + )} + + + + + + + + + `; + } + + async init() { + await this.initMonaco(); + await this.initData(); + this.hasInitializedResolve(); + this.currentFile = this.defaultSelected; + } + + async initMonaco() { + await this.updateComplete; + const slotEl = this.shadowRoot?.querySelector('slot[name="monaco-editor"]') as HTMLSlotElement; + const editorElem = slotEl.assignedNodes()[0]; + if (editorElem) { + this.editor = await init(editorElem as HTMLDivElement); + this.editor._domElement.addEventListener('keydown', (ev: KeyboardEvent) => { + if (ev.key === 's' && (ev.ctrlKey || ev.metaKey)) { + ev.preventDefault(); + this.saveFile(); + } + }); + } + } + + async initData() { + const [, tokens] = await Promise.all([this.initScript(), this.initTokens()]); + const cfg = await this.initConfig(tokens); + this.runSD(cfg); + return cfg; + } + + async initScript() { + const scriptData = JSON.parse(this.script); + if (scriptData.value) { + const bundled = await bundle(scriptData.value); + const url = URL.createObjectURL( + new Blob([bundled], { + type: 'text/javascript', + }), + ); + await import(/* @vite-ignore */ url); + } + } + + async initTokens() { + let tokens = defaults.tokens; + const tokensData = JSON.parse(this.tokens); + if (tokensData.value) { + if (tokensData.lang === 'js') { + const bundled = await bundle(tokensData.value); + const url = URL.createObjectURL( + new Blob([bundled], { + type: 'text/javascript', + }), + ); + tokens = (await import(/* @vite-ignore */ url)).default; + } else { + tokens = JSON.parse(tokensData.value); + } + } + return tokens; + } + + async initConfig(tokens: Record) { + let sdConfig = { ...defaults.config, tokens }; + if (this.config) { + const configData = JSON.parse(this.config); + if (configData.lang === 'js') { + const bundled = await bundle(configData.value); + const url = URL.createObjectURL( + new Blob([bundled], { + type: 'text/javascript', + }), + ); + sdConfig = (await import(/* @vite-ignore */ url)).default; + } else if (configData.value) { + sdConfig = JSON.parse(configData.value); + } + sdConfig.tokens = sdConfig.tokens ?? tokens; + } + + return sdConfig as Config; + } + + getFileData(file: 'tokens' | 'config' | 'script' | 'output') { + const def = defaults[file as keyof typeof defaults]; + return { + lang: JSON.parse(this[file]).lang ?? (file === 'script' ? 'js' : 'json'), + value: + JSON.parse(this[file]).value ?? (file === 'script' ? def : JSON.stringify(def, null, 2)), + }; + } + + async fileSwitch(val: 'tokens' | 'config' | 'script' | 'output') { + await this.hasInitialized; + const data = this.getFileData(val); + this.editor.setValue(data.value); + await changeLang(getLang(data.lang), this.editor); + } + + async runSD(cfg: Config) { + try { + this.volume = new Volume(); + const sd = new StyleDictionary(cfg, { volume: this.volume }); + await sd.buildAllPlatforms(); + this.outputFiles = this.traverseDir(); + const firstFile = this.outputFiles[0]; + this.changeOutputs(firstFile); + } catch (e) { + // TODO: visualize the fact that an error was thrown + console.error(e); + } + } + + changeOutputs(filePath: string, changeCurrentFile = false) { + this.output = JSON.stringify({ + value: this.volume.readFileSync(filePath, 'utf-8'), + lang: path.extname(filePath).replace(/^\./g, ''), + }); + // call the setter so the editor value updates to the new output selection + if (this.currentFile === 'output' || changeCurrentFile) { + this.currentFile = 'output'; + } + } + + // TODO: make async and parallelize + traverseDir(dir = '/', files: string[] = []) { + let _files = files; + (this.volume.readdirSync(dir) as string[]).forEach((file: string) => { + const fullPath = path.join(dir, file); + if (this.volume.lstatSync(fullPath).isDirectory()) { + _files = [..._files, ...this.traverseDir(fullPath, _files)]; + } else { + _files = [..._files, fullPath]; + } + }); + return [...new Set(_files)]; + } + + async saveFile() { + this[this.currentFile] = JSON.stringify({ + value: this.editor.getValue(), + lang: this.getFileData(this.currentFile).lang, + }); + await this.initData(); + } + + async ejectHandler() { + const tokens = this.getFileData('tokens'); + const script = this.getFileData('script'); + const config = this.getFileData('config'); + const dependencies = await analyzeDependencies(script.value); + const sdDep = dependencies.find((dep) => dep.package === 'style-dictionary'); + if (sdDep) { + sdDep.package = 'style-dictionary@'; + } + const files: Record = {}; + files[`tokens.${tokens.lang}`] = tokens.value; + + const scriptLang = script.lang === 'js' ? 'mjs' : script.lang; + const configLang = config.lang === 'js' ? 'mjs' : config.lang; + + if (configLang === 'json') { + const parsed = JSON.parse(config.value); + parsed.source = [`tokens.${tokens.lang}`]; + config.value = JSON.stringify(parsed, null, 2); + } else if (config.lang === 'js') { + // this is a bit brittle, to add the "source" into a JS file like that.. + config.value = config.value.replace( + /export( *)default( *){/, + `export default {\n source: ['tokens.${tokens.lang}'],`, + ); + } + + files[`config.${configLang}`] = config.value; + files[`build-tokens.${scriptLang}`] = `${script.value} + +const sd = new StyleDictionary('config.${configLang}'); + +await sd.cleanAllPlatforms(); +await sd.buildAllPlatforms(); +`; + files['README.md'] = `# Style Dictionary Eject + +Install your dependencies with [NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm): + +\`\`\`sh +npm init -y && npm install ${dependencies.map((dep) => dep.package).join(' ')} +\`\`\` + +Then run + +\`\`\`sh +node build-tokens.${scriptLang} +\`\`\` +`; + + const today = new Date(Date.now()); + const filename = `sd-output_${today.getFullYear()}-${today.getMonth()}-${( + '0' + today.getDate() + ).slice(-2)}.zip`; + await downloadZIP(files, filename); + } +} + +customElements.define('sd-playground', SdPlayground); diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts new file mode 100644 index 000000000..0a41f8a04 --- /dev/null +++ b/docs/src/content/config.ts @@ -0,0 +1,6 @@ +import { defineCollection } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +} as any; diff --git a/docs/src/content/docs/examples/basic.mdx b/docs/src/content/docs/examples/basic.mdx new file mode 100644 index 000000000..28a2468c0 --- /dev/null +++ b/docs/src/content/docs/examples/basic.mdx @@ -0,0 +1,328 @@ +--- +title: Basic Example +--- + +import { FileTree } from '@astrojs/starlight/components'; + +This example code is bare-bones to show you what this framework can do. +Under the hood of this interactive demo, we run Style Dictionary through the Node API in a way that is equivalent to running the CLI command: + +```bash +npx style-dictionary build +``` + +~ sd-playground + +```json tokens +{ + "colors": { + "base": { + "gray": { + "light": { "value": "#CCCCCC", "type": "color" }, + "medium": { "value": "#999999", "type": "color" }, + "dark": { "value": "#111111", "type": "color" } + }, + "red": { "value": "#FF0000", "type": "color" }, + "green": { "value": "#00FF00", "type": "color" } + }, + "font": { + "base": { "value": "{colors.base.red.value}", "type": "color" }, + "secondary": { "value": "{colors.base.green.value}", "type": "color" }, + "tertiary": { "value": "{colors.base.gray.light.value}", "type": "color" } + } + }, + "size": { + "font": { + "small": { + "value": "0.75", + "type": "fontSize", + "comment": "the small size of the font" + }, + "medium": { + "value": "1", + "type": "fontSize", + "comment": "the medium size of the font" + }, + "large": { + "value": "2", + "type": "fontSize", + "comment": "the large size of the font" + }, + "base": { + "value": "{size.font.medium.value}", + "type": "fontSize", + "comment": "the base size of the font" + } + } + } +} +``` + +```json config +{ + "source": ["tokens.json"], + "platforms": { + "scss": { + "transformGroup": "scss", + "buildPath": "build/scss/", + "files": [ + { + "destination": "_variables.scss", + "format": "scss/variables" + } + ] + }, + "android": { + "transformGroup": "android", + "buildPath": "build/android/", + "files": [ + { + "destination": "font_dimens.xml", + "format": "android/fontDimens" + }, + { + "destination": "colors.xml", + "format": "android/colors" + } + ] + }, + "compose": { + "transformGroup": "compose", + "buildPath": "build/compose/", + "files": [ + { + "destination": "StyleDictionaryColor.kt", + "format": "compose/object", + "options": { + "className": "StyleDictionaryColor", + "packageName": "StyleDictionaryColor" + }, + "filter": { + "type": "color" + } + }, + { + "destination": "StyleDictionarySize.kt", + "format": "compose/object", + "options": { + "className": "StyleDictionarySize", + "packageName": "StyleDictionarySize", + "type": "float" + }, + "filter": { + "type": "fontSize" + } + } + ] + }, + "ios": { + "transformGroup": "ios", + "buildPath": "build/ios/", + "files": [ + { + "destination": "StyleDictionaryColor.h", + "format": "ios/colors.h", + "options": { + "className": "StyleDictionaryColor", + "type": "StyleDictionaryColorName" + }, + "filter": { + "type": "color" + } + }, + { + "destination": "StyleDictionaryColor.m", + "format": "ios/colors.m", + "options": { + "className": "StyleDictionaryColor", + "type": "StyleDictionaryColorName" + }, + "filter": { + "type": "color" + } + }, + { + "destination": "StyleDictionarySize.h", + "format": "ios/static.h", + "options": { + "className": "StyleDictionarySize", + "type": "float" + }, + "filter": { + "type": "fontSize" + } + }, + { + "destination": "StyleDictionarySize.m", + "format": "ios/static.m", + "options": { + "className": "StyleDictionarySize", + "type": "float" + }, + "filter": { + "type": "fontSize" + } + } + ] + }, + "ios-swift": { + "transformGroup": "ios-swift", + "buildPath": "build/ios-swift/", + "files": [ + { + "destination": "StyleDictionary+Class.swift", + "format": "ios-swift/class.swift", + "options": { + "className": "StyleDictionaryClass" + } + }, + { + "destination": "StyleDictionary+Enum.swift", + "format": "ios-swift/enum.swift", + "options": { + "className": "StyleDictionaryEnum" + } + }, + { + "destination": "StyleDictionary+Struct.swift", + "format": "ios-swift/any.swift", + "options": { + "className": "StyleDictionaryStruct", + "imports": "SwiftUI", + "objectType": "struct", + "accessControl": "internal" + } + } + ] + }, + "ios-swift-separate-enums": { + "transformGroup": "ios-swift-separate", + "buildPath": "build/ios-swift/", + "files": [ + { + "destination": "StyleDictionaryColor.swift", + "format": "ios-swift/enum.swift", + "options": { + "className": "StyleDictionaryColor" + }, + "filter": { + "type": "color" + } + }, + { + "destination": "StyleDictionarySize.swift", + "format": "ios-swift/enum.swift", + "options": { + "className": "StyleDictionarySize" + }, + "filter": { + "type": "fontSize" + } + } + ] + } + } +} +``` + +:::note +You can click the download button to the top right of the interactive demo to download a ZIP file for this particular example. +This contains a README.md telling you which commands to run to get this example running locally. +You will need NodeJS and NPM installed, Node v18 minimum being required. +::: + +You should see something like this output in the console: + +``` +scss +✔︎ build/scss/_variables.scss + +android +✔︎ build/android/font_dimens.xml +✔︎ build/android/colors.xml + +compose +✔︎ build/compose/StyleDictionaryColor.kt +✔︎ build/compose/StyleDictionarySize.kt + +ios +✔︎ build/ios/StyleDictionaryColor.h +✔︎ build/ios/StyleDictionaryColor.m +✔︎ build/ios/StyleDictionarySize.h +✔︎ build/ios/StyleDictionarySize.m + +ios-swift +✔︎ build/ios-swift/StyleDictionary.swift + +ios-swift-separate-enums +✔︎ build/ios-swift/StyleDictionaryColor.swift +✔︎ build/ios-swift/StyleDictionarySize.swift +``` + +Good for you! You have now built your first Style Dictionary! +Moving on, take a look at what we have built. This should have created a build directory and it should look like this: + + + +- config.json +- tokens.json +- script.js (empty) +- build/ + - android/ + - font_dimens.xml + - colors.xml + - compose/ + - StyleDictionaryColor.kt + - StyleDictionarySize.kt + - scss/ + - \_variables.scss + - ios/ + - StyleDictionaryColor.h + - StyleDictionaryColor.m + - StyleDictionarySize.h + - StyleDictionarySize.m + - ios-swift/ + - StyleDictionary.swift + - StyleDictionaryColor.swift + - StyleDictionarySize.swift + + + +If you open `config.json` you will see there are 5 platforms defined: + +- `scss` +- `android` +- `compose` +- `ios` +- `ios-swift` + +Each platform has a `transformGroup`, `buildPath`, and `files`. The `buildPath` and `files` of the platform should match up to the files what were built. +These files can be viewed in the live demo above by clicking the output dropdown button. + +Pretty nifty! This shows a few things happening: + +1. The build system does a deep merge of all the token JSON files defined in the `source` attribute of `config.json`. This allows you to split up the token JSON files however you want. There are 2 JSON files with `color` as the top level key, but they get merged properly. +2. The build system resolves references to other design tokens. `{size.font.medium.value}` gets resolved properly. +3. The build system handles references to token values in other files as well as you can see in `tokens/color/font.json`. + +Now let's make a change and see how that affects things. Open up `tokens/color/base.json` and change `"#111111"` to `"#000000"`. After you make that change, save the file and re-run the build command `style-dictionary build`. Open up the build files and take a look. + +**Huzzah!** + +Now go forth and create! Take a look at all the built-in [transforms](https://v4.styledictionary.com/reference/hooks/transforms/predefined/) and [formats](https://v4.styledictionary.com/reference/hooks/formats/predefined/). + +:::tip +If you want to re-run Style Dictionary every time your tokens are changed, e.g. during local development, you can use a file-watcher like [Chokidar](https://github.com/open-cli-tools/chokidar-cli) +to watch file changes and re-run Style Dictionary when needed. In our playground this is done automatically but in order to replicate that behavior locally, implement the filewatcher in your NPM build script: + +```sh +chokidar \"tokens.json\" -c \"node build-tokens.mjs\" +``` + +Or if you don't really need a wrapper build-tokens script and can use the Style Dictionary CLI directly: + +```sh +chokidar \"tokens.json\" -c \"style-dictionary build\" +``` + +::: diff --git a/docs/src/content/docs/examples/splitting-output-files.md b/docs/src/content/docs/examples/splitting-output-files.md new file mode 100644 index 000000000..c24e586fb --- /dev/null +++ b/docs/src/content/docs/examples/splitting-output-files.md @@ -0,0 +1,297 @@ +--- +title: Splitting output files +--- + +Common questions are: + +- How do I prevent my global/primitive tokens from getting to the output? +- How do I split and output my component tokens in their respective component folders? + +This example will show how you can dynamically generate file outputs for each component, and filter out global/primitive tokens. +The trick is to dynamically generate the files array, generate one for each output file you want, and use filters to ensure those outputs only contain the tokens that are relevant. + +~ sd-playground + +```json tokens +{ + "global": { + "colors": { + "black": { + "value": "#000000", + "type": "color" + }, + "white": { + "value": "#ffffff", + "type": "color" + }, + "gray": { + "100": { + "value": "#f7fafc", + "type": "color" + }, + "200": { + "value": "#edf2f7", + "type": "color" + }, + "300": { + "value": "#e2e8f0", + "type": "color" + }, + "400": { + "value": "#cbd5e0", + "type": "color" + }, + "500": { + "value": "#a0aec0", + "type": "color" + }, + "600": { + "value": "#718096", + "type": "color" + }, + "700": { + "value": "#4a5568", + "type": "color" + }, + "800": { + "value": "#2d3748", + "type": "color" + }, + "900": { + "value": "#1a202c", + "type": "color" + } + }, + "orange": { + "100": { + "value": "#fffaf0", + "type": "color" + }, + "200": { + "value": "#feebc8", + "type": "color" + }, + "300": { + "value": "#fbd38d", + "type": "color" + }, + "400": { + "value": "#f6ad55", + "type": "color" + }, + "500": { + "value": "#ed8936", + "type": "color" + }, + "600": { + "value": "#dd6b20", + "type": "color" + }, + "700": { + "value": "#c05621", + "type": "color" + }, + "800": { + "value": "#9c4221", + "type": "color" + }, + "900": { + "value": "#7b341e", + "type": "color" + } + } + }, + "spacing": { + "0": { + "value": "0px", + "type": "dimension" + }, + "1": { + "value": "4px", + "type": "dimension" + }, + "2": { + "value": "8px", + "type": "dimension" + }, + "3": { + "value": "12px", + "type": "dimension" + }, + "4": { + "value": "16px", + "type": "dimension" + }, + "5": { + "value": "20px", + "type": "dimension" + }, + "6": { + "value": "24px", + "type": "dimension" + }, + "7": { + "value": "28px", + "type": "dimension" + }, + "8": { + "value": "32px", + "type": "dimension" + }, + "max": { + "value": "9999px", + "type": "dimension" + } + } + }, + "button": { + "padding": { + "vertical": { + "value": "{global.spacing.2}", + "type": "dimension" + }, + "horizontal": { + "value": "{global.spacing.3}", + "type": "dimension" + } + }, + "primary": { + "default": { + "backgroundColor": { + "value": "{global.colors.orange.500}", + "type": "color" + }, + "textColor": { + "value": "{global.colors.white}", + "type": "color" + }, + "border": { + "value": { + "width": "2px", + "color": "{global.colors.orange.500}", + "style": "solid" + }, + "type": "border" + } + }, + "hover": { + "backgroundColor": { + "value": "{global.colors.orange.400}", + "type": "color" + }, + "border": { + "value": { + "width": "2px", + "color": "{global.colors.orange.400}", + "style": "solid" + }, + "type": "border" + } + } + }, + "secondary": { + "default": { + "backgroundColor": { + "value": "transparent", + "type": "color" + }, + "textColor": { + "value": "{global.colors.orange.500}", + "type": "color" + }, + "border": { + "value": { + "width": "2px", + "color": "{global.colors.orange.500}", + "style": "solid" + }, + "type": "border" + } + }, + "hover": { + "backgroundColor": { + "value": "{global.colors.orange.500}", + "type": "color" + } + } + } + }, + "select": { + "padding": { + "vertical": { + "value": "{global.spacing.2}", + "type": "dimension" + }, + "horizontal": { + "value": "{global.spacing.4}", + "type": "dimension" + } + } + }, + "switch": { + "track": { + "borderRadius": { + "value": "{global.spacing.max}", + "type": "borderRadius" + }, + "height": { + "value": "{global.spacing.5}", + "type": "dimension" + }, + "width": { + "value": "{global.spacing.8}", + "type": "dimension" + } + }, + "thumb": { + "borderRadius": { + "value": "{global.spacing.max}", + "type": "borderRadius" + }, + "size": { + "value": "{global.spacing.4}", + "type": "dimension" + } + } + } +} +``` + +```js config +function generateComponentFiles(components) { + return components.map((comp) => ({ + // output the component tokens in the right folder and file e.g. components/button/button-vqrs.css + destination: `components/${comp}/${comp}-vars.css`, + format: 'css/variables', + // only include the tokens that are inside this component token group + filter: (token) => token.path[0] === comp, + })); +} + +export default { + source: ['tokens.json'], + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'global.css', + format: 'css/variables', + // filter only the tokens that are inside the global object + filter: (token) => token.path[0] === 'global', + }, + // dynamically generate file outputs for each component + ...generateComponentFiles(['button', 'select', 'switch']), + ], + }, + }, +}; +``` + +:::note +You can click the download button to the top right of the interactive demo to download a ZIP file for this particular example. +This contains a README.md telling you which commands to run to get this example running locally. +You will need NodeJS and NPM installed, Node v18 minimum being required. +::: + +More information can be found on the [filters documentation](/reference/hooks/filters) and [files config](/reference/hooks/formats/#format-configuration). diff --git a/docs/examples.md b/docs/src/content/docs/getting-started/examples.md similarity index 72% rename from docs/examples.md rename to docs/src/content/docs/getting-started/examples.md index f37209cc5..592657379 100644 --- a/docs/examples.md +++ b/docs/src/content/docs/getting-started/examples.md @@ -1,55 +1,60 @@ -# Examples +--- +title: Examples +--- To get you started, there are some example packages included that you can use. You can [take a look at the code on Github](https://github.com/amzn/style-dictionary/tree/main/examples/) or you can use the CLI included to generate a new package using some of these examples. Here is how you can do that: ```bash -$ mkdir MyFolder -$ cd MyFolder -$ style-dictionary init [example] +mkdir MyFolder +cd MyFolder +style-dictionary init [example] ``` Where `[example]` is one of: `basic`, `complete`. ## Basic + [View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/basic) This example code is bare-bones to show you what this framework can do. Use this if you want to play around with what the Style Dictionary can do. - ## Complete + [View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/complete) This is a more complete package and should have everything you need to get started. This package can be consumed as a Cocoapod on iOS, as a node module for web, and as a local library for Android. ## Advanced + [View the folder](https://github.com/amzn/style-dictionary/tree/main/examples/advanced) If you want to look at more advanced examples of possible applications and customizations of Style Dictionary, the [`examples/advanced`](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/) folder on GitHub contains these extra folders: -* [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. -* [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the tokens. -* [**component-cti**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. -* [**create-react-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-app) shows how to integrate Style Dictionary into a React application. -* [**create-react-native-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-native-app) shows how to integrate Style Dictionary into a React Native application. -* [**custom-file-header**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) shows how to define custom file headers and use them in output files. -* [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. -* [**custom-parser**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) shows how to use custom parsers for token files. -* [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. -* [**flutter**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/flutter) shows how to integrate with Flutter applications. -* [**matching-build-files**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/matching-build-files) shows how to output files 1-to-1 with source files. -* [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with token values depending on brand and platforms. -* [**node-modules-as-config-and-properties**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) shows how to use Javascript rather than JSON for configuration and token files. -* [**npm-module**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. -* [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. -* [**s3**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. -* [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. -* [**transitive-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms) shows how to use transitive transforms to transform references -* [**variables-in-outputs**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs) shows you how to use the `outputReferences` option to generate files variable references in them. -* [**yaml-tokens**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) shows how to use a custom parser to define your source files in YAML rather than JSON. - +- [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. +- [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the tokens. +- [**component-cti**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. +- [**create-react-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-app) shows how to integrate Style Dictionary into a React application. +- [**create-react-native-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-native-app) shows how to integrate Style Dictionary into a React Native application. +- [**custom-file-header**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) shows how to define custom file headers and use them in output files. +- [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. +- [**custom-parser**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) shows how to use custom parsers for token files. +- [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. +- [**flutter**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/flutter) shows how to integrate with Flutter applications. +- [**matching-build-files**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/matching-build-files) shows how to output files 1-to-1 with source files. +- [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with token values depending on brand and platforms. +- [**node-modules-as-config-and-properties**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) shows how to use Javascript rather than JSON for configuration and token files. +- [**npm-module**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. +- [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. +- [**s3**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. +- [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. +- [**transitive-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms) shows how to use transitive transforms to transform references +- [**variables-in-outputs**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs) shows you how to use the `outputReferences` option to generate files variable references in them. +- [**yaml-tokens**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) shows how to use a custom parser to define your source files in YAML rather than JSON. --- -#### Do you think an example is missing?
Do you want to see another example added to the project?
Do you have a working example that we can add to the list? +Do you think an example is missing?\ +Do you want to see another example added to the project?\ +Do you have a working example that we can add to the list? -Fantastic! Let us know by [filing an issue](https://github.com/amzn/style-dictionary/issues) or sending us an email: style-dictionary@amazon.com. +Fantastic! Let us know by [filing an issue](https://github.com/amzn/style-dictionary/issues). diff --git a/docs/quick_start.md b/docs/src/content/docs/getting-started/installation.mdx similarity index 73% rename from docs/quick_start.md rename to docs/src/content/docs/getting-started/installation.mdx index 04df150b3..7409cd328 100644 --- a/docs/quick_start.md +++ b/docs/src/content/docs/getting-started/installation.mdx @@ -1,29 +1,56 @@ -# Quick Start +--- +title: Overview +sidebar: + order: 1 +--- + +import { FileTree } from '@astrojs/starlight/components'; + +Style Dictionary is a build-system that runs in both NodeJS and browsers (natively), to parse and transform your design tokens to then export them to any platform: +iOS, Android, CSS, JS, HTML, sketch files, style documentation, or anything you can think of. + +It's also forward-compatible with Design Token Community Group spec. + +## Watch the Demo on Youtube + +[![Watch the video](../../../assets/fake_player.png)](http://youtu.be/1HREvonfqhY) + +## Experiment in the playground + +~ sd-playground + +--- ## Installation -*Note that you must have [node (and npm) installed](https://www.npmjs.com/get-npm) before you can follow this guide.* +:::caution +Note that you must have [NodeJS (and NPM) installed](https://nodejs.org/en) before you can follow this guide. +::: If you want to use the CLI, you can install it globally via npm: ```bash -$ npm install -g style-dictionary +npm install -g style-dictionary ``` Or you can install it like a normal npm dependency. Style Dictionary is a build tool, and you are most likely to use it as a dev dependency: ```bash -$ npm install -D style-dictionary +npm install -D style-dictionary ``` +:::note +When using as a dependency or dev dependency, prefix the style-dictionary commands with `npx` +::: + ## Creating a New Project The CLI comes with some starter code to get a new project started easily. ```bash -$ mkdir MyStyleD -$ cd MyStyleD -$ style-dictionary init basic +mkdir MyStyleD +cd MyStyleD +style-dictionary init basic ``` This command will copy over the example files found in the [basic example](https://github.com/amzn/style-dictionary/tree/main/examples/basic) in this repo and then run the `style-dictionary build` command to generate the build artifacts. You should see something like this output: @@ -62,38 +89,42 @@ ios-swift-separate-enums ``` Pat yourself on the back, you built your first style dictionary! Take a look at what you built. This should have created a build directory and it should look like this: -``` -├── README.md -├── config.json -├── tokens/ -│ ├── color/ -│ ├── base.json -│ ├── font.json -│ ├── size/ -│ ├── font.json -├── build/ -│ ├── android/ -│ ├── font_dimens.xml -│ ├── colors.xml -│ ├── compose/ -│ ├── StyleDictionaryColor.kt -│ ├── StyleDictionarySize.kt -│ ├── scss/ -│ ├── _variables.scss -│ ├── ios/ -│ ├── StyleDictionaryColor.h -│ ├── StyleDictionaryColor.m -│ ├── StyleDictionarySize.h -│ ├── StyleDictionarySize.m -│ ├── ios-swift/ -│ ├── StyleDictionary.swift -│ ├── StyleDictionaryColor.swift -│ ├── StyleDictionarySize.swift -``` + + + +- README.md +- config.json +- tokens + - color + - base.json + - font.json + - size + - font.json +- build + - android + - font_dimens.xml + - colors.xml + - compose + - StyleDictionaryColor.kt + - StyleDictionarySize.kt + - scss + - \_variables.scss + - ios + - StyleDictionaryColor.h + - StyleDictionaryColor.m + - StyleDictionarySize.h + - StyleDictionarySize.m + - ios-swift + - StyleDictionary.swift + - StyleDictionaryColor.swift + - StyleDictionarySize.swift + + If you open `config.json` you will see there are 3 platforms defined: scss, android, ios. Each platform has a transformGroup, buildPath, and files defined. The buildPath and files of the platform should match up to the files what were built. Those files should look like these: **Android** + ```xml @@ -102,7 +133,9 @@ If you open `config.json` you will see there are 3 platforms defined: scss, andr 32.00sp 16.00sp +``` +```xml #ffcccccc @@ -117,7 +150,8 @@ If you open `config.json` you will see there are 3 platforms defined: scss, andr ``` **Compose** -```kotlin + +```kotlin title="StyleDictionaryColor.kt" object StyleDictionaryColor { val colorBaseGrayDark = Color(0xff111111) val colorBaseGrayLight = Color(0xffcccccc) @@ -128,7 +162,9 @@ object StyleDictionaryColor { val colorFontSecondary = Color(0xff00ff00) val colorFontTertiary = Color(0xffcccccc) } +``` +```kotlin title="StyleDictionarySize.kt" object StyleDictionarySize { /** the base size of the font */ val sizeFontBase = 16.00.sp @@ -142,7 +178,8 @@ object StyleDictionarySize { ``` **SCSS** -```scss + +```scss title="_variables.scss" $color-base-gray-light: #cccccc; $color-base-gray-medium: #999999; $color-base-gray-dark: #111111; @@ -158,7 +195,8 @@ $size-font-base: 1rem; ``` **iOS** -```objectivec + +```swift title="StyleDictionaryColor.h" #import "StyleDictionaryColor.h" @implementation StyleDictionaryColor @@ -191,17 +229,18 @@ $size-font-base: 1rem; ``` Pretty nifty! This shows a few things happening: + 1. The build system does a deep merge of all the design token files defined in the `source` attribute of `config.json`. This allows you to split up the design token files however you want. There are 2 JSON files with `color` as the top level key, but they get merged properly. 1. The build system resolves references to other design tokens. `{size.font.medium.value}` is resolved properly. 1. The build system handles references to design token values in other files as well (as you can see in `tokens/color/font.json`). 1. Values are transformed specifically for each platform. - ## Making a change Now let's make a change and see how that affects things. Open up `tokens/color/base.json` and change `"#111111"` to `"#000000"`. After you make that change, save the file and re-run the build command `style-dictionary build`. Open up the build files and take a look. Now: **Android** + ```xml @@ -215,7 +254,8 @@ Now let's make a change and see how that affects things. Open up `tokens/color/b #ffcccccc ``` -```kotlin + +```kotlin title="StyleDictionaryColor.kt" object StyleDictionaryColor { val colorBaseGrayDark = Color(0xff000000) val colorBaseGrayLight = Color(0xffcccccc) @@ -227,7 +267,8 @@ object StyleDictionaryColor { val colorFontTertiary = Color(0xffcccccc) } ``` -```scss + +```scss title="_variables.scss" $color-base-gray-light: #cccccc; $color-base-gray-medium: #999999; $color-base-gray-dark: #000000; @@ -237,7 +278,8 @@ $color-font-base: #ff0000; $color-font-secondary: #00ff00; $color-font-tertiary: #cccccc; ``` -```objectivec + +```swift title="StyleDictionaryColor.h" [UIColor colorWithRed:0.800f green:0.800f blue:0.800f alpha:1.000f], [UIColor colorWithRed:0.600f green:0.600f blue:0.600f alpha:1.000f], [UIColor colorWithRed:0.000f green:0.000f blue:0.000f alpha:1.000f], @@ -249,46 +291,54 @@ $color-font-tertiary: #cccccc; ``` That's it! There is a lot more you can do with your style dictionary than generating files with color values. Take a look -at some [examples](examples.md) or take a deeper dive into [package structure](package_structure.md), [extending](extending.md), or how the [build process](build_process.md) works. +at some [examples](examples.md) or take a deeper dive into [package structure](/info/package_structure) or how the [build process](/info/architecture) works. ## Basic Usage + ### Command Line Interface (CLI) + ```bash -$ style-dictionary build +style-dictionary build ``` -Call this in the root directory of your project, which must include a [configuration](config.md) file. -More detailed information about [using the Style Dictionary CLI is available here](using_the_cli.md). +Call this in the root directory of your project, which must include a [configuration](/reference/config) file. + +More detailed information about [using the Style Dictionary CLI is available here](/getting-started/using_the_cli). -### Node +### NodeJS -You can also use the style dictionary build system in node if you want to [extend](extending.md) the functionality or use it in another build system like Grunt or Gulp. +You can also use the Style Dictionary build system in Node if you want to [extend](/getting-started/using_the_npm_module) the functionality or use it in another build system like Grunt or Gulp. -```javascript -const StyleDictionary = require('style-dictionary').extend('config.json'); +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; -StyleDictionary.buildAllPlatforms(); +const sd = new StyleDictionary('config.json'); +await sd.buildAllPlatforms(); ``` -The `.extend()` method is an overloaded method that can also take a [configuration](config.md) object. +The StyleDictionary constructor can also take a [configuration](/reference/config) object. + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; -```javascript -const StyleDictionary = require('style-dictionary').extend({ +const sd = new StyleDictionary({ source: ['tokens/**/*.json'], platforms: { scss: { transformGroup: 'scss', buildPath: 'build/', - files: [{ - destination: 'variables.scss', - format: 'scss/variables' - }] - } + files: [ + { + destination: 'variables.scss', + format: 'scss/variables', + }, + ], + }, // ... - } + }, }); -StyleDictionary.buildAllPlatforms(); +await sd.buildAllPlatforms(); ``` -More detailed information about [using the Style Dictionary npm module is available here](using_the_npm_module.md). +More detailed information about [using the Style Dictionary npm module is available here](/getting-started/using_the_npm_module). diff --git a/docs/src/content/docs/getting-started/using_the_cli.md b/docs/src/content/docs/getting-started/using_the_cli.md new file mode 100644 index 000000000..4ee1d08a3 --- /dev/null +++ b/docs/src/content/docs/getting-started/using_the_cli.md @@ -0,0 +1,103 @@ +--- +title: Using the CLI +sidebar: + order: 2 +--- + +The Style Dictionary command line interface (CLI) provides an executable system to create and act upon style dictionaries. + +## Installation + +To use the CLI, you can install it globally via npm: + +```bash +npm install -g style-dictionary +``` + +Most of the time you will want to install Style Dictionary as a dev dependency in your NPM package. The reason to have it as a dev dependency rather than a regular dependency is that Style Dictionary is a build tool rather than a runtime tool because it is used to _generate_ files rather than used directly in an application. + +```bash +npm install --save-dev style-dictionary +``` + +In your `package.json` file you can add an NPM script that runs Style Dictionary: + +```json title="package.json" +{ + "scripts": { + "build": "style-dictionary build" + } +} +``` + +## Commands + +The CLI provides three basic commands: + +- [build](#build) Builds a Style Dictionary package from the current directory. +- [clean](#clean) Removes files specified in the config of the Style Dictionary package of the current directory. +- [init](#init) Generates a starter Style Dictionary +- [version](#version) Get the version of Style Dictionary + +These commands can be run using: + +```bash +style-dictionary [command] [options] +``` + +### build + +Builds a style dictionary package from the current directory. Usage: + +```bash +style-dictionary build [options] +``` + +Options: + +| Name | Usage | Description | +| ------------------ | ------------------------------------ | -------------------------------------------------------------------------------------------------------- | +| Configuration Path | -c , --config | Set the path to the configuration file. Defaults to './config.json'. | +| Platform | -p , --platform | Only build a specific platform. If not supplied, builds all platform found in the configuration file. | +| Silent | -s, --silent | Silence all logging, except for fatal errors. | +| Verbose | -v, --verbose | Enable verbose logging for reference errors, token collisions and filtered tokens with outputReferences. | +| No Warnings | -n, --no-warn | Disable warnings from being logged. Still logs success logs and fatal errors. | + +### clean + +Removes files and folders generated by a previously run 'build' command. Usage: + +```bash +style-dictionary clean [options] +``` + +Options: + +| Name | Usage | Description | +| ------------------ | ------------------------------------ | -------------------------------------------------------------------------------------------------------- | +| Configuration Path | -c , --config | Set the path to the configuration file. Defaults to './config.json'. | +| Platform | -p , --platform | Only clean a specific platform. If not supplied, cleans all platform found in the configuration file. | +| Silent | -s, --silent | Silence all logging, except for fatal errors. | +| Verbose | -v, --verbose | Enable verbose logging for reference errors, token collisions and filtered tokens with outputReferences. | +| No Warnings | -n, --no-warn | Disable warnings from being logged. Still logs success logs and fatal errors. | + +### init + +Generates a starter style dictionary, based on the supplied example type. Usage: + +```bash +style-dictionary init +``` + +Where example-type is one of: + +- `basic` +- `complete` + +### version + +To see what version of Style Dictionary you have, run this command: + +```bash +style-dictionary --version +``` diff --git a/docs/src/content/docs/getting-started/using_the_npm_module.md b/docs/src/content/docs/getting-started/using_the_npm_module.md new file mode 100644 index 000000000..986e9af1e --- /dev/null +++ b/docs/src/content/docs/getting-started/using_the_npm_module.md @@ -0,0 +1,129 @@ +--- +title: Using the NPM Module +sidebar: + order: 3 +--- + +The Style Dictionary [NPM](https://www.npmjs.com/) module exposes an [API](/reference/api) to interact with Style Dictionary. + +## Installation + +To use the NPM module, install it like a normal NPM dependency. You are most likely going to want to save it as a dev dependency (The -D option) because it's a build-tool: + +```bash +npm install -D style-dictionary +``` + +## NPM Module Quick Start + +To use the style dictionary build system in node, there are generally three steps: + +1. Import the StyleDictionary module +2. Construct an instance with a configuration, creating the fully defined dictionary (importing all tokens and intended outputs) +3. Call one or more build calls for various platforms + +To use the NPM module you will need to update your NPM script that runs Style Dictionary from using the CLI command to running Node on the file you are using. +Alternatively, you can also use [`npx`](https://docs.npmjs.com/cli/v8/commands/npm-exec). + +```json +// package.json +{ + "scripts": { + "build": "style-dictionary build" + } +} +``` + +becomes + +```json +// package.json +{ + "scripts": { + "build": "node build.js" + } +} +``` + +Update `build.js` to the name of the file you created. + +Using a JSON [configuration](/reference/config) file, that looks like this: + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary('config.json'); +await sd.buildAllPlatforms(); +``` + +You can also `extend` Style Dictionary multiple times and call `buildAllPlatforms` as many times as you need. This can be useful if you are creating nested (parent-child) themes with Style Dictionary. + +```javascript +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ + // add custom formats/transforms +}); + +await ( + await sd.extend({ + // ... + }) +).buildAllPlatforms(); + +await ( + await sd.extend({ + // ... + }) +).buildAllPlatforms(); +``` + +Another way to do this is to loop over an array and apply different configurations to Style Dictionary: + +```javascript +import StyleDictionary from 'style-dictionary'; + +const brands = [`brand-1`, `brand-2`, `brand-3`]; + +await Promise.all( + brands.map((brand) => { + const sd = new StyleDictionary({ + include: [`tokens/default/**/*.json`], + source: [`tokens/${brand}/**/*.json`], + // ... + }); + return sd.buildAllPlatforms(); + }), +); +``` + +The [multi-brand-multi-platform example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) uses this method. + +--- + +## Utils + +There is also a utils entrypoint on the NPM module that contains helper utils. + +```js title="import-utils.js" +import { flattenTokens } from 'style-dictionary/utils'; +``` + +For more details, [read the utils docs](/reference/utils) + +## Types + +There is also a types entrypoint on the NPM module that contains additional type interfaces +that may be useful when using TypeScript and creating your own hooks or needing to type your design token objects. + +Any import from style-dictionary comes with first-class TypeScript annotations already attached, so you won't need this too often. + +```ts title="import-types.ts" +import type { DesignTokens, Parser } from 'style-dictionary/types'; +``` + +For more details, [read the types docs](/reference/types) + +## NPM Module API + +The [complete npm module API is documented here](/reference/api). diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx new file mode 100644 index 000000000..c3bd1b201 --- /dev/null +++ b/docs/src/content/docs/index.mdx @@ -0,0 +1,38 @@ +--- +title: Style Dictionary +template: splash +hero: + tagline: + Export your Design Tokens to any platform - iOS, Android, CSS, JS, HTML, sketch files, style documentation, or anything you can think of. + Forward-compatible with Design Tokens Community Group spec. + image: + file: ../../assets/logo.png + actions: + - text: Documentation + link: /getting-started/installation + icon: right-arrow + variant: primary + - text: Migration to Version 4 + link: /version-4/migration/ + icon: up-caret + variant: secondary + - text: GitHub + link: https://github.com/amzn/style-dictionary + icon: external +--- + +import tokens from '/public/demo-tokens.json'; + +## Live Demo + +Below is a showcase of how a set of DTCG tokens would be exported to CSS: + + + +
+
+ +Upload your JSON or ZIP of tokens and convert them to DTCG format: + + +[Read more about DTCG](/info/dtcg/) diff --git a/docs/src/content/docs/info/DTCG.mdx b/docs/src/content/docs/info/DTCG.mdx new file mode 100644 index 000000000..58bd08d76 --- /dev/null +++ b/docs/src/content/docs/info/DTCG.mdx @@ -0,0 +1,36 @@ +--- +title: Design Tokens Community Group +sidebar: + order: 4 +--- + +import tokens from '/public/demo-tokens.json'; + +The [Design Tokens W3C Community Group](https://www.w3.org/community/design-tokens/)’s (DTCG) goal is to "provide standards upon which products and design tools can rely for sharing stylistic pieces of a design system at scale". + +The Community Group publishes a [specification defining how Design Tokens ought to be formatted](https://tr.designtokens.org/format/) for cross-tool and cross-platform interoperability. + +**As of version 4**, Style Dictionary has first-class support for the DTCG format. + +## Convert your tokens to the DTCG format + +We provide a tool that converts design tokens from the Style Dictionary v3 JSON format to the DTCG format: + +
+ + +What it does: + +- ✅ Converts `value`, `type` and `description` design token property keys into `$value`, `$type` and `$description` respectively. +- ✅ Moves `$type` properties from the uppermost common ancestor token group to individual design tokens + +What it does not do (at the moment, [suggestions welcome](https://github.com/amzn/style-dictionary/issues/new?title=Conversion%20tool%20suggestion:%20%3Cyour-suggestion-here%3E)): + +- ⛔ It does not refactor type values commonly used to the DTCG types (for example: `"$type": "size"` -> `"$type": "dimension"`). + +## Live demo + + + +
+
diff --git a/docs/src/content/docs/info/architecture.md b/docs/src/content/docs/info/architecture.md new file mode 100644 index 000000000..fd441cefc --- /dev/null +++ b/docs/src/content/docs/info/architecture.md @@ -0,0 +1,89 @@ +--- +title: Architecture +sidebar: + order: 2 +--- + +This is how Style Dictionary works under the hood: + +```mermaid +flowchart LR + subgraph global + direction TB + Z[Config] -->|Parse config| X + X[Parsed Config] -->|Run| A + A[Token Files] -->|Parsers| B + B[JavaScript Objects] -->|Combine| C + C[Dictionary] -->|Preprocessors| C + click X "#1-parse-the-config" "Explanation about parsing config" + click A "#2-find-all-token-files" "Explanation about finding tokens files" + click B "#3-parse-token-files" "Explanation about parsing tokens files" + click C "#4-deep-merge-token-files" "Explanation about deep merging tokens into a dictionary" + end + + subgraph platform + direction TB + D[Dictionary] -->|Preprocessors| D + D -->|Transforms| E + E[Transformed Dictionary] -->|Resolve references| F + F[Resolved Dictionary] -->|Transitive transforms| E + click D "#5-run-preprocessors-over-the-dictionary" "Explanation about preprocessing the dictionary" + click E "#6-transform-the-tokens" "Explanation about transforming tokens" + click F "#7-resolve-aliases--references-to-other-values" "Explanation about token references resolution" + end + + subgraph files + direction TB + G[Resolved Dictionary] --> |Filters| H + H[Filtered Dictionary] --> |Formats| I + H[Filtered Dictionary] --> |File headers| I + I[Platform output] --> |Actions| J[Actions output] + click I "#8-format-the-tokens-into-files" "Explanation about formatting tokens to output files" + click J "#9-run-actions" "Explanation about running actions" + end + global --> platform --> files +``` + +Let's take a closer look into each of these steps. + +## 1. Parse the config + +Style Dictionary is a configuration based framework, you tell it what to do in a configuration file. Style Dictionary first parses this [configuration](/reference/config) to know what to do. + +## 2. Find all token files + +In your [config](/reference/config) file can define `include` and `source`, which are arrays of file path globs. These tell Style Dictionary where to find your token files. You can have them anywhere and in any folder structure as long as you tell Style Dictionary where to find them. + +## 3. Parse token files + +If there are [custom parsers](/reference/hooks/parsers) defined and applied in the config, Style Dictionary will run those on files the applied parsers match. For JSON or JavaScript token files, those are parsed automatically through built-in parsers. + +## 4. Deep merge token files + +Style Dictionary takes all the files it found and performs a deep merge. This allows you to split your token files in any way you like, without worrying about accidentally overriding groups of tokens. This gives Style Dictionary a single, complete token object to work from. + +## 5. Run preprocessors over the dictionary + +Allows users to configure [custom preprocessors](/reference/hooks/preprocessors), to process the merged dictionary as a whole, rather than per token file individually. +These preprocessors have to be applied in the config, either on a global or platform level. +Platform level preprocessors run once you get/export/format/build a platform, at the very start. + +## 6. Transform the tokens + +Style Dictionary now traverses over the whole token object and looks for design tokens. It does this by looking for anything with a `value` key. When it comes across a design token, it then performs all the [transforms](/reference/hooks/transforms) defined in your [config](/reference/config) in order. + +Value transforms, transforms that modify a token's value, are skipped if the token references another token. Starting in 3.0, you can define a [transitive transform](/reference/hooks/transforms#transitive-transforms) that will transform a value that references another token after that reference has been resolved. + +## 7. Resolve aliases / references to other values + +After all the tokens have been transformed, it then does another pass over the token object looking for aliases, which look like `"{size.font.base.value}"`. When it finds these, it then replaces the reference with the transformed value. Because Style Dictionary merges all token files into a single object, aliases can be in any token file and still work. + +## 8. Format the tokens into files + +Now all the design tokens are ready to be written to a file. Style Dictionary takes the whole transformed and resolved token object and for each file defined in the platform it [formats](/reference/hooks/formats) the token object and write the output to a file. Internally, Style Dictionary creates a flat array of all the design tokens it finds in addition to the token object. This is how you can output a flat SCSS variables file. + +## 9. Run actions + +[Actions](/reference/hooks/actions) are custom code that run in a platform after the files are generated. They are useful for things like copying assets to specific build directories or generating images. + +After Style Dictionary does steps 4a-4d for each platform, you will have all your output files that are ready to consume in each platform and codebase. diff --git a/docs/src/content/docs/info/package_structure.mdx b/docs/src/content/docs/info/package_structure.mdx new file mode 100644 index 000000000..aaa9e2e8c --- /dev/null +++ b/docs/src/content/docs/info/package_structure.mdx @@ -0,0 +1,38 @@ +--- +title: Package Structure +sidebar: + order: 3 +--- + +import { FileTree } from '@astrojs/starlight/components'; + +Style Dictionary is configuration driven. A Style Dictionary package must contain a configuration and reference a path to design token files. You can optionally include assets in your package. + +Here is a basic example of what a Style Dictionary package looks like. + + + +- config.json +- tokens + - size + - font.json + - color + - font.json +- assets + - fonts + - images + + + +| Name | Description | +| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `config.json` | This is where the [configuration](/reference/config) for the style dictionary lives, where you define what happens when Style Dictionary runs | +| design token files | [Design tokens](/references/info/tokens) are saved as a collection of JSON or JS module files. You can put them wherever you like - the path to them should be in the `source` attribute on your `config.json` file. | +| assets (optional) | Assets can be included in your style dictionary package, allowing you to keep them in your style dictionary as a single source of truth. | + +## Assets + +Assets are not required, but can be useful to include in your style dictionary. If you don't want to manage having assets like images, +vectors, font files, etc. in multiple locations, you can keep them in your style dictionary as a single source of truth. + +> Coming soon: how to generate image assets based on your style dictionary diff --git a/docs/src/content/docs/info/tokens.md b/docs/src/content/docs/info/tokens.md new file mode 100644 index 000000000..5c2163c0b --- /dev/null +++ b/docs/src/content/docs/info/tokens.md @@ -0,0 +1,362 @@ +--- +title: Design Tokens +sidebar: + order: 1 +--- + +> Synonyms: style properties, design variables, design constants, atoms + +Design tokens are the platform-agnostic way to define design decisions, and are the main input for Style Dictionary. + +:::note +Currently, Style Dictionary is forward-compatible with the [Design Token Community Group spec](https://design-tokens.github.io/community-group/format/) +Our docs still display the original Style Dictionary way of defining design tokens. +The biggest difference is that the DTCG uses `$value`, `$type` and `$description` whereas the original format uses `value`, `type` and `comment`. +In version 4 you can use either format, pick one though as they cannot be combined inside a single Style Dictionary instance. +::: + +A design token is transformed for use in different platforms, languages, and contexts. +A simple example is color. A color can be represented in many ways, all of these are the same color: `#ffffff`, `rgb(255,255,255)`, `hsl(0,0,1)`. + +A collection of design tokens which are organized in a nested object make the Style Dictionary. Here is an example of design tokens written for Style Dictionary: + +```json title="tokens.json" +{ + "colors": { + "font": { + "base": { "value": "#111111", "type": "color" }, + "secondary": { "value": "#333333", "type": "color" }, + "tertiary": { "value": "#666666", "type": "color" }, + "inverse": { + "base": { "value": "#ffffff", "type": "color" } + } + } + } +} +``` + +Any node in the object that has a `value` attribute on it is a design token. In this example there are 4 style design tokens: `color.font.base`, `color.font.secondary`, `color.font.tertiary`, and `color.font.inverse.base`. + +Using DTCG format that would look like: + +```json title="dtcg-tokens.json" +{ + "colors": { + "$type": "color", + "font": { + "base": { "$value": "#111111" }, + "secondary": { "$value": "#333333" }, + "tertiary": { "$value": "#666666" }, + "inverse": { + "base": { "$value": "#ffffff" } + } + } + } +} +``` + +> **From this point on, we are assuming the old Style Dictionary format, this is a disclaimer that some of this will be in slight contradiction with the DTCG spec, e.g. how metadata is handled.** + +## Design token attributes + +For any design tokens you wish to output, the "value" attribute is required. This provides the data that will be used throughout the build process (and ultimately used for styling in your deliverables). You can optionally include any custom attributes you would like (e.g. "comment" with a string or "metadata" as an object with its own attributes). + +| Property | Type | Description | +| :--------- | :----------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| value | Any | The value of the design token. This can be any type of data, a hex string, an integer, a file path to a file, even an object or array. | +| comment | String (optional) | The comment attribute will show up in a code comment in output files if the format supports it. | +| themeable | Boolean (optional) | This is used in formats that support override-able or themable values like the `!default` flag in Sass. | +| name | String (optional) | Usually the name for a design token is generated with a [name transform](/reference/hooks/transforms#transform-types), but you can write your own if you choose. By default Style Dictionary will add a default name which is the key of the design token object. | +| attributes | Object (optional) | Extra information about the design token you want to include. [Attribute transforms](/reference/hooks/transforms#transform-types) will modify this object so be careful | + +You can add any attributes or data you want in a design token and Style Dictionary will pass it along to transforms and formats. For example, you could add a `deprecated` flag like in [this example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation). Other things you can do is add documentation information about each design token or information about color contrast. + +### Default design token metadata + +Style Dictionary adds some default metadata on each design token that helps with transforms and formats. Here is what Style Dictionary adds onto each design token: + +| Property | Type | Description | +| :------- | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| name | String | A default name of the design token that is set to the key of the design token. This is only added if you do not provide one. | +| path | Array[String] | The object path of the design token. `color: { background: { primary: { value: "#fff" } } }` will have a path of `['color','background', 'primary']`. | +| original | Object | A pristine copy of the original design token object. This is to make sure transforms and formats always have the unmodified version of the original design token. | +| filePath | String | The file path of the file the token is defined in. This file path is derived from the `source` or `include` file path arrays defined in the [configuration](/reference/config). | +| isSource | Boolean | If the token is from a file defined in the `source` array as opposed to `include` in the [configuration](/reference/config). | + +Given this configuration: + +```json5 +// config.json +{ + source: ['tokens/**/*.json'], + //... +} +``` + +This design token: + +```json5 +// tokens/color/background.json +{ + color: { + background: { + primary: { value: '#fff' }, + }, + }, +} +``` + +becomes: + +```json5 +{ + color: { + background: { + primary: { + name: 'primary', + value: '#fff', + path: ['color', 'background', 'primary'], + original: { + value: '#fff', + }, + filePath: 'tokens/color/background.json', + isSource: true, + }, + }, + }, +} +``` + +--- + +## Referencing / Aliasing + +You can reference (alias) existing values by using the dot-notation object path (the fully articulated design token name) in curly brackets. Note that this only applies to values; referencing a non-value design token will cause unexpected results in your output. + +```json +{ + "size": { + "font": { + "small": { "value": "10" }, + "medium": { "value": "16" }, + "large": { "value": "24" }, + "base": { "value": "{size.font.medium.value}" } + } + } +} +``` + +See more in the advanced [referencing-aliasing example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing). + +--- + +## Defining design tokens + +Design token files can included inline in the configuration, or be written in separate files. Style Dictionary supports these languages for design token files: + +- JSON +- [JSONC](https://code.visualstudio.com/docs/languages/json#_json-with-comments) +- [JSON5](https://json5.org) +- ES Modules +- Potentially any language with [custom parsers](/reference/hooks/parsers) + +Tokens can be defined _inline_ in the Style Dictionary configuration, or in files. You can add a `tokens` object to your Style Dictionary configuration like this: + +```javascript +// config.js +export default { + tokens: { + color: { + background: { + primary: { value: '#fff' }, + }, + }, + }, + platforms: { + //... + }, +}; +``` + +Generally you will have too many design tokens to include them all inline, so you can separate them out into their own files. You can tell Style Dictionary where to find your design token files with the `source` and `include` attributes in the configuration like this: + +```javascript +// config.js +export default { + include: [ + // you can list singular files: + `node_modules/my-other-style-dictionary/tokens.json`, + ], + source: [ + // or use file path [globs](https://www.npmjs.com/package/glob) + // this says grab all files in the tokens directory with a .json extension + `tokens/**/*.json`, + ], + // ... +}; +``` + +**You can organize your design token files in any way as long as you can tell Style Dictionary where to find them.** The directory and file structure of design token files does not have any effect on the object structure of the tokens because Style Dictionary does a deep merge on all design token files. Separating tokens into files and folders is to make the authoring experience cleaner and more flexible. + +### Collision warnings + +Style Dictionary takes all the files it finds in the include and source arrays and performs a deep merge on them. It will first add files in the include array, in order, and then the source array in order. Later files will take precedence. For example if you defined 2 source files like this: + +```javascript +// config.js +export default { + source: [`tokens.json`, `tokens2.json`], +}; +``` + +```json5 +// tokens.json +{ + color: { + background: { + primary: { value: '#fff' }, + secondary: { value: '#ccc' }, + }, + }, +} +``` + +```json5 +// tokens2.json +{ + color: { + background: { + primary: { value: '#eee' }, + tertiary: { value: '#999' }, + }, + }, +} +``` + +The resulting merged dictionary would be: + +```json5 +{ + color: { + background: { + primary: { value: '#eee' }, + secondary: { value: '#ccc' }, + tertiary: { value: '#999' }, + }, + }, +} +``` + +This example would show a warning in the console that you have a collision at `color.background.primary` because 2 source files defined the same design token. A file in source overriding a file in include will not show a warning because the intent is that you include files you want to potentially override. For example, if you had multiple brands and you wanted to share a default theme, you could include the default theme and then override certain parts. + +### ES Modules + +One way to write your design token files is to write them in Javascript rather than JSON. The only requirement for writing your source files in Javascript is to use an ES Module containing a default export of a plain object. For example: + +```javascript title="config.js" +export default { + color: { + base: { + red: { value: '#ff0000' }, + }, + }, +}; +``` + +is equivalent to this JSON file: + +```json title="config.json" +{ + "color": { + "base": { + "red": { "value": "#ff0000" } + } + } +} +``` + +You might prefer authoring your design token files in Javascript because it can be a bit more friendly to read and write (don't have to quote keys, can leave dangling commas, etc.). Writing your design token files as Javascript gives you more freedom to do complex things like generating many tokens based on code: + +```javascript title="colors.json" +import Color from 'tinycolor2'; + +const baseColors = { + red: { h: 4, s: 62, v: 90 }, + purple: { h: 262, s: 47, v: 65 }, + blue: { h: 206, s: 70, v: 85 }, + teal: { h: 178, s: 75, v: 80 }, + green: { h: 119, s: 47, v: 73 }, + yellow: { h: 45, s: 70, v: 95 }, + orange: { h: 28, s: 76, v: 98 }, + grey: { h: 240, s: 14, v: 35 }, +}; + +// Use a reduce function to take the array of keys in baseColor +// and map them to an object with the same keys. +export default Object.keys(baseColors).reduce((ret, color) => { + return Object.assign({}, ret, { + [color]: { + // generate the shades/tints for each color + 20: { value: Color(baseColors[color]).lighten(30).toString() }, + 40: { value: Color(baseColors[color]).lighten(25).toString() }, + 60: { value: Color(baseColors[color]).lighten(20).toString() }, + 80: { value: Color(baseColors[color]).lighten(10).toString() }, + 100: { value: baseColors[color] }, + 120: { value: Color(baseColors[color]).darken(10).toString() }, + 140: { value: Color(baseColors[color]).darken(20).toString() }, + }, + }); +}, {}); +``` + +Take a look at the [this example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) if you want to see a more in-depth example of using JavaScript files as input. + +### Custom file parsers + +You can define custom parsers to parse your source files. This allows you to author your design token files in other languages like [YAML](https://yaml.org/). Custom parsers run on certain input files based on a file path pattern regular expression (similar to how Webpack loaders work). The parser function gets the contents of the file and is expected to return an object of the data of that file for Style Dictionary to merge with the other input file data. + +```javascript title="build-tokens.json" +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerParser({ + pattern: /.json$/, + parse: ({ contents, filePath }) => { + return JSON.parse(contents); + }, +}); +``` + +For more information, [read the parsers docs](/reference/hooks/parsers). + +[Here is a complete custom file parser example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) + +[yaml-tokens example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) + +--- + +### Category / Type / Item + +**This structure is not required.** This is just one example of how to structure your design tokens. + +Design tokens are organized into a hierarchical tree structure with 'category' defining the primitive nature of the design token. For example, we have the color category and every design token underneath is always a color. As you proceed down the tree, you get more specific about what that color is. Is it a background color, a text color, or a border color? What kind of text color is it? You get the point. It's like the animal kingdom classification: + +![](../../../assets/cti.png) + +Now you can structure your tokens in a nested object like this: + +```json +{ + "size": { + "font": { + "base": { "value": "16" }, + "large": { "value": "20" } + } + } +} +``` + +The CTI is implicit in the structure, the category is 'size' and the type is 'font', and there are 2 tokens 'base' and 'large'. + +Structuring design tokens in this manner gives us consistent naming and accessing of these tokens. You don't need to remember if it is `button_color_error` or `error_button_color`, it is `color_background_button_error`! + +You can organize and name your design tokens however you want, **there are no restrictions**. But there are a good amount of helpers if you do use this structure, like the [`'attribute/cti'` transform](/reference/hooks/transforms#attributecti) which adds attributes to the design token of its CTI based on the path in the object. These attributes can then be used in other transforms to get some info about the token, or to [filter tokens using filters](/reference/hooks/filters). diff --git a/docs/src/content/docs/reference/Hooks/Formats/helpers.md b/docs/src/content/docs/reference/Hooks/Formats/helpers.md new file mode 100644 index 000000000..b5efff8c1 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Formats/helpers.md @@ -0,0 +1,28 @@ +--- +title: Custom format helpers +sidebar: + label: Helpers +--- + +We provide some helper methods we use internally in some of the built-in formats to make building custom formats a bit easier. + +They are accessible at `style-dictionary/utils` entrypoint, you can read more about them in the [Utils -> Format Helpers](/reference/utils/format-helpers) docs. + +```javascript +import StyleDictionary from 'style-dictionary'; +import { fileHeader, formattedVariables } from 'style-dictionary/utils'; + +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: async ({ dictionary, file, options }) => { + const { outputReferences } = options; + const header = await fileHeader({ file }); + return ( + header + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, +}); +``` diff --git a/docs/src/content/docs/reference/Hooks/Formats/index.md b/docs/src/content/docs/reference/Hooks/Formats/index.md new file mode 100644 index 000000000..a614cfc58 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Formats/index.md @@ -0,0 +1,470 @@ +--- +title: Formats +sidebar: + label: Overview +--- + +Formats define the output of your created files. For example, to use your styles in CSS +you use the `css/variables` format. This will create a CSS file containing the variables from +your style dictionary. + +## Using formats + +You use formats in your config file under `platforms` > `[Platform]` > `files` > `[File]` > `format`. + +```json +{ + "source": ["tokens/**/*.json"], + "platforms": { + "css": { + "transformGroup": "css", + "files": [ + { + "format": "css/variables", + "destination": "variables.css" + } + ] + } + } +} +``` + +There is an extensive (but not exhaustive) list of [built-in formats](#pre-defined-formats) available in Style Dictionary. + +## Format configuration + +Formats can take configuration to make them more flexible. This allows you to re-use the same format multiple times with different configurations or to allow the format to use data not defined in the tokens themselves. To configure a format, add extra attributes on the file `options` in your configuration like the following: + +```json +{ + "source": ["tokens/**/*.json"], + "platforms": { + "scss": { + "transformGroup": "scss", + "files": [ + { + "destination": "map.scss", + "format": "scss/map-deep", + "options": { + "mapName": "my-tokens" + } + } + ] + } + } +} +``` + +In this example we are adding the `mapName` configuration to the `scss/map-deep` format. This will change the name of the SCSS map in the output. Not all formats have the configuration options; format configuration is defined by the format itself. To see the configuration options of a format, take a look at the documentation of the [specific format](#pre-defined-formats) + +## Filtering tokens + +A special file configuration is [`filter`](/reference/hooks/filter), which will filter the tokens before they get to the format. +This allows you to re-use the same format to generate multiple files with different sets of tokens. +Filtering tokens works by adding a `filter` attribute on the file object, where `filter` is: + +- An object which gets passed to [Lodash's filter method](https://lodash.com/docs/4.17.14#filter). +- A string that references the name of a registered [`filter`](/reference/hooks/filter), using the [`registerFilter`](/reference/api#registerfilter) method +- A function that takes a token and returns a boolean if the token should be included (true) or excluded (false). **This is only available if you are defining your configuration in Javascript.** + +```javascript +{ + "destination": "destination", + "format": "myCustomFormat", + "filter": "myCustomFilter", // a named filter defined with .registerFilter + "filter": function(token) {}, // an inline function + "filter": {} // an object pass to lodash's filter method +} +``` + +The design token that is passed to the filter function has already been [transformed](/reference/hooks/transforms) and has [default metadata](/info/tokens#default-design-token-metadata) added by Style Dictionary. + +## References in output files + +Some formats can keep the references in the output. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens: + +```json +// tokens.json +{ + "color": { + "red": { "value": "#ff0000" }, + "danger": { "value": "{color.red.value}" }, + "error": { "value": "{color.danger.value}" } + } +} +``` + +With this configuration: + +```json +// config.json +{ + "source": ["tokens.json"], + "platforms": { + "css": { + "transformGroup": "css", + "files": [ + { + "destination": "variables.css", + "format": "css/variables", + "options": { + // Look here 👇 + "outputReferences": true + } + } + ] + } + } +} +``` + +This would be the output: + +```css title="variables.css" +:root { + --color-red: #ff0000; + --color-danger: var(--color-red); + --color-error: var(--color-danger); +} +``` + +The css variables file now keeps the references you have in your Style Dictionary! This is useful for outputting themeable and dynamic code. + +Without `outputReferences: true` Style Dictionary would resolve all references and the output would be: + +```css title="variables.css" +:root { + --color-red: #ff0000; + --color-danger: #ff0000; + --color-error: #ff0000; +} +``` + +It is also possible to provide a function instead of `true` or `false` to `outputReferences`, if you need to conditionally output references on a per token basis. + +```js +// config.js +export default { + source: ['tokens.json'], + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'variables.css', + format: 'css/variables', + options: { + // Look here 👇 + outputReferences: (token, { dictionary, usesDtcg }) => { + // `dictionary` contains `allTokens`, `tokens` and `unfilteredTokens` props + // `usesDtcg` tells you whether the Design Token Community Group spec is used with $ prefixes ($value, $type etc.) + // return true or false + }, + }, + }, + ], + }, + }, +}; +``` + +Not all formats use the `outputReferences` option because that file format might not support it (like JSON for example). The current list of formats that handle `outputReferences`: + +- [css/variables](#cssvariables) +- [scss/variables](#scssvariables) +- [less/variables](#lessvariables) +- [android/resources](#androidresources) +- [compose/object](#composeobject) +- [ios-swift/class.swift](#ios-swiftclassswift) +- [flutter/class.dart](#flutterclassdart) + +You can create custom formats that output references as well. See the [Custom format with output references](#custom-format-with-output-references) section. + +### Filtering out references + +When combining [`filters`](/reference/hooks/filters) with `outputReferences`, it could happen that a token is referencing another token that is getting filtered out. +When that happens, Style Dictionary will throw a warning. However, it is possible to configure `outputReferences` to use [our `outputReferencesFilter` utility function](/reference/utils/references/#outputreferencesfilter), which will prevent tokens that reference other tokens that are filtered out from outputting references, they will output the resolved values instead. + +### outputReferences with transitive transforms + +When combining [transitive value transforms](/reference/hooks/transforms/#transitive-transforms) with `outputReferences`, +it could happen that a token that contains references has also been transitively transformed. +What this means is that putting back the references in the output would mean we are undoing that work. +In this scenario, it's often preferable not to output a reference. + +There is an [`outputReferencesTransformed`](/reference/utils/references/#outputreferencestransformed) utility function that takes care of checking if this happened and not outputting refs for tokens in this scenario. + +## File headers + +By default Style Dictionary adds a file header comment in the top of files built using built-in formats like this: + +```js title="variables.js" +// Do not edit directly +// Generated on Sat, 01 Jan 2000 00:00:00 GMT +``` + +You can remove these comments with the option: `showFileHeader: false` if you do not want them in your generated files. You can also create your own file header or extend the default one. This could be useful if you want to put a version number or hash of the source files rather than a timestamp. + +Custom file headers can be added the same way you would add a custom format, either by using the [`registerFileHeader`](/reference/api#registerfileheader) function or adding the [`fileHeader`](/reference/hooks/file-headers) object directly in the Style Dictionary [configuration](/reference/config). Your custom file header can be used in built-in formats as well as custom formats. To use a custom file header in a custom format see the [`fileHeader`](/reference/hooks/formats#fileheader) format helper method. + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerFileHeader({ + name: 'myCustomHeader', + // This can be an async function as well + fileHeader: (defaultMessage) => { + // defaultMessage are the 2 lines above that appear in the default file header + // you can use this to add a message before or after the default message 👇 + + // the fileHeader function should return an array of strings + // which will be formatted in the proper comment style for a given format + return [...defaultMessage, `hello?`, `is it me you're looking for?`]; + }, +}); +``` + +Then you can use your custom file header in a file similar to a custom format: + +```json title="config.json" +{ + "source": ["tokens/**/*.json"], + "platforms": { + "css": { + "transformGroup": "css", + "files": [ + { + "destination": "variables.css", + "format": "css/variables", + "options": { + "fileHeader": "myCustomHeader" + } + } + ] + } + } +} +``` + +Which should output a file that will start like this: + +```css title="variables.css" +/** + * Do not edit directly + * Generated on Thu, 18 Mar 2021 21:30:47 GMT + * hello? + * is it me you're looking for? + */ +``` + +For an in-depth example see the [custom-file-header](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) example. + +## Custom formats + +You can create custom formats using the [`registerFormat`](/reference/api#registerformat) function or by directly including them in your [configuration](/reference/config). A format has a name and a format function, which takes an object as the argument and should return a string which is then written to a file. + +### format + +`format.format(args)` ⇒ `unknown` + +The format function that is called when Style Dictionary builds files. + +:::tip +You might be wondering why the return type of a format function is `unknown`. +[More information about this here](#custom-return-types) +::: + +| Param | Type | Description | +| ------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------- | +| `args` | `Object` | A single argument to support named parameters and destructuring. | +| `args.dictionary` | `Dictionary` | Transformed Dictionary object containing allTokens, tokens and unfilteredTokens. | +| `args.dictionary.allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. | +| `args.dictionary.tokens` | `TransformedTokens` | All tokens, still in unflattened object format. | +| `args.dictionary.unfilteredAllTokens` | `TransformedToken[]` | Flattened array of all tokens, including tokens that were filtered out by filters. | +| `args.dictionary.unfilteredTokens` | `TransformedTokens` | All tokens, still in unflattened object format, including tokens that were filtered out by filters. | +| `args.platform` | `Platform` | [Platform config](/reference/config#platform) | +| `args.file` | `File` | [File config](/reference/config#file) | +| `args.options` | `Object` | Merged object with SD [Config](/reference/config#properties) & [FormatOptions](#format-configuration) | + +Example: + +```js +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary, platform, options, file }) { + return JSON.stringify(dictionary.tokens, null, 2); + }, +}); +``` + +--- + +To use your custom format, you call it by name in the file configuration object: + +```json +{ + "source": ["tokens/**/*.json"], + "platforms": { + "css": { + "options": { + "showFileHeader": true + }, + "transformGroup": "css", + "files": [ + { + "destination": "destination", + "format": "myCustomFormat", + "options": { + "showFileHeader": false + } + } + ] + } + } +} +``` + +It is recommended for any configuration needed for your custom format to use the `options` object. Style Dictionary will merge platform and file options so that in your Style Dictionary configuration you can specify options at a platform or file level. In the configuration above, the `options` object passed to the format would have `showFileHeader: false`. + +## Custom return types + +When writing outputs to the filesystem, the return type of the `format` function is always `string`. +However, since v4 you can return any data format and use [`SD.formatAllPlatforms`](/reference/api#formatallplatforms) +or [`SD.formatPlatform`](/reference/api#formatplatform) methods when you do not intend to write the output to the filesystem, +but want to do something custom with the output instead. + +Note that when you have a format that returns something that isn't a string, you won't be able to use it with +[`buildPlatform`](/reference/api#buildplatform) or [`buildAllPlatforms`](/reference/api#buildallplatforms) methods, +because they are writing to the filesystem and you can't really write data to the filesystem that isn't a string/buffer/stream. + +This also means that the `destination` property is therefore optional for formats that aren't ran by the `build` methods: + +```json title="config.json" +{ + "source": ["tokens/**/*.json"], + "platforms": { + "css": { + "options": { + "showFileHeader": true + }, + "transformGroup": "css", + "files": [ + { + "format": "format-that-returns-array" + } + ] + } + } +} +``` + +```js title="grabTokens.js" +const sd = new StyleDictionary('config.json'); + +const cssTokens = (await sd.formatPlatform('css')).output; +/** + * Example: + * [ + * ["--colors-red-500", "#ff0000"], + * ["--colors-blue-500", "#0000ff"] + * ] + */ +``` + +## Custom format with output references + +To take advantage of outputting references in your custom formats there are 2 helper methods in the `dictionary` argument passed to your format function: `usesReference(value)` and `getReferences(value)`. Here is an example using those: + +```javascript title="build-tokens.js" +StyleDictionary.registerFormat({ + name: `es6WithReferences`, + format: function ({ dictionary }) { + return dictionary.allTokens + .map((token) => { + let value = JSON.stringify(token.value); + // the `dictionary` object now has `usesReference()` and + // `getReferences()` methods. `usesReference()` will return true if + // the value has a reference in it. `getReferences()` will return + // an array of references to the whole tokens so that you can access their + // names or any other attributes. + if (dictionary.usesReference(token.original.value)) { + // Note: make sure to use `token.original.value` because + // `token.value` is already resolved at this point. + const refs = dictionary.getReferences(token.original.value); + refs.forEach((ref) => { + value = value.replace(ref.value, function () { + return `${ref.name}`; + }); + }); + } + return `export const ${token.name} = ${value};`; + }) + .join(`\n`); + }, +}); +``` + +--- + +## Using a template / templating engine to create a format + +Formats are functions and created easily with most templating engines. Formats can be built using templates if there is a lot of boilerplate code to insert (e.g. ObjectiveC files). If the output consists of only the values (e.g. a flat SCSS variables file), writing a format function directly may be easier. + +Any templating language can work as long as there is a node module for it. All you need to do is register a format that calls your template and returns a string. + +Our recommendation is to use Template Literals for this as the easiest way to accomplish this: + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +// Very simplistic/naive custom CSS format, just as an example, for CSS you should prefer using our predefined formats +const template = ({ dictionary, file, options, platform }) => `:root { +${dictionary.allTokens.map(token => ` ${token.name}`: `"${token.value}"`).join('\n')} +} +`; + +StyleDictionary.registerFormat({ + name: 'my/format', + format: template, +}); + +// format: 'my/format' is now available for use... +``` + +Here is a quick example for Lodash templates. + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import _ from 'lodash-es'; +import fs from 'node:fs'; + +const template = _.template(fs.readFileSync('templates/myFormat.template')); + +StyleDictionary.registerFormat({ + name: 'my/format', + format: template, +}); + +// format: 'my/format' is now available for use... +``` + +And another example for Handlebars. + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import Handlebars from 'handlebars'; + +const template = Handlebars.compile(fs.readFileSync('templates/MyTemplate.hbs').toString()); + +StyleDictionary.registerFormat({ + name: 'my/format', + format: function ({ dictionary, platform }) { + return template({ + tokens: dictionary.tokens, + options: platform, + }); + }, +}); + +// format: 'my/format' is now available for use... +``` diff --git a/docs/src/content/docs/reference/Hooks/Formats/predefined.md b/docs/src/content/docs/reference/Hooks/Formats/predefined.md new file mode 100644 index 000000000..3c43a7021 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Formats/predefined.md @@ -0,0 +1,912 @@ +--- +title: Built-in formats +--- + +These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/formats.js) + +Want a format? [You can request it here](https://github.com/amzn/style-dictionary/issues). + +You created a format and think it should be included? [Send us a PR](https://github.com/amzn/style-dictionary/pulls). + +### css/variables + +Creates a CSS file with variable definitions based on the style dictionary + +| Param | Type | Description | +| ---------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | +| `options.outputReferenceFallbacks` | `boolean` | Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the format function. | +| `options.selector` | `string` | Override the root css selector | +| `options.formatting` | `FormattingOptions` | Custom formatting properties that define parts of a declaration line in code. The configurable strings are: `prefix`, `indentation`, `separator`, `suffix`, `lineSeparator`, `fileHeaderTimestamp`, `header`, `footer`, `commentStyle` and `commentPosition`. Those are used to generate a line like this: `${indentation}${prefix}${token.name}${separator} ${prop.value}${suffix}`. The remaining formatting options are used for the fileHeader helper. | + +Example: + +```css title="variables.css" +:root { + --color-background-base: #f0f0f0; + --color-background-alt: #eeeeee; +} +``` + +--- + +### scss/map-flat + +Creates a SCSS file with a flat map based on the style dictionary + +Name the map by adding a `mapName` property on the `options` object property on the `file` object property in your config. + +Example: + +```scss title="vars.scss" +$tokens: ( + 'color-background-base': #f0f0f0; 'color-background-alt': #eeeeee;, +); +``` + +--- + +### scss/map-deep + +Creates a SCSS file with a deep map based on the style dictionary. + +Name the map by adding a `mapName` property on the `options` object property on the `file` object property in your config. + +| Param | Type | Description | +| ---------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | +| `options.outputReferenceFallbacks` | `boolean` | Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the format function. | +| `options.themeable` | `boolean` | Whether or not tokens should default to being themeable, if not otherwise specified per token. Defaults to `false`. | +| `options.mapName` | `string` | Name of your SCSS map. | +| `options.formatting` | `FormattingOptions` | Custom formatting properties that define parts of a declaration line in code. The configurable strings are: `prefix`, `indentation`, `separator`, `suffix`, `lineSeparator`, `fileHeaderTimestamp`, `header`, `footer`, `commentStyle` and `commentPosition`. Those are used to generate a line like this: `${indentation}${prefix}${token.name}${separator} ${prop.value}${suffix}`. The remaining formatting options are used for the fileHeader helper. | + +Example: + +```scss title="vars.scss" +$color-background-base: #f0f0f0 !default; +$color-background-alt: #eeeeee !default; + +$tokens: ( + 'color': ( + 'background': ( + 'base': $color-background-base, + 'alt': $color-background-alt, + ), + ), +); +``` + +--- + +### scss/variables + +Creates a SCSS file with variable definitions based on the style dictionary. + +Add `!default` to any variable by setting a `themeable: true` attribute in the token's definition. + +| Param | Type | Description | +| ---------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | +| `options.outputReferenceFallbacks` | `boolean` | Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the format function. | +| `options.themeable` | `boolean` | Whether or not tokens should default to being themeable, if not otherwise specified per token. Defaults to `false`. | +| `options.formatting` | `FormattingOptions` | Custom formatting properties that define parts of a declaration line in code. The configurable strings are: `prefix`, `indentation`, `separator`, `suffix`, `lineSeparator`, `fileHeaderTimestamp`, `header`, `footer`, `commentStyle` and `commentPosition`. Those are used to generate a line like this: `${indentation}${prefix}${token.name}${separator} ${prop.value}${suffix}`. The remaining formatting options are used for the fileHeader helper. | + +Example: + +```scss title="vars.scss" +$color-background-base: #f0f0f0; +$color-background-alt: #eeeeee !default; +``` + +--- + +### scss/icons + +Creates a SCSS file with variable definitions and helper classes for icons + +Example: + +```scss title="vars.scss" +$content-icon-email: '\E001'; +.icon.email:before { + content: $content-icon-email; +} +``` + +--- + +### less/variables + +Creates a LESS file with variable definitions based on the style dictionary + +| Param | Type | Description | +| ---------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | +| `options.outputReferenceFallbacks` | `boolean` | Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the format function. | +| `options.formatting` | `FormattingOptions` | Custom formatting properties that define parts of a declaration line in code. The configurable strings are: `prefix`, `indentation`, `separator`, `suffix`, `lineSeparator`, `fileHeaderTimestamp`, `header`, `footer`, `commentStyle` and `commentPosition`. Those are used to generate a line like this: `${indentation}${prefix}${token.name}${separator} ${prop.value}${suffix}`. The remaining formatting options are used for the fileHeader helper. | + +Example: + +```less title="vars.less" +@color-background-base: #f0f0f0; +@color-background-alt: #eeeeee; +``` + +--- + +### less/icons + +Creates a LESS file with variable definitions and helper classes for icons + +Example: + +```less title="vars.less" +@content-icon-email: '\E001'; +.icon.email:before { + content: @content-icon-email; +} +``` + +--- + +### stylus/variables + +Creates a Stylus file with variable definitions based on the style dictionary + +Example: + +```stylus title="vars.stylus" +$color-background-base= #f0f0f0; +$color-background-alt= #eeeeee; +``` + +--- + +### javascript/module + +Creates a CommonJS module with the whole style dictionary + +Example: + +```js title="vars.cjs" +module.exports = { + color: { + base: { + red: { + value: '#ff0000', + }, + }, + }, +}; +``` + +--- + +### javascript/module-flat + +Creates a CommonJS module with the whole style dictionary flattened to a single level. + +Example: + +```js title="vars.cjs" +module.exports = { + ColorBaseRed: '#ff0000', +}; +``` + +--- + +### javascript/object + +Creates a JS file a global var that is a plain javascript object of the style dictionary. +Name the variable by adding a `name` property on the `options` object property of the `file` object property in your config. + +Example: + +```js title="vars.js" +var StyleDictionary = { + color: { + base: { + red: { + value: '#ff0000', + }, + }, + }, +}; +``` + +--- + +### javascript/umd + +Creates a [UMD](https://github.com/umdjs/umd) module of the style +dictionary. Name the module by adding a `name` property on the `options` object property of the `file` object property in your config. + +Example + +```js title="vars.js" +(function (root, factory) { + if (typeof module === 'object' && module.exports) { + module.exports = factory(); + } else if (typeof exports === 'object') { + exports['_styleDictionary'] = factory(); + } else if (typeof define === 'function' && define.amd) { + define([], factory); + } else { + root['_styleDictionary'] = factory(); + } +})(this, function () { + return { + color: { + red: { + value: '#FF0000', + }, + }, + }; +}); +``` + +--- + +### javascript/es6 + +Creates a ES6 module of the style dictionary. + +```json title="config.json" +{ + "platforms": { + "js": { + "transformGroup": "js", + "files": [ + { + "format": "javascript/es6", + "destination": "colors.js", + "filter": { + "type": "color" + } + } + ] + } + } +} +``` + +Example: + +```js title="vars.js" +export const ColorBackgroundBase = '#ffffff'; +export const ColorBackgroundAlt = '#fcfcfcfc'; +``` + +--- + +### typescript/es6-declarations + +Creates TypeScript declarations for ES6 modules + +```json title="config.json" +{ + "platforms": { + "ts": { + "transformGroup": "js", + "files": [ + { + "format": "javascript/es6", + "destination": "colors.js" + }, + { + "format": "typescript/es6-declarations", + "destination": "colors.d.ts" + } + ] + } + } +} +``` + +| Param | Type | Description | +| ------------------------------ | --------- | ------------------------------------------------------------------------------ | +| `options` | `Object` | | +| `options.outputStringLiterals` | `boolean` | Whether or not to output literal types for string values. Defaults to `false`. | + +Example: + +```typescript title="vars.ts" +export const ColorBackgroundBase: string; +export const ColorBackgroundAlt: string; +``` + +--- + +### typescript/module-declarations + +Creates TypeScript declarations for module + +```json title="config.json" +{ + "platforms": { + "ts": { + "transformGroup": "js", + "files": [ + { + "format": "javascript/module", + "destination": "colors.js" + }, + { + "format": "typescript/module-declarations", + "destination": "colors.d.ts" + } + ] + } + } +} +``` + +Example: + +```typescript title="vars.ts" +export default tokens; +declare interface DesignToken { + value?: any; + type?: string; + name?: string; + comment?: string; + themeable?: boolean; + attributes?: Record; + [key: string]: any; +} +declare const tokens: { + color: { + red: DesignToken; + }; +}; +``` + +As you can see above example output this does not generate 100% accurate d.ts. +This is a compromise between of what style-dictionary can do to help and not bloating the library with rarely used dependencies. + +Thankfully you can extend style-dictionary very easily: + +```js title="build-tokens.js" +import JsonToTS from 'json-to-ts'; + +StyleDictionaryPackage.registerFormat({ + name: 'typescript/accurate-module-declarations', + format: function ({ dictionary }) { + return ( + 'declare const root: RootObject\n' + + 'export default root\n' + + JsonToTS(dictionary.tokens).join('\n') + ); + }, +}); +``` + +--- + +### android/resources + +Creates a [resource](https://developer.android.com/guide/topics/resources/providing-resources) xml file. It is recommended to use a filter with this format +as it is generally best practice in Android development to have resource files +organized by type (color, dimension, string, etc.). However, a resource file +with mixed resources will still work. + +This format will try to use the proper resource type for each token based on +the category (color => color, size => dimen, etc.). However if you want to +force a particular resource type you can provide a `resourceType` property on the `options` +object property on the `file` object property configuration. +You can also provide a `resourceMap` if you +don't use Style Dictionary's built-in CTI structure. + +| Param | Type | Description | +| -------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | + +Example: + +```xml title="resources.xml" + + + #fffaf3f2 + #fff0cccc + 14sp +``` + +--- + +### android/colors + +Creates a color resource xml file with all the colors in your style dictionary. + +It is recommended to use the 'android/resources' format with a custom filter +instead of this format: + +```javascript title="config.js" +format: 'android/resources', +filter: { + type: "color" +} +``` + +Example: + +```xml title="resources.xml" + + + #fffaf3f2 + #fff0cccc + #ffe19d9c +``` + +--- + +### android/dimens + +Creates a dimen resource xml file with all the sizes in your style dictionary. + +It is recommended to use the 'android/resources' format with a custom filter +instead of this format: + +```javascript title="config.js" +format: 'android/resources', +filter: { + type: "dimension" +} +``` + +Example: + +```xml title="dimens.xml" + + + 5.00dp + 10.00dp + 15.00dp +``` + +--- + +### android/fontDimens + +Creates a dimen resource xml file with all the font sizes in your style dictionary. + +It is recommended to use the 'android/resources' format with a custom filter +instead of this format: + +```javascript title="config.js" +format: 'android/resources', +filter: { + type: "dimension" +} +``` + +Example: + +```xml title="font-dimens.xml" + + + 10.00sp + 13.00sp + 15.00sp +``` + +--- + +### android/integers + +Creates a resource xml file with all the integers in your style dictionary. It filters your +design tokens by `token.type === 'time'` + +It is recommended to use the 'android/resources' format with a custom filter +instead of this format: + +```javascript title="config.js" +format: 'android/resources', +filter: { + type: 'time' +} +``` + +Example: + +```xml title="integers.xml" + + + 1000 + 2000 + 4000 +``` + +--- + +### android/strings + +Creates a resource xml file with all the strings in your style dictionary. Filters your +design tokens by `token.type === 'content'` + +It is recommended to use the 'android/resources' format with a custom filter +instead of this format: + +```javascript title="config.js" +format: 'android/resources', +filter: { + type: 'content' +} +``` + +Example: + +```xml title="icons.xml" + + + + + +``` + +--- + +### compose/object + +Creates a Kotlin file for Compose containing an object with a `val` for each property. + +| Param | Type | Description | +| ----- | ---- | ----------- | + +| `options` | `Object` | | +| `options.import` | `string[] \| string` | Modules to import. Can be a string or array of strings. Defaults to `['androidx.compose.ui.graphics.Color', 'androidx.compose.ui.unit.*']`. | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | +| `options.className` | `string` | The name of the generated Kotlin object | +| `options.packageName` | `string` | The package for the generated Kotlin object | + +Example: + +```kotlin title="vars.kt" +package com.example.tokens; + +import androidx.compose.ui.graphics.Color + +object StyleDictionary { + val colorBaseRed5 = Color(0xFFFAF3F2) +} +``` + +--- + +### ios/macros + +Creates an Objective-C header file with macros for design tokens + +Example: + +```swift title="macros.swift" +#import +#import + +#define ColorFontLink [UIColor colorWithRed:0.00f green:0.47f blue:0.80f alpha:1.00f] +#define SizeFontTiny 176.00f +``` + +--- + +### ios/plist + +Creates an Objective-C plist file + +**Todo** + +- Fix this template and add example and usage + +--- + +### ios/singleton.m + +Creates an Objective-C implementation file of a style dictionary singleton class + +**Todo** + +- Add example and usage + +--- + +### ios/singleton.h + +Creates an Objective-C header file of a style dictionary singleton class + +**Todo** + +- Add example and usage + +--- + +### ios/static.h + +Creates an Objective-C header file of a static style dictionary class + +**Todo** + +- Add example and usage + +--- + +### ios/static.m + +Creates an Objective-C implementation file of a static style dictionary class + +**Todo** + +- Add example and usage + +--- + +### ios/colors.h + +Creates an Objective-C header file of a color class + +**Todo** + +- Add example and usage + +--- + +### ios/colors.m + +Creates an Objective-C implementation file of a color class + +**Todo** + +- Add example and usage + +--- + +### ios/strings.h + +Creates an Objective-C header file of strings + +**Todo** + +- Add example and usage + +--- + +### ios/strings.m + +Creates an Objective-C implementation file of strings + +**Todo** + +- Add example and usage + +--- + +### ios-swift/class.swift + +Creates a Swift implementation file of a class with values. It adds default `class` object type, `public` access control and `UIKit` import. + +| Param | Type | Description | +| -------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.accessControl` | `string` | Level of [access](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) of the generated swift object. Defaults to `public`. | +| `options.import` | `string[] \| string` | Modules to import. Can be a string or array of strings. Defaults to `'UIKit'`. | +| `options.className` | `string` | The name of the generated Kotlin object | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | + +Example: + +```swift title="colors.swift" +public class StyleDictionary { + public static let colorBackgroundDanger = UIColor(red: 1.000, green: 0.918, blue: 0.914, alpha: 1) +} +``` + +--- + +### ios-swift/enum.swift + +Creates a Swift implementation file of an enum with values. It adds default `enum` object type, `public` access control and `UIKit` import. + +| Param | Type | Description | +| -------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.accessControl` | `string` | Level of [access](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) of the generated swift object. Defaults to `public`. | +| `options.import` | `string[] \| string` | Modules to import. Can be a string or array of strings. Defaults to `'UIKit'`. | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | + +Example: + +```swift title="colors.swift" +public enum StyleDictionary { + public static let colorBackgroundDanger = UIColor(red: 1.000, green: 0.918, blue: 0.914, alpha: 1) +} +``` + +--- + +### ios-swift/any.swift + +Creates a Swift implementation file of any given type with values. It has by default `class` object type, `public` access control and `UIKit` import. + +```javascript title="config.js" +format: 'ios-swift/any.swift', +import: ['UIKit', 'AnotherModule'], +objectType: 'struct', +accessControl: 'internal', +``` + +| Param | Type | Description | +| -------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.accessControl` | `string` | Level of [access](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) of the generated swift object. Defaults to `public`. | +| `options.import` | `string[] \| string` | Modules to import. Can be a string or array of strings. Defaults to `'UIKit'`. | +| `options.objectType` | `string` | The type of the generated Swift object. Defaults to `'class'`. | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | + +Example: + +```swift title="colors.swift" +import UIKit +import AnotherModule + +internal struct StyleDictionary { + internal static let colorBackgroundDanger = UIColor(red: 1.000, green: 0.918, blue: 0.914, alpha: 1) +} +``` + +--- + +### css/fonts.css + +Creates CSS file with @font-face declarations + +**Todo** + +- Add example and usage + +--- + +### json + +Creates a JSON file of the style dictionary. + +Example: + +```json title="vars.json" +{ + "color": { + "base": { + "red": { + "value": "#ff0000" + } + } + } +} +``` + +--- + +### json/asset + +Creates a JSON file of the assets defined in the style dictionary. + +Example: + +```json title="assets.json" +{ + "asset": { + "image": { + "logo": { + "value": "assets/logo.png" + } + } + } +} +``` + +--- + +### json/nested + +Creates a JSON nested file of the style dictionary. + +Example: + +```json title="vars.json" +{ + "color": { + "base": { + "red": "#ff0000" + } + } +} +``` + +--- + +### json/flat + +Creates a JSON flat file of the style dictionary. + +Example: + +```json title="vars.json" +{ + "color-base-red": "#ff0000" +} +``` + +--- + +### sketch/palette + +Creates a sketchpalette file of all the base colors + +Example: + +```json title="palette.json" +{ + "compatibleVersion": "1.0", + "pluginVersion": "1.1", + "colors": ["#ffffff", "#ff0000", "#fcfcfc"] +} +``` + +--- + +### sketch/palette/v2 + +Creates a sketchpalette file compatible with version 2 of +the sketchpalette plugin. To use this you should use the +'color/sketch' transform to get the correct value for the colors. + +Example: + +```json title="palette-2.json" +{ + "compatibleVersion": "2.0", + "pluginVersion": "2.2", + "colors": [ + { "name": "red", "r": 1.0, "g": 0.0, "b": 0.0, "a": 1.0 }, + { "name": "green", "r": 0.0, "g": 1.0, "b": 0.0, "a": 1.0 }, + { "name": "blue", "r": 0.0, "g": 0.0, "b": 1.0, "a": 1.0 } + ] +} +``` + +--- + +### flutter/class.dart + +Creates a Dart implementation file of a class with values + +| Param | Type | Description | +| -------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | + +Example: + +```dart title="tokens.dart" +import 'package:flutter/material.dart'; + +class StyleDictionary { + StyleDictionary._(); + + static const colorBrandPrimary = Color(0x00ff5fff); + static const sizeFontSizeMedium = 16.00; + static const contentFontFamily1 = "NewJune"; +``` + +--- diff --git a/docs/src/content/docs/reference/Hooks/Transform Groups/index.md b/docs/src/content/docs/reference/Hooks/Transform Groups/index.md new file mode 100644 index 000000000..e51a499a0 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Transform Groups/index.md @@ -0,0 +1,40 @@ +--- +title: Transform Groups +sidebar: + label: Overview +--- + +Transform Groups are a way to easily use multiple transforms at once as a collection or group. +They are an array of transforms. You can define a custom transform group with the [`registerTransformGroup`](/reference/api#registertransformgroup). + +You use transformGroups in your config file under `platforms` > `[platform]` > `transformGroup` + +```json title="config.json" +{ + "source": ["tokens/**/*.json"], + "platforms": { + "android": { + "transformGroup": "android" + } + } +} +``` + +## Combining with transforms + +You can also combine transforms with transformGroup: + +```json title="config.json" +{ + "source": ["tokens/**/*.json"], + "platforms": { + "android": { + "transformGroup": "android", + "transforms": ["name/snake"] + } + } +} +``` + +The transforms that are standalone will be added **after** the ones inside the transformGroup. +If it's important to determine the order of these yourself, you can always register a custom transformGroup to have more granular control. diff --git a/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md b/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md new file mode 100644 index 000000000..2479137b2 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md @@ -0,0 +1,213 @@ +--- +title: Built-in Transform Groups +--- + +:::tip +You can find the source code of the built-in transforms here: +[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transformGroups.js) +::: + +### web + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/kebab](/reference/hooks/transforms/predefined#namekebab) +[size/px](/reference/hooks/transforms/predefined#sizepx) +[color/css](/reference/hooks/transforms/predefined#colorcss) + +--- + +### js + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/pascal](/reference/hooks/transforms/predefined#namepascal) +[size/rem](/reference/hooks/transforms/predefined#sizerem) +[color/hex](/reference/hooks/transforms/predefined#colorhex) + +--- + +### scss + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/kebab](/reference/hooks/transforms/predefined#namekebab) +[time/seconds](/reference/hooks/transforms/predefined#timeseconds) +[html/icon](/reference/hooks/transforms/predefined#htmlicon) +[size/rem](/reference/hooks/transforms/predefined#sizerem) +[color/css](/reference/hooks/transforms/predefined#colorcss) +[asset/url](/reference/hooks/transforms/predefined#asseturl) +[fontFamily/css](/reference/hooks/transforms/predefined#fontfamilycss) +[cubicBezier/css](/reference/hooks/transforms/predefined#cubicbeziercss) +[strokeStyle/css/shorthand](/reference/hooks/transforms/predefined#strokestylecssshorthand) +[border/css/shorthand](/reference/hooks/transforms/predefined#bordercssshorthand) +[typography/css/shorthand](/reference/hooks/transforms/predefined#typographycssshorthand) +[transition/css/shorthand](/reference/hooks/transforms/predefined#transitioncssshorthand) +[shadow/css/shorthand](/reference/hooks/transforms/predefined#shadowcssshorthand) + +--- + +### css + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/kebab](/reference/hooks/transforms/predefined#namekebab) +[time/seconds](/reference/hooks/transforms/predefined#timeseconds) +[html/icon](/reference/hooks/transforms/predefined#htmlicon) +[size/rem](/reference/hooks/transforms/predefined#sizerem) +[color/css](/reference/hooks/transforms/predefined#colorcss) +[asset/url](/reference/hooks/transforms/predefined#asseturl) +[fontFamily/css](/reference/hooks/transforms/predefined#fontfamilycss) +[cubicBezier/css](/reference/hooks/transforms/predefined#cubicbeziercss) +[strokeStyle/css/shorthand](/reference/hooks/transforms/predefined#strokestylecssshorthand) +[border/css/shorthand](/reference/hooks/transforms/predefined#bordercssshorthand) +[typography/css/shorthand](/reference/hooks/transforms/predefined#typographycssshorthand) +[transition/css/shorthand](/reference/hooks/transforms/predefined#transitioncssshorthand) +[shadow/css/shorthand](/reference/hooks/transforms/predefined#shadowcssshorthand) + +--- + +### less + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/kebab](/reference/hooks/transforms/predefined#namekebab) +[time/seconds](/reference/hooks/transforms/predefined#timeseconds) +[html/icon](/reference/hooks/transforms/predefined#htmlicon) +[size/rem](/reference/hooks/transforms/predefined#sizerem) +[color/hex](/reference/hooks/transforms/predefined#colorhex) +[asset/url](/reference/hooks/transforms/predefined#asseturl) +[fontFamily/css](/reference/hooks/transforms/predefined#fontfamilycss) +[cubicBezier/css](/reference/hooks/transforms/predefined#cubicbeziercss) +[strokeStyle/css/shorthand](/reference/hooks/transforms/predefined#strokestylecssshorthand) +[border/css/shorthand](/reference/hooks/transforms/predefined#bordercssshorthand) +[typography/css/shorthand](/reference/hooks/transforms/predefined#typographycssshorthand) +[transition/css/shorthand](/reference/hooks/transforms/predefined#transitioncssshorthand) +[shadow/css/shorthand](/reference/hooks/transforms/predefined#shadowcssshorthand) + +--- + +### html + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[attribute/color](/reference/hooks/transforms/predefined#attributecolor) +[name/human](/reference/hooks/transforms/predefined#namehuman) + +--- + +### android + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/snake](/reference/hooks/transforms/predefined#namesnake) +[color/hex8android](/reference/hooks/transforms/predefined#colorhex8android) +[size/remToSp](/reference/hooks/transforms/predefined#sizeremtosp) +[size/remToDp](/reference/hooks/transforms/predefined#sizeremtodp) + +--- + +### compose + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/camel](/reference/hooks/transforms/predefined#namecamel) +[color/composeColor](/reference/hooks/transforms/predefined#colorcomposecolor) +[size/compose/em](/reference/hooks/transforms/predefined#sizecomposeem) +[size/compose/remToSp](/reference/hooks/transforms/predefined#sizecomposeremtosp) +[size/compose/remToDp](/reference/hooks/transforms/predefined#sizecomposeremtodp) + +--- + +### ios + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/pascal](/reference/hooks/transforms/predefined#namepascal) +[color/UIColor](/reference/hooks/transforms/predefined#coloruicolor) +[content/objC/literal](/reference/hooks/transforms/predefined#contentobjcliteral) +[asset/objC/literal](/reference/hooks/transforms/predefined#assetobjcliteral) +[size/remToPt](/reference/hooks/transforms/predefined#sizeremtopt) + +--- + +### ios-swift + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/camel](/reference/hooks/transforms/predefined#namecamel) +[color/UIColorSwift](/reference/hooks/transforms/predefined#coloruicolorswift) +[content/swift/literal](/reference/hooks/transforms/predefined#contentswiftliteral) +[asset/swift/literal](/reference/hooks/transforms/predefined#assetswiftliteral) +[size/swift/remToCGFloat](/reference/hooks/transforms/predefined#sizeswiftremtocgfloat) + +--- + +### ios-swift-separate + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/camel](/reference/hooks/transforms/predefined#namecamel) +[color/UIColorSwift](/reference/hooks/transforms/predefined#coloruicolorswift) +[content/swift/literal](/reference/hooks/transforms/predefined#contentswiftliteral) +[asset/swift/literal](/reference/hooks/transforms/predefined#assetswiftliteral) +[size/swift/remToCGFloat](/reference/hooks/transforms/predefined#sizeswiftremtocgfloat) + +This is to be used if you want to have separate files per category and you don't want the category (e.g., `color`) as the lead value in the name of the token (e.g., `StyleDictionaryColor.baseText` instead of `StyleDictionary.colorBaseText`). + +--- + +### assets + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) + +--- + +### flutter + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/camel](/reference/hooks/transforms/predefined#namecamel) +[color/hex8flutter](/reference/hooks/transforms/predefined#colorhex8flutter) +[size/flutter/remToDouble](/reference/hooks/transforms/predefined#sizeflutterremToDouble) +[content/flutter/literal](/reference/hooks/transforms/predefined#contentflutterliteral) +[asset/flutter/literal](/reference/hooks/transforms/predefined#assetflutterliteral) + +--- + +### flutter-separate + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/camel](/reference/hooks/transforms/predefined#namecamel) +[color/hex8flutter](/reference/hooks/transforms/predefined#colorhex8flutter) +[size/flutter/remToDouble](/reference/hooks/transforms/predefined#sizeflutterremToDouble) +[content/flutter/literal](/reference/hooks/transforms/predefined#contentflutterliteral) +[asset/flutter/literal](/reference/hooks/transforms/predefined#assetflutterliteral) + +This is to be used if you want to have separate files per category and you don't want the category (e.g., `color`) as the lead value in the name of the token (e.g., `StyleDictionaryColor.baseText` instead of `StyleDictionary.colorBaseText`). + +--- + +### react-native + +Transforms: + +[name/camel](/reference/hooks/transforms/predefined#namecamel) +[size/object](/reference/hooks/transforms/predefined#sizeobject) +[color/css](/reference/hooks/transforms/predefined#colorcss) diff --git a/docs/src/content/docs/reference/Hooks/Transforms/index.md b/docs/src/content/docs/reference/Hooks/Transforms/index.md new file mode 100644 index 000000000..8fa28aed8 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Transforms/index.md @@ -0,0 +1,139 @@ +--- +title: Transforms +sidebar: + label: Overview +--- + +Transforms are functions that modify a [token](/info/tokens) so that it can be understood by a specific platform. It can modify the name, value, or attributes of a token - enabling each platform to use the design token in different ways. A simple example is changing pixel values to point values for iOS and `dp` or `sp` for Android. + +Transforms are isolated per platform; each platform begins with the same design token and makes the modifications it needs without affecting other platforms. The order you use transforms matters because transforms are performed sequentially. Transforms are used in your [configuration](/reference/config), and can be either [pre-defined transforms](/reference/hooks/transforms/predefined) supplied by Style Dictionary or [custom transforms](#defining-custom-transforms). + +Some platform configuration attributes apply a broader effect over the transforms applied. For example, the `size/remToDp` transform will scale a number by 16, or by the value of `options.basePxFontSize` if it is present. Check individual transform documentation to see where this is applicable. + +## Using Transforms + +You use transforms in your config file under `platforms` > `[platform]` > `transforms`. + +```json title="config.json" +{ + "source": ["tokens/**/*.json"], + "platforms": { + "android": { + "transforms": ["attribute/cti", "name/kebab", "color/hex", "size/rem"] + } + } +} +``` + +A transform consists of 4 parts: `type`, `name`, `filter`, and `transform`. Transforms are run on all design tokens where the filter returns true. + +:::tip +If you don't provide a filter function, it will match all tokens. +::: + +:::note +`transform` functions can be async as well. +::: + +## Transform Types + +There are 3 types of transforms: `attribute`, `name`, and `value`. + +**Attribute:** An attribute transform adds to the attributes object on a design token. This is for including any meta-data about a design token such as it's CTI attributes or other information. + +**Name:** A name transform transforms the name of a design token. You should really only be applying one name transform because they will override each other if you use more than one. + +**Value:** The value transform is the most important as this is the one that modifies the value or changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a filter function that filter which tokens that transform runs on. This allows us to only run a color transform on only the colors and not every design token. + +## Defining Custom Transforms + +You can define custom transforms with the [`registerTransform`](/reference/api#registertransform). Style Dictionary adds some [default metadata](/info/tokens#default-design-token-metadata) to each design token to provide context that may be useful for some transforms. + +## Transitive Transforms + +You can define transitive transforms which allow you to transform a referenced value. Normally, value transforms only transform non-referenced values and because transforms happen before references are resolved, the transformed value is then used to resolve references. + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerTransform({ + type: `value`, + transitive: true, + name: `myTransitiveTransform`, + filter: (token, options) => {}, + transform: (token) => { + // token.value will be resolved and transformed at this point + }, +}); +``` + +There is one thing to be mindful of with transitive transforms. The token's value will be resolved and _transformed_ already at the time the transitive transform. What happens is Style Dictionary will transform and resolve values iteratively. First it will transform any non-referenced values, then it will resolve any references to non-referenced values, then it will try to transform any non-referenced values, and so on. Let's take a look at an example: + +```json title="tokens.json" +{ + "color": { + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}" }, + "error": { "value": "{color.danger}" } + } +} +``` + +Style dictionary will first transform the value of `color.red`, then resolve `color.danger` to the transformed `color.red` value. Then it will transform `color.danger` and resolve `color.error` to the transformed `color.danger`. Finally, it will transform `color.error` and see that there is nothing left to transform or resolve. + +This allows you to modify a reference that modifies another reference. For example: + +```json title="tokens.json" +{ + "color": { + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}", "darken": 0.75 }, + "error": { "value": "{color.danger}", "darken": 0.5 } + } +} +``` + +Using a custom transitive transform you could have `color.danger` darken `color.red` and `color.error` darken `color.danger`. The pre-defined transforms are _not transitive_ to be backwards compatible with Style Dictionary v2 - an upgrade should not cause breaking changes. + +### Defer transitive transformation manually + +It's also possible to control, inside a transitive transform's `transform` function, whether the transformation should be deferred until a later cycle of references resolution. +This is done by returning `undefined`, which basically means "I cannot currently do the transform due to a reference not yet being resolved". + +Imagine the following transform: + +```js title="build-tokens.js" +import { StyleDictionary } from 'style-dictionary'; +import { usesReferences } from 'style-dictionary/utils'; + +StyleDictionary.registerTransform({ + name: '', + type: 'value', + transitive: true, + transform: (token) => { + const darkenModifier = token.darken; + if (usesReferences(darkenModifier)) { + // defer this transform, because our darken value is a reference + return undefined; + } + return darken(token.value, darkenModifier); + }, +}); +``` + +Combined with the following tokens: + +```json title="tokens.json" +{ + "color": { + "darken": { "value": 0.5 }, + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}", "darken": "{darken}" } + } +} +``` + +Due to `token.darken` being a property that uses a reference, we need the ability to defer its transformation from within the transform, +since the transform is the only place where we know which token properties the transformation is reliant upon. + +If you want to learn more about transitive transforms, take a look at the [transitive transforms example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms). diff --git a/docs/src/content/docs/reference/Hooks/Transforms/predefined.md b/docs/src/content/docs/reference/Hooks/Transforms/predefined.md new file mode 100644 index 000000000..8f3c0a066 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/Transforms/predefined.md @@ -0,0 +1,748 @@ +--- +title: Built-in transforms +--- + +:::tip +You can find the source code of the built-in transforms here: +[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transforms.js) +::: + +:::note +All the pre-defined transforms included in Style Dictionary **up until version 3** were using the [CTI structure](/info/tokens#category-type-item) for matching tokens. +If you structure your design tokens differently you will need to write [custom transforms](/reference/hooks/transforms#defining-custom-transforms) or make sure the proper CTIs are on the attributes of your design tokens. + +From **version 4 onwards**, instead of using the CTI structure of a token object, we're determining the token's `type` by the `token.type` property. +Or, the `$type` property if you're using the [DTCG spec format](https://design-tokens.github.io/community-group/format/). + +So instead of using `token.attributes.category` (v3), you will now use `token.type` (v4). +::: + +### attribute/cti + +Adds: category, type, item, subitem, and state on the attributes object based on the location in the style dictionary. + +```js +// Matches: all +// Returns: +{ + "category": "color", + "type": "background", + "item": "button", + "subitem": "primary", + "state": "active" +} +``` + +--- + +### attribute/color + +Adds: hex, hsl, hsv, rgb, red, blue, green. + +```js +// Matches: token.type === 'color' +// Returns +{ + "hex": "009688", + "rgb": {"r": 0, "g": 150, "b": 136, "a": 1}, + "hsl": {"h": 174.4, "s": 1, "l": 0.294, "a": 1}, + "hsv": {"h": 174.4, "s": 1, "l": 0.588, "a": 1}, +} +``` + +--- + +### name/human + +Creates a human-friendly name + +```js +// Matches: All +// Returns: +'button primary'; +``` + +--- + +### name/camel + +Creates a camel case name. If you define a prefix on the platform in your config, it will prepend with your prefix + +```js +// Matches: all +// Returns: +'colorBackgroundButtonPrimaryActive'; +'prefixColorBackgroundButtonPrimaryActive'; +``` + +--- + +### name/kebab + +Creates a kebab case name. If you define a prefix on the platform in your config, it will prepend with your prefix + +```js +// Matches: all +// Returns: +'color-background-button-primary-active'; +'prefix-color-background-button-primary-active'; +``` + +--- + +### name/snake + +Creates a snake case name. If you define a prefix on the platform in your config, it will prepend with your prefix + +```js +// Matches: all +// Returns: +'color_background_button_primary_active'; +'prefix_color_background_button_primary_active'; +``` + +--- + +### name/constant + +Creates a constant-style name based on the full CTI of the token. If you define a prefix on the platform in your config, it will prepend with your prefix + +```js +// Matches: all +// Returns: +'COLOR_BACKGROUND_BUTTON_PRIMARY_ACTIVE'; +'PREFIX_COLOR_BACKGROUND_BUTTON_PRIMARY_ACTIVE'; +``` + +--- + +### name/pascal + +Creates a Pascal case name. If you define a prefix on the platform in your config, it will prepend with your prefix + +```js +// Matches: all +// Returns: +'ColorBackgroundButtonPrimaryActive'; +'PrefixColorBackgroundButtonPrimaryActive'; +``` + +--- + +### color/rgb + +Transforms the value into an RGB string + +```js +// Matches: token.type === 'color' +// Returns: +'rgb(0, 150, 136)'; +``` + +--- + +### color/hsl + +Transforms the value into an HSL string or HSLA if alpha is present. Better browser support than color/hsl-4 + +```js +// Matches: token.type === 'color' +// Returns: +'hsl(174, 100%, 29%)'; +'hsl(174, 100%, 29%, .5)'; +``` + +--- + +### color/hsl-4 + +Transforms the value into an HSL string, using fourth argument if alpha is present. + +```js +// Matches: token.type === 'color' +// Returns: +'hsl(174 100% 29%)'; +'hsl(174 100% 29% / .5)'; +``` + +--- + +### color/hex + +Transforms the value into an 6-digit hex string + +```js +// Matches: token.type === 'color' +// Returns: +'#009688'; +``` + +--- + +### color/hex8 + +Transforms the value into an 8-digit hex string + +```js +// Matches: token.type === 'color' +// Returns: +'#009688ff'; +``` + +--- + +### color/hex8android + +Transforms the value into an 8-digit hex string for Android because they put the alpha channel first + +```js +// Matches: token.type === 'color' +// Returns: +'#ff009688'; +``` + +--- + +### color/composeColor + +Transforms the value into a Color class for Compose + +```kotlin +// Matches: token.type === 'color' +// Returns: +Color(0xFF009688) +``` + +--- + +### color/UIColor + +Transforms the value into an UIColor class for iOS + +```objective-c +// Matches: token.type === 'color' +// Returns: +[UIColor colorWithRed:0.114f green:0.114f blue:0.114f alpha:1.000f] +``` + +--- + +### color/UIColorSwift + +Transforms the value into an UIColor swift class for iOS + +```swift +// Matches: token.type === 'color' +// Returns: +UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha: 0.6) +``` + +--- + +### color/ColorSwiftUI + +Transforms the value into an UIColor swift class for iOS + +```swift +// Matches: token.type === 'color' +// Returns: +Color(red: 0.667, green: 0.667, blue: 0.667, opacity: 0.6) +``` + +--- + +### color/css + +Transforms the value into a hex or rgb string depending on if it has transparency + +```css +// Matches: token.type === 'color' +// Returns: +#000000 +rgba(0,0,0,0.5) +``` + +--- + +### color/sketch + +Transforms a color into an object with red, green, blue, and alpha +attributes that are floats from 0 - 1. This object is how Sketch stores +colors. + +```js +// Matches: token.type === 'color' +// Returns: +{ + red: 0.5, + green: 0.5, + blue: 0.5, + alpha: 1 +} +``` + +--- + +### size/sp + +Transforms the value into a scale-independent pixel (sp) value for font sizes on Android. It will not scale the number. + +```js +// Matches: token.type === 'fontSize' +// Returns: +'10.0sp'; +``` + +--- + +### size/dp + +Transforms the value into a density-independent pixel (dp) value for non-font sizes on Android. It will not scale the number. + +```js +// Matches: token.type === 'fontSize' +// Returns: +'10.0dp'; +``` + +--- + +### size/object + +Transforms the value into a useful object ( for React Native support ) + +```js +// Matches: token.type === 'dimension' +// Returns: +{ + original: "10px", + number: 10, + decimal: 0.1, // 10 divided by 100 + scale: 160, // 10 times 16 +} +``` + +--- + +### size/remToSp + +Transforms the value from a REM size on web into a scale-independent pixel (sp) value for font sizes on Android. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). + +```js +// Matches: token.type === 'fontSize' +// Returns: +'16.0sp'; +``` + +--- + +### size/remToDp + +Transforms the value from a REM size on web into a density-independent pixel (dp) value for font sizes on Android. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). + +```js +// Matches: token.type === 'fontSize' +// Returns: +'16.0dp'; +``` + +--- + +### size/px + +Adds 'px' to the end of the number. Does not scale the number + +```js +// Matches: token.type === 'dimension' +// Returns: +'10px'; +``` + +--- + +### size/rem + +Adds 'rem' to the end of the number. Does not scale the number + +```js +// Matches: token.type === 'dimension' +// Returns: +'10rem'; +``` + +--- + +### size/remToPt + +Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'pt' to the end. + +```js +// Matches: token.type === 'dimension' +// Returns: +'16pt'; +``` + +--- + +### size/compose/remToSp + +Transforms the value from a REM size on web into a scale-independent pixel (sp) value for font sizes in Compose. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). + +```kotlin +// Matches: token.type === 'fontSize' +// Returns: +"16.0.sp" +``` + +--- + +### size/compose/remToDp + +Transforms the value from a REM size on web into a density-independent pixel (dp) value for font sizes in Compose. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). + +```kotlin +// Matches: token.type === 'fontSize' +// Returns: +"16.0.dp" +``` + +--- + +### size/compose/em + +Adds the .em Compose extension to the end of a number. Does not scale the value + +```kotlin +// Matches: token.type === 'fontSize' +// Returns: +"16.0em" +``` + +--- + +### size/swift/remToCGFloat + +Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Swift and initializes a CGFloat + +```js +// Matches: token.type === 'dimension' +// Returns: "CGFloat(16.00)"" +``` + +--- + +### size/remToPx + +Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'px' to the end. + +```js +// Matches: token.type === 'dimension' +// Returns: +'16px'; +``` + +--- + +### size/pxToRem + +Scales non-zero numbers to rem, and adds 'rem' to the end. If you define a "basePxFontSize" on the platform in your config, it will be used to scale the value, otherwise 16 (default web font size) will be used. + +```js +// Matches: token.type === 'dimension' +// Returns: +'0'; +'1rem'; +``` + +--- + +### html/icon + +Takes an HTML entity and transforms it into a form CSS can use. + +```js +// Matches: token.type === 'html' +// Returns: +"'\\E001'"; +``` + +--- + +### content/quote + +Wraps the value in a single quoted string + +```js +// Matches: token.type === 'content' +// Returns: +"'string'"; +``` + +--- + +### content/objC/literal + +Wraps the value in a double-quoted string and prepends an '@' to make a string literal. + +```objective-c +// Matches: token.type === 'content' +// Returns: +**"string"**: +``` + +--- + +### content/swift/literal + +Wraps the value in a double-quoted string to make a string literal. + +```swift +// Matches: token.type === 'content' +// Returns: +"string" +``` + +--- + +### time/seconds + +Assumes a time in miliseconds and transforms it into a decimal + +```js +// Matches: token.type === 'time' +// Returns: +'0.5s'; +``` + +--- + +### fontFamily/css + +Transforms `fontFamily` type token (which can be an array) into a CSS string, putting single quotes around font names that contain spaces where necessary. +Also handles the `fontFamily` property inside `typography` type object-values. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#font-family) + +```css +/** + * Matches: token.type === 'fontFamily' || token.type === 'typography' + * Returns: + */ +:root { + --var: 'Arial Black', Helvetica, sans-serif; +} +``` + +--- + +### cubicBezier/css + +Transforms `cubicBezier` type token into a CSS string, using the CSS `cubic-bezier` function. +Also handles the `timingFunction` property inside `transition` type object-values. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#cubic-bezier) + +```css +/** + * Matches: token.type === 'cubicBezier' || token.type === 'transition' + * Returns: + */ +:root { + --var: cubic-bezier(0, 0, 0.5, 1); +} +``` + +--- + +### strokeStyle/css/shorthand + +Transforms `strokeStyle` type object-value token into a CSS string, using the CSS `dashed` fallback. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#stroke-style) + +```css +/** + * Matches: token.type === 'strokeStyle' + * Returns: + */ +:root { + --var: dashed; +} +``` + +--- + +### border/css/shorthand + +Transforms `border` type object-value token into a CSS string, using the CSS `border` shorthand notation. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#border) + +```css +/** + * Matches: token.type === 'border' + * Returns: + */ +:root { + --var: 2px solid #000000; +} +``` + +--- + +### typography/css/shorthand + +Transforms `typography` type object-value token into a CSS string, using the CSS `font` shorthand notation. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#typography) + +```css +/** + * Matches: token.type === 'typography' + * Returns: + */ +:root { + --var: italic 400 1.2rem/1.5 'Fira Sans', sans-serif; +} +``` + +--- + +### transition/css/shorthand + +Transforms `transition` type object-value token into a CSS string, using the CSS `transition` shorthand notation. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#transition) + +```css +/** + * Matches: token.type === 'transition' + * Returns: + */ +:root { + --var: 200ms ease-in-out 50ms; +} +``` + +--- + +### shadow/css/shorthand + +Transforms `shadow` type object-value token (which can also be an array) into a CSS string, using the CSS `shadow` shorthand notation. + +[DTCG definition](https://design-tokens.github.io/community-group/format/#shadow) + +```css +/** + * Matches: token.type === 'shadow' + * Returns: + */ +:root { + --var: 2px 4px 8px 10px #000000, 1px 1px 4px #cccccc; +} +``` + +--- + +### asset/url + +Wraps the value in a [CSS `url()` function](https://developer.mozilla.org/en-US/docs/Web/CSS/url) + +```js +// Matches: token.type === 'asset' +// Returns: +url('https://www.example.com/style.css'); +``` + +--- + +### asset/base64 + +Wraps the value in a double-quoted string and prepends an '@' to make a string literal. + +```js +// Matches: token.type === 'asset' +// Returns: +'IyBlZGl0b3Jjb25maWcub3JnCnJvb3QgPSB0cnVlCgpbKl0KaW5kZW50X3N0eWxlID0gc3BhY2UKaW5kZW50X3NpemUgPSAyCmVuZF9vZl9saW5lID0gbGYKY2hhcnNldCA9IHV0Zi04CnRyaW1fdHJhaWxpbmdfd2hpdGVzcGFjZSA9IHRydWUKaW5zZXJ0X2ZpbmFsX25ld2xpbmUgPSB0cnVlCgpbKi5tZF0KdHJpbV90cmFpbGluZ193aGl0ZXNwYWNlID0gZmFsc2U='; +``` + +--- + +### asset/path + +Prepends the local file path + +```js +// Matches: token.type === 'asset' +// Returns: +'path/to/file/asset.png'; +``` + +--- + +### asset/objC/literal + +Wraps the value in a double-quoted string and prepends an '@' to make a string literal. + +```objective-c +// Matches: token.type === 'asset' +// Returns: @"string" +``` + +--- + +### asset/swift/literal + +Wraps the value in a double-quoted string to make a string literal. + +```swift +// Matches: token.type === 'asset' +// Returns: "string" +``` + +--- + +### color/hex8flutter + +Transforms the value into a Flutter Color object using 8-digit hex with the alpha chanel on start + +```js +// Matches: token.type === 'color' +// Returns: +Color(0xff00ff5f); +``` + +--- + +### content/flutter/literal + +Wraps the value in a double-quoted string to make a string literal. + +```dart +// Matches: token.type === 'content' +// Returns: "string" +``` + +--- + +### asset/flutter/literal + +Wraps the value in a double-quoted string to make a string literal. + +```dart +// Matches: token.type === 'asset' +// Returns: "string" +``` + +--- + +### size/flutter/remToDouble + +Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Flutter + +```dart +// Matches: token.type === 'dimension' +// Returns: 16.00 +``` + +--- diff --git a/docs/actions.md b/docs/src/content/docs/reference/Hooks/actions.md similarity index 79% rename from docs/actions.md rename to docs/src/content/docs/reference/Hooks/actions.md index 62b279d37..639ef6470 100644 --- a/docs/actions.md +++ b/docs/src/content/docs/reference/Hooks/actions.md @@ -1,12 +1,10 @@ - -# Actions +--- +title: Actions +--- Actions provide a way to run custom build code such as generating binary assets like images. -Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](api.md?id=registeraction). +Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](/reference/api#registeraction). You use actions in your config file under platforms > [platform] > actions @@ -23,26 +21,20 @@ You use actions in your config file under platforms > [platform] > actions } ``` - ----- +--- ## Pre-defined Actions [lib/common/actions.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/actions.js) -### android/copyImages - +### android/copyImages Action to copy images into appropriate android directories. +--- -* * * - -### copy_assets - +### copy_assets Action that copies everything in the assets directory to a new assets directory in the build path of the platform. - -* * * - +--- diff --git a/docs/src/content/docs/reference/Hooks/file-headers.md b/docs/src/content/docs/reference/Hooks/file-headers.md new file mode 100644 index 000000000..f303a49f6 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/file-headers.md @@ -0,0 +1,145 @@ +--- +title: File Headers +--- + +File headers is a hook that provides a way to configure the header of output files. + +```css title="_variables.css" +/** + * This is a file header! + */ +:root { + --foo-bar: 4px; +} +``` + +--- + +## File header structure + +A file header is an object with two props: + +- `name`: the name of the file header +- `fileHeader`: a callback function that receives the default message array of strings, usually set by the format, and returns an array of strings (message lines) or a Promise with an array of strings. + +The array of strings will be concatenated using newline separator. + +```javascript title="my-fileheader.js" +const myFileHeader = { + name: 'my-file-header', + // async is optional + fileHeader: async (defaultMessages = []) => { + return [...defaultMessages, 'Do not edit please', 'Auto-generated on...']; + }, +}; +``` + +--- + +## Using file headers + +First you will need to tell Style Dictionary about your file header. You can do this in two ways: + +1. Using the [`.registerFileHeader`](/reference/api#registerfileheader) method +1. Inline in the [configuration](/reference/config#properties) `hooks.fileHeaders` property + +### .registerFileHeader + +```javascript +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerFileHeader(myFileHeader); +``` + +### Inline + +```javascript +export default { + hooks: { + fileHeaders: { + 'my-file-header': myFileHeader, + }, + }, + // ... the rest of the configuration +}; +``` + +### Applying it in config + +File-specific: + +```json +{ + "source": ["**/*.tokens.json"], + "platforms": { + "css": { + "transformGroup": "css", + "files": [ + { + "format": "css/variables", + "destination": "_variables.css", + "options": { + "fileHeader": "my-file-header" + } + } + ] + } + } +} +``` + +or platform-specific: + +```json +{ + "source": ["**/*.tokens.json"], + "platforms": { + "css": { + "transformGroup": "css", + "options": { + "fileHeader": "my-file-header" + }, + "files": [ + { + "format": "css/variables", + "destination": "_variables.css" + } + ] + } + } +} +``` + +--- + +### Example + +~ sd-playground + +```js config +export default { + hooks: { + fileHeaders: { + 'my-file-header': (defaultMessages = []) => [ + 'Ola, planet!', + ...defaultMessages, + 'Hello, World!', + ], + }, + }, + platforms: { + css: { + transformGroup: 'css', + options: { + fileHeader: 'my-file-header', + }, + files: [ + { + format: 'css/variables', + destination: '_variables.css', + }, + ], + }, + }, +}; +``` diff --git a/docs/src/content/docs/reference/Hooks/filters.md b/docs/src/content/docs/reference/Hooks/filters.md new file mode 100644 index 000000000..c985a6d2b --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/filters.md @@ -0,0 +1,138 @@ +--- +title: Filters +--- + +Filters is a hook that provides a way to filter your tokens prior to formatting them to the final output. + +Common use cases for filtering are: + +- Not outputting your primitive/option tokens such as a color palette +- Splitting component tokens into separate files for each component + +--- + +## Filter structure + +A filter is an object with two props: + +- `name`: the name of the filter +- `filter`: a callback function that receives the `token` as argument and returns a boolean, `true` to include the token, `false` to exclude/filter it out. Can also be an async function. Also has a second argument with the Style Dictionary options, which also contains the `tokens` object, `usesDTCG` option, etc. + +```javascript title="my-filter.js" +const myFilter = { + name: 'my-filter', + // async is optional + filter: async (token, options) => { + return !token.filePath.endsWith('core.json'); + }, +}; +``` + +--- + +## Using filters + +First you will need to tell Style Dictionary about your filter. You can do this in two ways: + +1. Using the [`.registerFilter`](/reference/api#registerfilter) method +1. Inline in the [configuration](/reference/config#properties) `hooks.filters` property + +### .registerFilter + +```javascript +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerFilter(myFilter); +``` + +### Inline + +```javascript +export default { + hooks: { + filters: { + 'my-filter': myFilter, + }, + }, + // ... the rest of the configuration +}; +``` + +### Applying it in config + +```json +{ + "source": ["**/*.tokens.json"], + "platforms": { + "css": { + "transformGroup": "css", + "files": [ + { + "format": "css/variables", + "destination": "_variables.css", + "filter": "my-filter" + } + ] + } + } +} +``` + +--- + +### Example + +~ sd-playground + +```json tokens +{ + "colors": { + "red": { + "type": "color", + "value": "#ff0000" + }, + "blue": { + "type": "color", + "value": "#0000ff" + } + }, + "spacing": { + "0": { + "type": "dimension", + "value": "0px" + }, + "1": { + "type": "dimension", + "value": "4px" + }, + "2": { + "type": "dimension", + "value": "8px" + } + } +} +``` + +```js config +export default { + hooks: { + filters: { + 'no-colors': (token, options) => { + return token.type !== 'color'; + }, + }, + }, + platforms: { + css: { + transformGroup: 'css', + files: [ + { + format: 'css/variables', + destination: '_variables.css', + filter: 'no-colors', + }, + ], + }, + }, +}; +``` diff --git a/docs/src/content/docs/reference/Hooks/parsers.md b/docs/src/content/docs/reference/Hooks/parsers.md new file mode 100644 index 000000000..9efcbae9c --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/parsers.md @@ -0,0 +1,87 @@ +--- +title: Parsers +--- + +You can define custom parsers to parse design token files. This allows you to define your design token files in _any_ language you like as long as you can write a parser for it. + +A custom parser matches design token files based on a file path regular expression. It will get the contents of a file as a string and should return an object of the data. + +Custom parsers can be used to keep design token files in other languages like YAML, but they can also be used to add extra metadata or modify the design tokens themselves before they get to Style Dictionary. For example, you could modify the token object based on its file path or programmatically generate tokens based on the data in certain files. + +:::note +`parser` function can be async as well. +::: + +--- + +## Parser structure + +A parser has 2 parts: a pattern which is a regular expression to match against a file path, and a parse function which takes the file path and contents of the file and is expected to return a function. + +```javascript title="my-parser.js" +const myParser = { + name: 'json-parser', + pattern: /\.json$/, + parser: ({ filePath, contents }) => { + return JSON.parse(contents); + }, +}; +``` + +--- + +## Using parsers + +First you will need to tell Style Dictionary about your parser. You can do this in two ways: + +1. Using the [`.registerParser`](/reference/api#registerparser) method +2. Inline in the [configuration](/reference/config#properties) + +You will then have to apply the parser by name in the [config](/reference/config): + +```json +{ + "source": ["tokens/*.json"], + "parsers": ["json-parser"], + "platforms": {} +} +``` + +### .registerParser + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerParser({ + name: 'json-parser', + pattern: /\.json$/, + parser: ({ filePath, contents }) => { + return JSON.parse(contents); + }, +}); +``` + +### Inline + +```javascript title="config.js" +export default { + hooks: { + parsers: { + 'json-parser': { + pattern: /\.json$/, + parser: ({ filePath, contents }) => { + return JSON.parse(contents); + }, + }, + }, + }, + // ... the rest of the configuration +}; +``` + +--- + +## Parser examples + +- [More in-depth custom parser example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) +- [Using custom parsers to support YAML design token files](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) diff --git a/docs/src/content/docs/reference/Hooks/preprocessors.md b/docs/src/content/docs/reference/Hooks/preprocessors.md new file mode 100644 index 000000000..766b4a1d8 --- /dev/null +++ b/docs/src/content/docs/reference/Hooks/preprocessors.md @@ -0,0 +1,138 @@ +--- +title: Preprocessors +--- + +Starting in version 4.0, you can define custom preprocessors to process the dictionary object as a whole, after it all token files have been parsed and combined into one. +This is useful if you want to do more complex transformations on the dictionary as a whole, when all other ways are not powerful enough. + +Preprocessors can be applied globally or per platform. + +:::caution +It should be clear that using this feature should be a last resort. Using custom parsers to parse per file or using transforms to do transformations on a per token basis, +gives more granular control and reduces the risks of making mistakes. +::: + +That said, preprocessing the full dictionary gives ultimate flexibility when needed. + +--- + +## Preprocessor structure + +A preprocessor is an object with two props: + +- `name`: the name of the preprocessor +- `preprocessor` a callback function that receives the dictionary and SD options as parameters, and returns the processed dictionary + +```javascript title="my-preprocessor.js" +const myPreprocessor = { + name: 'strip-third-party-meta', + preprocessor: (dictionary, options) => { + delete dictionary.thirdPartyMetadata; + return dictionary; + }, +}; +``` + +Asynchronous callback functions are also supported, giving even more flexibility. + +```javascript title="my-preprocessor-async.js" +const myPreprocessor = { + name: 'strip-props', + preprocessor: async (dictionary, options) => { + const propsToDelete = await someAPICall(); + + propsToDelete.forEach((propName) => { + delete dictionary[propName]; + }); + + return dictionary; + }, +}; +``` + +--- + +## Using preprocessors + +First you will need to tell Style Dictionary about your parser. You can do this in two ways: + +1. Using the [`.registerPreprocessor`](/reference/api#registerpreprocessor) method +1. Inline in the [configuration](/reference/config#properties) + +### .registerPreprocessor + +```javascript +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerPreprocessor(myPreprocessor); +``` + +### Inline + +```javascript +export default { + hooks: { + preprocessors: { + 'strip-props': myPreprocessor, + }, + }, + // ... the rest of the configuration +}; +``` + +### Applying it in config + +```json +{ + "source": ["**/*.tokens.json"], + "preprocessors": ["strip-props"] +} +``` + +or platform-specific: + +```json +{ + "source": ["**/*.tokens.json"], + "platforms": { + "css": { + "transformGroup": "css", + "preprocessors": ["strip-props"] + } + } +} +``` + +--- + +## Preprocessor examples + +Stripping description property recursively in the entire dictionary object: + +```js +StyleDictionary.registerPreprocessor({ + name: 'strip-descriptions', + preprocessor: (dict, options) => { + // recursively traverse token objects and delete description props + function removeDescription(slice) { + delete slice.description; + Object.values(slice).forEach((value) => { + if (typeof value === 'object') { + removeDescription(value); + } + }); + return slice; + } + return removeDescription(dict); + }, +}); +``` + +--- + +## Default preprocessors + +There are two default preprocessors that are always applied and run before other custom preprocessors do: + +- [`typeDtcgDelegate`](/reference/utils/dtcg#typedtcgdelegate), for DTCG tokens, make sure the `$type` is either already present or gets inherited from the closest ancestor that has it defined, so that the `$type` is always available on the token level, for ease of use +- [`expandObjectTokens`](/reference/config#expand), a private preprocessor that will expand object-value (composite) tokens when user config has this enabled. diff --git a/docs/src/content/docs/reference/Utils/DTCG.md b/docs/src/content/docs/reference/Utils/DTCG.md new file mode 100644 index 000000000..005d74430 --- /dev/null +++ b/docs/src/content/docs/reference/Utils/DTCG.md @@ -0,0 +1,131 @@ +--- +title: Design Tokens Community Group +--- + +These utilities have to do with the [Design Tokens W3C Community Group specification](https://tr.designtokens.org/format/). + +For converting a ZIP or JSON tokens file to the DTCG format, use the button below: + + + +This button is a tiny Web Component using file input as a wrapper around the convert DTCG utils listed below. + +## convertToDTCG + +This function converts your dictionary object to DTCG formatted dictionary, meaning that your `value`, `type` and `description` properties are converted to be prefixed with `$`, and the `$type` property is moved from the token level to the topmost common ancestor token group. + +```js +import { convertToDTCG } from 'style-dictionary/utils'; + +const outputDictionary = convertToDTCG(dictionary, { applyTypesToGroup: false }); +``` + +`applyTypesToGroup` is `true` by default, but can be turned off by setting to `false`. + +`dictionary` is the result of doing for example JSON.parse() on your tokens JSON string so it becomes a JavaScript object type. + +:::danger +Do not use this hook with `applyTypesToGroup` set to `true` (default) inside of a Preprocessor hook!\ +Style Dictionary relies on `typeDtcgDelegate` utility being ran right before user-defined preprocessors delegating all of the token group types to the token level, +because this makes it easier and more performant to grab the token type from the token itself, without needing to know about and traverse its ancestor tree to find it.\ +`typeDtcgDelegate` is doing the opposite action of `convertToDTCG`, delegating the `$type` down rather than moving and condensing the `$type` up. +::: + +### convertJSONToDTCG + +This function converts your JSON (either a JSON Blob or string that is an absolute filepath to your JSON file) to a JSON Blob which has been converted to DTCG format, see `convertToDTCG` function above. + +```js +import { convertToDTCG } from 'style-dictionary/utils'; + +const outputBlob = convertJSONToDTCG(JSONBlobOrFilepath, { applyTypesToGroup: false }); +``` + +`applyTypesToGroup` option can be passed, same as for `convertToDTCG` function. + +Note that if you use a filepath instead of Blob as input, this filepath should preferably be an absolute path. +You can use a utility like [`node:path`](https://nodejs.org/api/path.html) or a browser-compatible copy like [`path-unified`](https://www.npmjs.com/package/path-unified) +to resolve path segments or relative paths to absolute ones. + +### convertZIPToDTCG + +This function converts your ZIP (either a ZIP Blob or string that is an absolute filepath to your ZIP file) to a ZIP Blob which has been converted to DTCG format, see `convertToDTCG` function above. + +Basically the same as `convertJSONToDTCG` but for a ZIP file of JSON tokens. + +```js +import { convertZIPToDTCG } from 'style-dictionary/utils'; + +const outputBlob = convertZIPToDTCG(ZIPBlobOrFilepath, { applyTypesToGroup: false }); +``` + +## typeDtcgDelegate + +This function processes your ["Design Tokens Community Group Draft spec"-compliant](https://tr.designtokens.org/format/) dictionary of tokens, and ensures that `$type` inheritance is applied. + +We built this utility because it's cheaper to apply the inheritance once, rather than on every access of a token's "$type" property, checking the ancestor tree to find it. + +This utility runs by default in Style-Dictionary after the parser hook and before the preprocessor hook. + +```js +import { typeDtcgDelegate } from 'style-dictionary/utils'; + +const output = typeDtcgDelegate(input); +``` + +Input: + +```js +{ + dimensions: { + $type: 'dimension', + sm: { + $value: '5', + }, + md: { + $value: '10', + }, + nested: { + deep: { + lg: { + $value: '15', + }, + }, + }, + nope: { + $value: '20', + $type: 'spacing', + }, + }, +} +``` + +Output: + +```js +{ + dimensions: { + $type: 'dimension', + sm: { + $value: '5', + $type: 'dimension', + }, + md: { + $value: '10', + $type: 'dimension', + }, + nested: { + deep: { + lg: { + $value: '15', + $type: 'dimension', + }, + }, + }, + nope: { + $value: '20', + $type: 'spacing', + }, + }, +} +``` diff --git a/docs/src/content/docs/reference/Utils/format-helpers.md b/docs/src/content/docs/reference/Utils/format-helpers.md new file mode 100644 index 000000000..bf5e72eb3 --- /dev/null +++ b/docs/src/content/docs/reference/Utils/format-helpers.md @@ -0,0 +1,283 @@ +--- +title: Format Helpers +--- + +We provide some helper methods we use internally in some of the built-in formats to make building custom formats a bit easier. + +They are accessible at `style-dictionary/utils` entrypoint. + +```javascript +import StyleDictionary from 'style-dictionary'; +import { fileHeader, formattedVariables } from 'style-dictionary/utils'; + +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: async ({ dictionary, file, options }) => { + const { outputReferences } = options; + const header = await fileHeader({ file }); + return ( + header + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, +}); +``` + +Here are the available format helper methods: + +### createPropertyFormatter + +Creates a function that can be used to format a property. This can be useful +to use as the function on `dictionary.allTokens.map`. The formatting +is configurable either by supplying a `format` option or a `formatting` object +which uses: prefix, indentation, separator, suffix, and commentStyle. + +| Param | Type | Description | +| ------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | A single argument to support named parameters and destructuring. | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to output references. You will want to pass this from the `options` object sent to the format function. Also allows passing a function to conditionally output references on a per token basis. | +| `options.outputReferenceFallbacks` | `boolean` | Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the format function. | +| `options.dictionary` | `Dictionary` | Transformed Dictionary object containing allTokens, tokens and unfilteredTokens. | +| `options.dictionary.allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. | +| `options.dictionary.tokens` | `TransformedTokens` | All tokens, still in unflattened object format. | +| `options.dictionary.unfilteredTokens` | `TransformedTokens` | All tokens, still in unflattened object format, including tokens that were filtered out by filters. | +| `options.format` | `string` | Available formats are: 'css', 'sass', 'less', and 'stylus'. If you want to customize the format and can't use one of those predefined formats, use the `formatting` option | +| `options.formatting` | `FormattingOptions` | Custom formatting properties that define parts of a declaration line in code. The configurable strings are: `prefix`, `indentation`, `separator`, `suffix`, `lineSeparator`, `fileHeaderTimestamp`, `header`, `footer`, `commentStyle` and `commentPosition`. Those are used to generate a line like this: `${indentation}${prefix}${token.name}${separator} ${prop.value}${suffix}`. The remaining formatting options are used for the fileHeader helper. | +| `options.themeable` | `boolean` | Whether tokens should default to being themeable. Defaults to false. | + +Example: + +```javascript title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary, options }) { + const { outputReferences } = options; + const formatProperty = createPropertyFormatter({ + outputReferences, + dictionary, + format: 'css', + }); + return dictionary.allTokens.map(formatProperty).join('\n'); + }, +}); +``` + +--- + +### fileHeader + +This is for creating the comment at the top of generated files with the generated at date. +It will use the custom file header if defined on the configuration, or use the +default file header. + +| Param | Type | Description | +| ------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.file` | [`File`](/reference/config#file) | The file object that is passed to the format. | +| `options.commentStyle` | `string` | The only options are 'short', 'xml' and 'long', which will use the `//`, `` or `/*` style comments respectively. Defaults to 'long'. | +| `options.commentPosition` | `string` | 'above' or 'inline', so either above the token or inline with the token | +| `options.formatting` | `Object` | Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, footer and fileHeaderTimestamp. | + +Example: + +```js title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: async ({ dictionary, file }) => { + const header = await fileHeader({ file, commentStyle: 'short' }); + return ( + header + dictionary.allTokens.map((token) => `${token.name} = ${token.value};`).join('\n') + ); + }, +}); +``` + +Use `options.formatting.fileHeaderTimestamp` set to `true` to create a fileHeader that contains a timestamp for when the file was created. +This used to be default behavior but was made opt-in to accompany the common use case of Style Dictionary running in Continuous Integration (CI) pipelines, +and not wanting to create redundant git diffs just because of the timestamp changing between versions. + +--- + +### formattedVariables + +This is used to create lists of variables like Sass variables or CSS custom properties + +| Param | Type | Description | +| ------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.format` | `string` | What type of variables to output. Options are: 'css', 'sass', 'less', and 'stylus'. | +| `options.dictionary` | `Dictionary` | Transformed Dictionary object containing allTokens, tokens and unfilteredTokens. | +| `options.dictionary.allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. | +| `options.dictionary.tokens` | `TransformedTokens` | All tokens, still in unflattened object format. | +| `options.dictionary.unfilteredTokens` | `TransformedTokens` | All tokens, still in unflattened object format, including tokens that were filtered out by filters. | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to output references. You will want to pass this from the `options` object sent to the format function. Also allows passing a function to conditionally output references on a per token basis. | +| `options.formatting` | `Object` | Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer. | +| `options.themeable` | `boolean` | Whether tokens should default to being themeable. Defaults to false. | + +Example: + +```js title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary, options }) { + return formattedVariables({ + format: 'less', + dictionary, + outputReferences: options.outputReferences, + }); + }, +}); +``` + +--- + +### getTypeScriptType + +Given some value, returns a basic valid TypeScript type for that value. +Supports numbers, strings, booleans, arrays and objects of any of those types. + +Returns: `string` - A valid name for a TypeScript type. + +| Param | Type | Description | +| ------------------------------ | --------- | -------------------------------------------------------- | +| `value` | `any` | A value to check the type of. | +| `options` | `Object` | | +| `options.outputStringLiterals` | `boolean` | Whether or not to output literal types for string values | + +Example: + +```javascript title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary, options }) { + return dictionary.allTokens + .map(function (prop) { + var to_ret_prop = 'export const ' + prop.name + ' : ' + getTypeScriptType(prop.value) + ';'; + if (prop.comment) to_ret_prop = to_ret_prop.concat(' // ' + prop.comment); + return to_ret_prop; + }) + .join('\n'); + }, +}); +``` + +--- + +### iconsWithPrefix + +This is used to create CSS (and CSS pre-processor) lists of icons. It assumes you are +using an icon font and creates helper classes with the :before pseudo-selector to add +a unicode character. +**You probably don't need this.** + +| Param | Type | Description | +| ----------- | -------------------- | -------------------------------------------------------------------------------- | +| `prefix` | `string` | Character to prefix variable names, like `$` for Sass | +| `allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. | +| `options` | `Object` | options object passed to the format function. | + +Example: + +```js title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary, options }) { + return iconsWithPrefix('$', dictionary.allTokens, options); + }, +}); +``` + +--- + +### minifyDictionary + +Outputs an object stripping out everything except values + +| Param | Type | Description | +| ----- | ------------------- | ------------------------------------------------------------------------------------- | +| `obj` | `TransformedTokens` | The object to minify. You will most likely pass dictionary.tokens to it. | + +Example: + +```js title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary }) { + return JSON.stringify(minifyDictionary(dictionary.tokens)); + }, +}); +``` + +--- + +### setComposeObjectProperties + +Outputs an object for compose format configurations. Sets import. + +| Param | Type | Description | +| --------- | -------- | -------------------------------------------- | +| `options` | `Object` | The options object declared at configuration | + +--- + +### setSwiftFileProperties + +Outputs an object with swift format configurations. Sets import, object type and access control. + +| Param | Type | Description | +| ------------ | -------- | ------------------------------------------------------------------------------ | +| `options` | `Object` | The options object declared at configuration | +| `objectType` | `string` | The type of the object in the final file. Could be a class, enum, struct, etc. | +| `options` | `string` | The transformGroup of the file, so it can be applied proper import | + +--- + +### sortByName + +A sorting function to be used when iterating over `dictionary.allTokens` in +a format. + +**Returns**: `Integer` - `-1` or `1` depending on which element should come first based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort + +| Param | Type | Description | +| ----- | ----- | ----------------------------- | +| `a` | `any` | first element for comparison | +| `b` | `any` | second element for comparison | + +Example: + +```javascript title="build-tokens.js" +StyleDictionary.registerFormat({ + name: 'myCustomFormat', + format: function ({ dictionary, options }) { + return dictionary.allTokens + .sort(sortByName) + .map((token) => `${token.name} = ${token.value}`) + .join('\n'); + }, +}); +``` + +--- + +### sortByReference + +A function that returns a sorting function to be used with Array.sort that +will sort the allTokens array based on references. This is to make sure +if you use output references that you never use a reference before it is +defined. + +| Param | Type | Description | +| ----------------------------- | -------------------- | --------------------------------------------------------------------------------------------------- | +| `dictionary` | `Dictionary` | Transformed Dictionary object containing allTokens, tokens and unfilteredTokens. | +| `dictionary.allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. | +| `dictionary.tokens` | `TransformedTokens` | All tokens, still in unflattened object format. | +| `dictionary.unfilteredTokens` | `TransformedTokens` | All tokens, still in unflattened object format, including tokens that were filtered out by filters. | + +Example: + +```javascript title="build-tokens.js" +dictionary.allTokens.sort(sortByReference(dictionary)); +``` diff --git a/docs/src/content/docs/reference/Utils/index.md b/docs/src/content/docs/reference/Utils/index.md new file mode 100644 index 000000000..8213d3365 --- /dev/null +++ b/docs/src/content/docs/reference/Utils/index.md @@ -0,0 +1,21 @@ +--- +title: Utilities +sidebar: + label: Overview +--- + +The Style Dictionary npm module exposes a `utils` entrypoint that contains some helpful utility functions. + +## Installation + +```bash +npm install -D style-dictionary +``` + +## Usage + +```js title="script.js" +import { flattenTokens, resolveReferences, typeDtcgDelegate } from 'style-dictionary/utils'; +``` + +Check out the next pages for more details about the specific categories of utility functions. diff --git a/docs/src/content/docs/reference/Utils/references.md b/docs/src/content/docs/reference/Utils/references.md new file mode 100644 index 000000000..5f2100cd2 --- /dev/null +++ b/docs/src/content/docs/reference/Utils/references.md @@ -0,0 +1,494 @@ +--- +title: References +--- + +These utilities have to do with token references/aliases. + +## usesReference + +Whether or not a token value contains references + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { usesReference } from 'style-dictionary/utils'; + +usesReference('{foo.bar}'); // true +usesReference('solid {border.width} {border.color}'); // true +usesReference('5px'); // false +usesReference('[foo.bar]', { + opening_character: '[', + closing_character: ']', +}); // true +``` + +## resolveReferences + +Takes a token value string value and resolves any reference inside it + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { resolveReferences } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + colors: { + black: { + value: '#000', + type: 'color', + }, + }, + spacing: { + 2: { + value: '2px', + type: 'dimension', + }, + }, + border: { + value: 'solid {spacing.2} {colors.black}', + }, + }, +}); +resolveReferences(sd.tokens.border.value, sd.tokens); // "solid 2px #000" +resolveReferences('solid {spacing.2} {colors.black}', sd.tokens); // alternative way, yet identical to line above -> "solid 2px #000" +resolveReferences('solid {spacing.2} {colors.black}', sd.tokens, { usesDtcg: true }); // Assumes DTCG spec format, with $ prefix ($value, $type) +``` + +You can pass a third `options` argument where you can pass some configuration options for how references are resolved: + +- `usesDtcg` boolean, if set to true, the `resolveReferences` utility will assume DTCG syntax (`$value` props) +- `warnImmediately` boolean, `true` by default. You should only set this to `false` if you know that this utility is used used inside of the Transform lifecycle hook of Style Dictionary, allowing the errors to be grouped and only thrown at the end of the transform step (end of [exportPlatform](/reference/api#exportplatform) method). + +## getReferences + +Whether or not a token value contains references + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { getReferences } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + colors: { + black: { + value: '#000', + type: 'color', + }, + }, + spacing: { + 2: { + value: '2px', + type: 'dimension', + }, + }, + border: { + value: 'solid {spacing.2} {colors.black}', + }, + }, +}); + +getReferences(sd.tokens.border.value, sd.tokens); +getReferences('solid {spacing.2} {colors.black}', sd.tokens); // alternative way, yet identical to line above +getReferences('solid {spacing.2} {colors.black}', sd.tokens, { usesDtcg: true }); // Assumes DTCG spec format, with $ prefix ($value, $type) +/** + * [ + * { value: '2px', type: 'dimension', ref: ['spacing', '2'] }, + * { value: '#000', type: 'color', ref: ['colors', 'black'] } + * ] + */ +``` + +You can pass a third `options` argument where you can pass some configuration options for how references are resolved: + +- `usesDtcg` boolean, if set to true, the `resolveReferences` utility will assume DTCG syntax (`$value` props) +- `unfilteredTokens`, assuming the second `tokens` argument is your filtered `tokens` object where [filters](/reference/hooks/filters) have already done its work, you'll likely want to pass the unfiltered set in case the reference you're trying to find no longer exist in the filtered set, but you still want to get the reference values. This is useful when you're writing your own custom format with an `outputReferences` feature and you want to prevent outputting refs that no longer exist in the filtered set. +- `warnImmediately` boolean, `true` by default. You should only set this to `false` if you know that this utility is used inside of the Format lifecycle hook of Style Dictionary, allowing the errors to be grouped and only thrown at the end of the format step. + +### Complicated example + +You can use the `getReferences` utility to create your own custom formats that have `outputReferences` capability. + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { usesReference, getReferences, fileHeader } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + colors: { + black: { + value: '#000', + type: 'color', + }, + }, + spacing: { + 2: { + value: '2px', + type: 'dimension', + }, + }, + zIndex: { + // number example.. which should stay a number in the output + aboveFold: { + value: 1, + type: 'other', + }, + }, + semantic: { + bg: { + primary: { + value: '{colors.black}', + type: 'color', + }, + }, + }, + border: { + value: 'solid {spacing.2} {semantic.bg.primary}', + }, + }, + platforms: { + es6: { + transformGroup: 'js', + files: [ + { + format: 'es6', + destination: 'output.js', + options: { + outputReferences: true, + }, + }, + ], + }, + }, +}); + +// More complex case +// Note that this example format does not account for token values that are arrays or objects +StyleDictionary.registerFormat({ + name: 'es6', + format: async (dictionary) => { + const { allTokens, options, file } = dictionary; + const isNumeric = (str) => { + if (typeof str !== 'string') return false; + return ( + !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)... + !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail + ); + }; + + const compileTokenValue = (token) => { + let value = `${token.value}`; + const original = `${token.original.value}`; + const originalIsReferenceExclusively = original.match(/^\{.+\}$/g); + + const shouldOutputRef = + usesReferences(original) && + (typeof options.outputReferences === 'function' + ? outputReferences(token, { dictionary }) + : options.outputReferences); + + if (shouldOutputRef) { + value = original; + if (!originalIsReferenceExclusively) { + // since we're putting references back and value is not exclusively a reference, use template literals + value = `\`${value}\``; + } + const refs = getReferences(dictionary, original); + refs.forEach((ref) => { + // check if the ref has a value, path and name property, meaning that a name transform + // that creates the token name is mandatory for this format to function properly + if (['value', 'name', 'path'].every((prop) => Object.hasOwn(ref, prop))) { + value = value.replace( + // e.g. `{foo.bar.qux}` or `{foo.bar.qux.value}` + // replaced by `${fooBarQux}` + new RegExp(`{${ref.path.join('.')}(.value)?}`, 'g'), + originalIsReferenceExclusively ? ref.name : `\${${ref.name}}`, + ); + } + }); + return value; + } + return isNumeric(value) ? value : JSON.stringify(value); + }; + + const header = await fileHeader({ file }); + + return `${header}${allTokens.reduce((acc, token) => { + return ( + acc + + `export const ${token.name} = ${compileTokenValue(token)}; ${ + token.comment ? `// ${token.comment}` : '' + }\n` + ); + }, '')}`; + }, +}); + +await sd.buildAllPlatforms(); + +// output below + +/** + * Do not edit directly + * Generated on Thu, 07 Dec 2023 14:44:53 GMT + */ + +export const ColorsBlack = '#000'; +export const Spacing2 = '2px'; +export const ZIndexAboveFold = 1; +export const SemanticBgPrimary = ColorsBlack; +export const Border = `solid ${Spacing2} ${SemanticBgPrimary}`; +``` + +:::note +The above example does not support DTCG syntax, but this could be quite easily added, +since you can query `sd.usesDtcg` or inside a format functions `dictionary.options.usesDtcg`. +::: + +## outputReferencesFilter + +An `OutputReferences` function that filters for tokens containing references to other tokens that are filtered out in the output. +Usually Style Dictionary will throw a warning when you're using `outputReferences: true` and are about to have a broken reference in your output because the token you're referencing is filtered out. +What that means is that you usually have to either adjust your filter or disable `outputReferences` altogether, but supplying a function instead [allows you to conditionally output references on a per token basis](/reference/hooks/formats#references-in-output-files). + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { outputReferencesFilter } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + colors: { + black: { + value: '#000', + type: 'color', + }, + grey: { + // filtering this one out + value: '#ccc', + type: 'color', + }, + }, + spacing: { + 2: { + value: '2px', + type: 'dimension', + }, + }, + border: { + value: 'solid {spacing.2} {colors.black}', + }, + shadow: { + // danger: references a filtered out token! + value: '0 4px 2px {colors.grey}', + }, + }, + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'vars.css', + format: 'css/variables', + filter: (token) => token.name !== 'colors-grey', + options: { + // returns false for the shadow token because it refs color-grey which is filtered out + outputReferences: outputReferencesFilter, + }, + }, + ], + }, + }, +}); +``` + +Output: + +```css title="vars.css" +:root { + --spacing-2: 2rem; + --colors-black: #000000; + --shadow: 0 4px 2px #cccccc; + --border: solid var(--spacing-2) var(--colors-black); +} +``` + +Note that `--colors-grey` was filtered out and therefore the shadow does not contain a CSS custom property (reference) but rather the resolved value. + +Live Demo: + +~ sd-playground + +```json tokens +{ + "colors": { + "black": { + "value": "#000", + "type": "color" + }, + "grey": { + "value": "#ccc", + "type": "color" + } + }, + "spacing": { + "2": { + "value": "2px", + "type": "dimension" + } + }, + "border": { + "value": "solid {spacing.2} {colors.black}" + }, + "shadow": { + "value": "0 4px 2px {colors.grey}" + } +} +``` + +```js config +import { outputReferencesFilter } from 'style-dictionary/utils'; + +export default { + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'vars.css', + format: 'css/variables', + filter: (token) => token.name !== 'colors-grey', + options: { + // returns false for the shadow token because it refs color-grey which is filtered out + outputReferences: outputReferencesFilter, + }, + }, + ], + }, + }, +}; +``` + +## outputReferencesTransformed + +An [`outputReferences`](/reference/hooks/formats/#references-in-output-files) function that checks for each token whether +the value has changed through a transitive transform compared to the original value where references are resolved. + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { outputReferencesTransformed } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + base: { + value: '#000', + type: 'color', + }, + referred: { + value: 'rgba({base}, 12%)', + type: 'color', + }, + }, + platforms: { + css: { + transformGroup: 'css', + // see https://github.com/tokens-studio/sd-transforms + // this transform handles rgba(#000, 0.12) -> rgba(0, 0, 0, 0.12) + // as a transitive transform + transforms: ['ts/color/css/hexrgba'], + files: [ + { + destination: 'vars.css', + format: 'css/variables', + options: { + outputReferences: outputReferencesTransformed, + }, + }, + ], + }, + }, +}); +``` + +Output: + +```css title="vars.css" +:root { + --base: #000; + --referred: rgba(0, 0, 0, 12%); +} +``` + +Note that `--referred` is using the resolved value that is a transformed version of `--base` instead of `rgba(var(--base), 12%)` which would be invalid CSS. +This can be verified by setting `outputReferences` to `true` in the demo below. + +Live Demo: + +~ sd-playground + +```json tokens +{ + "base": { + "value": "#000", + "type": "color" + }, + "referred": { + "value": "rgba({base}, 12%)", + "type": "color" + } +} +``` + +```js config +import { outputReferencesTransformed } from 'style-dictionary/utils'; + +export default { + platforms: { + css: { + transformGroup: 'css', + transforms: ['ts/color/css/hexrgba'], + files: [ + { + destination: 'vars.css', + format: 'css/variables', + options: { + outputReferences: outputReferencesTransformed, + }, + }, + ], + }, + }, +}; +``` + +```js script +import StyleDictionary from 'style-dictionary'; +import { registerTransforms } from '@tokens-studio/sd-transforms'; + +// registers 'ts/color/css/hexrgba' +registerTransforms(StyleDictionary); +``` + +### Combining multiple outputReference utility functions + +These utility functions can be quite easily combined together: + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { outputReferencesFilter, outputReferencesTransformed } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'vars.css', + format: 'css/variables', + options: { + outputReferences: (token, options) => + outputReferencesFilter(token, options) && outputReferencesTransformed(token, options), + }, + }, + ], + }, + }, +}); +``` diff --git a/docs/src/content/docs/reference/Utils/tokens.md b/docs/src/content/docs/reference/Utils/tokens.md new file mode 100644 index 000000000..b03d9d316 --- /dev/null +++ b/docs/src/content/docs/reference/Utils/tokens.md @@ -0,0 +1,50 @@ +--- +title: Tokens +--- + +These utilities have to do with processing/formatting tokens object. + +## flattenTokens + +Flatten dictionary tokens object to an array of flattened tokens. + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { flattenTokens } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + colors: { + black: { + value: '#000', + type: 'color', + name: 'colors-black', + }, + }, + spacing: { + 2: { + value: '2px', + type: 'dimension', + name: 'spacing-2', + }, + }, + border: { + value: 'solid {spacing.2} {colors.black}', + name: 'border', + }, + }, +}); + +const flat = flattenTokens(sd); +/** + * [ + * { value: '#000', type: 'color', name: 'colors-black' }, + * { value: '2px', type: 'dimension', name: 'spacing-2' }, + * { value: 'solid {spacing.2} {colors.black}', name: 'border' } + * ] + */ +``` + +:::note +You can pass a second argument `usesDtcg`, if set to true, the flattenTokens utility will assume DTCG syntax (`$value` props). +::: diff --git a/docs/src/content/docs/reference/api.md b/docs/src/content/docs/reference/api.md new file mode 100644 index 000000000..cb14c81e8 --- /dev/null +++ b/docs/src/content/docs/reference/api.md @@ -0,0 +1,555 @@ +--- +title: API +sidebar: + order: 1 +--- + +## new StyleDictionary() + +Create a new StyleDictionary instance. + +| Param | Type | Description | +| ------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `config` | [`Config`](/reference/config) | Configuration options to build your style dictionary. If you pass a string, it will be used as a path to a JSON config file. You can also pass an object with the configuration. | +| `options` | `Object` | Options object when creating a new StyleDictionary instance. | +| `options.init` | `boolean` | `true` by default but can be disabled to delay initializing the dictionary. You can then call `sdInstance.init()` yourself, e.g. for testing or error handling purposes. | +| `options.verbosity` | `'silent'\|'default'\|'verbose'` | Verbosity of logs, overrides `log.verbosity` set in SD config or platform config. | +| `options.warnings` | `'error'\|'warn'\|'disabled'` | Whether to throw warnings as errors, warn or disable warnings, overrides `log.verbosity` set in SD config or platform config. | +| `options.volume` | `import('memfs').IFs \| typeof import('node:fs')` | FileSystem Volume to use as an alternative to the default FileSystem, handy if you need to isolate or "containerise" StyleDictionary files | + +Example: + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary('config.json'); +const sdTwo = new StyleDictionary({ + source: ['tokens/*.json'], + platforms: { + scss: { + transformGroup: 'scss', + buildPath: 'build/', + files: [ + { + destination: 'variables.scss', + format: 'scss/variables', + }, + ], + }, + // ... + }, +}); +``` + +Using volume option: + +```js title="build-tokens.js" +import { Volume } from 'memfs'; +// You will need a bundler like webpack/rollup for memfs in browser... +// Or use as a prebundled fork: +import memfs from '@bundled-es-modules/memfs'; +const { Volume } = memfs; + +const vol = new Volume(); + +const sd = new StyleDictionary( + { + tokens: { + colors: { + red: { + value: '#FF0000', + type: 'color', + }, + }, + }, + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'variables.css', + format: 'css/variables', + }, + ], + }, + }, + }, + { volume: vol }, +); + +await sd.buildAllPlatforms(); + +vol.readFileSync('/variables.css'); +/** + * :root { + * --colors-red: #FF0000; + * } + */ +``` + +## Instance methods + +### init + +```ts +type init = (config: Config) ⇒ Promise +``` + +Called automatically when doing `new StyleDictionary(config)` unless passing a second argument with `init` property set to `false`. +In this scenario, you can call `.init()` manually, e.g. for testing or error handling purposes. + +| Param | Type | Description | +| ---------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `initConfig` | `Object` | Init configuration options. | +| `initConfig.verbosity` | `'silent'\|'default'\|'verbose'` | Verbosity of logs, overrides `log.verbosity` set in SD config or platform config. | +| `initConfig.warnings` | `'error'\|'warn'\|'disabled'` | Whether to throw warnings as errors, warn or disable warnings, overrides `log.verbosity` set in SD config or platform config. | + +### extend + +```ts +type extend = (config: Config | string, options: Options) ⇒ Promise +``` + +Extend a Style Dictionary instance with a config object, to create an extension instance. + +| Param | Type | Description | +| ------------------------ | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `config` | [`Config`](/reference/config) | Configuration options to build your style dictionary. If you pass a string, it will be used as a path to a JSON config file. You can also pass an object with the configuration. | +| `options` | `Object` | | +| `options.verbosity` | `'silent'\|'default'\|'verbose'` | Verbosity of logs, overrides `log.verbosity` set in SD config or platform config. | +| `options.warnings` | `'error'\|'warn'\|'disabled'` | Whether to throw warnings as errors, warn or disable warnings, overrides `log.verbosity` set in SD config or platform config. | +| `options.volume` | `import('memfs').IFs \| typeof import('node:fs')` | Pass a custom Volume to use instead of filesystem shim itself. Only possible in browser or in Node if you're explicitly using `memfs` as filesystem shim (by calling `setFs()` function and setting it to the `memfs` module) | +| `options.mutateOriginal` | `boolean` | Private option, do not use | + +Example: + +```js title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary('config.json'); + +const sdExtended = await sd.extend({ + source: ['tokens/*.json'], + platforms: { + scss: { + transformGroup: 'scss', + buildPath: 'build/', + files: [ + { + destination: 'variables.scss', + format: 'scss/variables', + }, + ], + }, + // ... + }, +}); +``` + +Volume option also works when using extend: + +```js +const extendedSd = await sd.extend(cfg, { volume: vol }); +``` + +--- + +### exportPlatform + +```ts +type exportPlatform = (platform: string) => Promise; +``` + +Exports a tokens object with applied platform transforms. + +This is useful if you want to use a Style Dictionary in JS build tools like Webpack. + +| Param | Type | Description | +| -------- | -------- | --------------------------------------------------------------------- | +| platform | `string` | The platform to be exported. Must be defined on the style dictionary. | + +--- + +### getPlatform + +```ts +type getPlatform = (platform: string) => Promise<{ + platformConfig: PlatformConfig; + dictionary: { + tokens: DesignTokens; + allTokens: DesignToken[]; + }; +}>; +``` + +`SDInstance.getPlatform(platform) ⇒ Promise` + +Wrapper around [`exportPlatform`](#exportplatform), returns a bit more data. + +Returns an object with `platformConfig` and `dictionary` properties: + +- `platformConfig` a processed version of the user config for the platform +- `dictionary` an object with `tokens` after transformations and reference resolutions, and an `allTokens` property which is a flattened (Array) version of that. + +This is useful if you want to use a Style Dictionary in JS build tools like Webpack. + +| Param | Type | Description | +| -------- | -------- | --------------------------------------------------------------------- | +| platform | `string` | The platform to be exported. Must be defined on the style dictionary. | + +--- + +### formatPlatform + +```ts +type formatPlatform = (platform: string) => Promise +``` + +Runs [`getPlatform`](#getplatform) under the hood, and then loops over the `files`, and formats the dictionary for each file, returning an array of file objects: + +- `output` property, which is usually a string but depending on the format, it could also be any other data type. This is useful if you don't intend to write to a file, but want to do something else with the formatted tokens. +- `destination` property, this one is optional, if you don't intend on writing to a file you don't need this, but it can still be useful to name your outputs if you've got multiple `files`. + +--- + +### formatAllPlatforms + +```ts +type formatAllPlatforms = () => Promise< + Record> +>; +``` + +Runs [`formatPlatform`](#formatplatform) under the hood but for each platform. + +The resulting object is similar, but an `Object` with key-value pairs where they key is the platform key, and the value is the same data from the `formatPlatform` method. + +This is useful if you don't want to write to the filesystem but want to do something custom with the data instead. + +--- + +### buildPlatform + +```ts +type buildPlatform = (platform: string) => Promise; +``` + +Takes a platform and performs all transforms to +the tokens object (non-mutative) then +builds all the files and performs any actions. This is useful if you only want to +build the artifacts of one platform to speed up the build process. + +This method is also used internally in [buildAllPlatforms](#buildallplatforms) to +build each platform defined in the config. + +| Param | Type | Description | +| -------- | -------- | --------------------------------------- | +| platform | `string` | Name of the platform you want to build. | + +Example: + +```js title="build-web.js" +// Async, so you can do `await` or .then() if you +// want to execute code after buildAllPlatforms has completed +await sd.buildPlatform('web'); +``` + +```bash +style-dictionary build --platform web +``` + +--- + +### buildAllPlatforms + +```ts +type buildAllPlatforms = () => Promise; +``` + +Uses [`buildPlatform`](#buildplatform) under the hood for each platform. + +:::tip +In the majority of cases, this is the method you'll use. +::: + +Example: + +```js +import StyleDictionary from 'style-dictionary'; +const sd = new StyleDictionary('config.json'); + +// Async, so you can do `await` or .then() if you +// want to execute code after buildAllPlatforms has completed +await sd.buildAllPlatforms(); +``` + +```bash +style-dictionary build +``` + +--- + +### cleanPlatform + +```ts +type cleanPlatform = (platform: string) => Promise; +``` + +Takes a platform and performs all transforms to +the tokens object (non-mutative) then +cleans all the files and performs the undo method of any [actions](/reference/hooks/actions). + +| Param | Type | +| -------- | -------- | +| platform | `string` | + +--- + +### cleanAllPlatforms + +```ts +type cleanAllPlatforms = () => Promise; +``` + +Uses [`cleanPlatform`](#cleanplatform) under the hood for each platform. + +Does the reverse of [buildAllPlatforms](#buildallplatforms) by +performing a clean on each platform. This removes all the files +defined in the platform and calls the undo method on any actions. + +--- + +## Class methods + +:::tip +Can also be used on the instance if you want to register something only on that particular StyleDictionary instance, as opposed to registering it globally for all instances. +::: + +### registerAction + +> `StyleDictionary.registerAction(action) ⇒ StyleDictionary` + +Adds a custom [action](/reference/hooks/actions) to Style Dictionary. Custom +actions can do whatever you need, such as: copying files, +base64'ing files, running other build scripts, etc. +After you register a custom action, you then use that +action in a platform your config.json + +You can perform operations on files generated by the style dictionary +as actions run after these files are generated. +Actions are run sequentially, if you write synchronous code then +it will block other actions, or if you use asynchronous code like Promises +it will not block. + +| Param | Type | Description | +| ----------- | ---------- | -------------------------------------------------- | +| action | `Object` | | +| action.name | `string` | The name of the action | +| action.do | `function` | The action in the form of a function. Can be async | +| action.undo | `function` | A function that undoes the action. Can be async | + +Example: + +```js +StyleDictionary.registerAction({ + name: 'copy_assets', + do: async function (dictionary, config) { + console.log('Copying assets directory'); + await fs.promises.copy('assets', config.buildPath + 'assets'); + }, + undo: async function (dictionary, config) { + console.log('Cleaning assets directory'); + await fs.promises.remove(config.buildPath + 'assets'); + }, +}); +``` + +--- + +### registerFileHeader + +> `StyleDictionary.registerFileHeader(fileHeader) ⇒ StyleDictionary` + +Add a custom [fileHeader](/reference/hooks/file-headers) to the Style Dictionary. File headers are used in +formats to display some information about how the file was built in a comment. + +| Param | Type | Description | +| ------------------ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| options | `Object` | | +| options.name | `string` | Name of the format to be referenced in your config.json | +| options.fileHeader | `function` | Function that returns an array of strings, which will be mapped to comment lines. It takes a single argument which is the default message array. See [file headers](/references/hooks/file-headers) for more information. Can be async. | + +Example: + +```js +StyleDictionary.registerFileHeader({ + name: 'myCustomHeader', + fileHeader: function (defaultMessage) { + return [...defaultMessage, `hello, world!`]; + }, +}); +``` + +--- + +### registerFilter + +> `StyleDictionary.registerFilter(filter) ⇒ StyleDictionary` + +Add a custom [filter](/reference/hooks/filters) to the Style Dictionary. + +| Param | Type | Description | +| ------------- | ---------- | ----------------------------------------------------------------------------- | +| Filter | `Object` | | +| Filter.name | `string` | Name of the filter to be referenced in your config.json | +| Filter.filter | `function` | Filter function, return boolean if the token should be included. Can be async | + +Example: + +```js +StyleDictionary.registerFilter({ + name: 'isColor', + filter: function (token) { + return token.type === 'color'; + }, +}); +``` + +--- + +### registerFormat + +> `StyleDictionary.registerFormat(format) ⇒ StyleDictionary` + +Add a custom [format](/reference/hooks/formats) to the Style Dictionary. + +| Param | Type | Description | +| ------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| format | `Object` | | +| format.name | `string` | Name of the format to be referenced in your config.json | +| format.format | `function` | Function to perform the format. Takes a single argument. See [creating custom formats](/references/hooks/formats#creating-formats) Must return a string, which is then written to a file. Can be async | + +Example: + +```js +StyleDictionary.registerFormat({ + name: 'json', + format: function ({ dictionary, platform, options, file }) { + return JSON.stringify(dictionary.tokens, null, 2); + }, +}); +``` + +--- + +### registerParser + +> `StyleDictionary.registerParser(parser) ⇒ StyleDictionary` + +Adds a custom [parser](/reference/hooks/parsers) to parse style dictionary files. + +| Param | Type | Description | +| -------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Parser.name | `string` | Name of the parser to be referenced in your config.json | +| Parser.pattern | `Regex` | A file path regular expression to match which files this parser should be be used on. This is similar to how webpack loaders work. `/\.json$/` will match any file ending in '.json', for example. | +| Parser.parser | `function` | Function to parse the file contents. Takes 1 argument, which is an object with 2 properties: `contents` wich is the string of the file contents and `filePath`. The function should return a plain JavaScript object. Can be async. | + +Example: + +```js +StyleDictionary.registerParser({ + name: 'json-parser', + pattern: /\.json$/, + parser: ({ contents, filePath }) => { + return JSON.parse(contents); + }, +}); +``` + +--- + +### registerPreprocessor + +> `StyleDictionary.registerPreprocessor({ name, preprocessor }) => StyleDictionary` + +Adds a custom [preprocessor](/reference/hooks/preprocessors) to preprocess already parsed Style Dictionary objects. + +| Param | Type | Description | +| ------------------------- | ---------- | --------------------------------------------------------------------------------------------------------- | +| Preprocessor | `Object` | | +| Preprocessor.name | `string` | Name of the format to be referenced in your config.json | +| Preprocessor.preprocessor | `function` | Function to preprocess the dictionary. The function should return a plain Javascript object. Can be async | + +Example: + +```js +StyleDictionary.registerPreprocessor({ + name: 'strip-third-party-meta', + preprocessor: (dictionary) => { + delete dictionary.thirdPartyMetadata; + return dictionary; + }, +}); +``` + +--- + +### registerTransform + +> `StyleDictionary.registerTransform(transform) ⇒ StyleDictionary` + +Add a custom [transform](/reference/hooks/transforms) to the Style Dictionary. +Transforms can manipulate a token's name, value, or attributes. + +| Param | Type | Description | +| -------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| transform | `Object` | Transform object | +| transform.type | `string` | Type of transform, can be: name, attribute, or value | +| transform.name | `string` | Name of the transform (used by transformGroup to call a list of transforms). | +| transform.transitive | `boolean` | If the value transform should be applied transitively, i.e. should be applied to referenced values as well as absolute values. | +| transform.filter | `function` | [Filter](/reference/hooks/filters) function, return boolean if transform should be applied. If you omit the filter function, it will match all tokens. | +| transform.transform | `function` | Modifies a design token object. The transform function will receive the token and the platform configuration as its arguments. The transform function should return a string for name transforms, an object for attribute transforms, and same type of value for a value transform. Can be async. | + +Example: + +```js +StyleDictionary.registerTransform({ + name: 'time/seconds', + type: 'value', + filter: function (token) { + return token.type === 'time'; + }, + transform: function (token) { + // Note the use of prop.original.value, + // before any transforms are performed, the build system + // clones the original token to the 'original' attribute. + return (parseInt(token.original.value) / 1000).tostring() + 's'; + }, +}); +``` + +--- + +### registerTransformGroup + +> `StyleDictionary.registerTransformGroup(transformGroup) ⇒ StyleDictionary` + +Add a custom [transformGroup](/reference/hooks/transform_groups) to the Style Dictionary, which is a +group of transforms. + +| Param | Type | Description | +| ------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| transformGroup | `Object` | | +| transformGroup.name | `string` | Name of the transform group that will be referenced in config.json | +| transformGroup.transforms | `string[]` | Array of strings that reference the name of transforms to be applied in order. Transforms must be defined and match the name or there will be an error at build time. | + +Example: + +```js +StyleDictionary.registerTransformGroup({ + name: 'Swift', + transforms: ['attribute/cti', 'size/pt', 'name'], +}); +``` + +--- diff --git a/docs/src/content/docs/reference/config.md b/docs/src/content/docs/reference/config.md new file mode 100644 index 000000000..f8bc81a53 --- /dev/null +++ b/docs/src/content/docs/reference/config.md @@ -0,0 +1,433 @@ +--- +title: Configuration +sidebar: + order: 2 +--- + +Style dictionaries are configuration driven. Your configuration lets Style Dictionary know: + +1. Where to find your [design tokens](/reference/tokens) +1. How to transform and format them to generate output files + +Here is an example configuration: + +```json title="config.json" +{ + "source": ["tokens/**/*.json"], + "platforms": { + "scss": { + "transformGroup": "scss", + "prefix": "sd", + "buildPath": "build/scss/", + "files": [ + { + "destination": "_variables.scss", + "format": "scss/variables" + } + ], + "actions": ["copy_assets"] + }, + "android": { + "transforms": ["attribute/cti", "name/snake", "color/hex", "size/remToSp", "size/remToDp"], + "buildPath": "build/android/src/main/res/values/", + "files": [ + { + "destination": "style_dictionary_colors.xml", + "format": "android/colors" + } + ] + } + } +} +``` + +## Configuration file formats + +Style Dictionary supports configuration files in these file formats: + +- JSON +- JSONC +- JSON5 +- Javascript (ES Modules, default export) + +Here is an example using an ES module for configuration: + +```javascript title="config.js" +export default { + source: [`tokens/**/*.json`], + // If you don't want to call the registerTransform method a bunch of times + // you can override the whole transform object directly. This works because + // the .extend method copies everything in the config + // to itself, allowing you to override things. It's also doing a deep merge + // to protect from accidentally overriding nested attributes. + transform: { + // Now we can use the transform 'myTransform' below + myTransform: { + type: 'name', + transform: (token) => token.path.join('_').toUpperCase(), + }, + }, + // Same with formats, you can now write them directly to this config + // object. The name of the format is the key. + format: { + myFormat: ({ dictionary, platform }) => { + return dictionary.allTokens.map((token) => `${token.name}: ${token.value};`).join('\n'); + }, + }, + platforms: { + // ... + }, +}; +``` + +Some interesting things you can do in a JS file that you cannot do in a JSON file: + +- Add custom transforms, formats, filters, actions, preprocessors and parsers +- Programmatically generate your configuration + +--- + +## Using configuration files + +By default, the Style Dictionary [CLI](/reference/using_the_cli) looks for a `config.json` or `config.js` file in the root of your package. + +```json5 +// package.json +"scripts": { + "build": "style-dictionary build" +} +``` + +You can also specify a custom location when you use the [CLI](/reference/using_the_cli) with the `--config` parameter. + +```json5 +// package.json +"scripts": { + "build": "style-dictionary build --config ./sd.config.js" +} +``` + +## Using in Node + +You can also use Style Dictionary as an [npm module](/reference/using_the_npm_module) and further customize how Style Dictionary is run, for example running Style Dictionary multiple times with different configurations. To do this you would create a Javascript file that imports the Style Dictionary npm module and calls the [`.extend`](/reference/api#extend) and [`.buildAllPlatforms`](/reference/api#buildallplatforms) functions. + +```javascript +// build-tokens.js +import StyleDictionary from 'style-dictionary'; + +const myStyleDictionary = new StyleDictionary({ + // configuration +}); + +await myStyleDictionary.buildAllPlatforms(); + +// You can also extend Style Dictionary multiple times: +const myOtherStyleDictionary = await myStyleDictionary.extend({ + // new configuration +}); + +await myOtherStyleDictionary.buildAllPlatforms(); +``` + +You would then change your npm script or CLI command to run that file with Node: + +```json5 +// package.json +"scripts": { + "build": "node build-tokens.js" +} +``` + +--- + +## Properties + +| Property | Type | Description | +| :-------------- | :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `log` | `Log` | [Configure logging behavior](/reference/logging) to either reduce/silence logs or to make them more verbose for debugging purposes. | +| `source` | `string[]` | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files. Style Dictionary will do a deep merge of all of the token files, allowing you to organize your files however you want. | +| `include` | `string[]` | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files that contain default styles. Style Dictionary uses this as a base collection of design tokens. The tokens found using the "source" attribute will overwrite tokens found using include. | +| `tokens` | `Object` | The tokens object is a way to include inline design tokens as opposed to using the `source` and `include` arrays. | +| `expand` | `ExpandConfig` | Configures whether and how composite (object-value) tokens will be expanded into separate tokens. `false` by default. Supports either `boolean`, `ExpandFilter` function or an Object containing a `typesMap` property and optionally an `include` OR `exclude` property. | +| `platforms` | `Record` | An object containing [platform](#platform) config objects that describe how the Style Dictionary should build for that platform. You can add any arbitrary attributes on this object that will get passed to formats and actions (more on these in a bit). This is useful for things like build paths, name prefixes, variable names, etc. | +| `hooks` | `Hooks` object | Object that contains all configured custom hooks: `preprocessors`. Note: `parsers`, `transforms`, `transformGroups`, `formats`, `fileHeaders`, `filters`, `actions` will be moved under property this later. Can be used to define hooks inline as an alternative to using `register` methods. | +| `parsers` | `string[]` | Names of custom [file parsers](/reference/hooks/parsers) to run on input files | +| `preprocessors` | `string[]` | Which [preprocessors](/reference/hooks/preprocessors) (by name) to run on the full token dictionary, before any transforms run, can be registered using `.registerPreprocessor`. You can also configure this on the platform config level if you need to run it on the dictionary only for specific platforms. | +| `transform` | `Record` | Custom [transforms](/reference/hooks/transforms) you can include inline rather than using `.registerTransform`. The keys in this object will be the transform's name, the value should be an object with `type` | +| `format` | `Record` | Custom [formats](/reference/hooks/formats) you can include inline in the configuration rather than using `.registerFormat`. The keys in this object will be for format's name and value should be the format function. | +| `usesDtcg` | `boolean` | Whether the tokens are using [DTCG Format](https://tr.designtokens.org/format/) or not. Usually you won't need to configure this, as style-dictionary will auto-detect this format. | + +### Log + +Log configuration object to configure the [logging behavior of Style Dictionary](/reference/logging). + +### Platform + +A platform is a build target that tells Style Dictionary how to properly transform and format your design tokens for output to a specific platform. You can have as many platforms as you need and you can name them anything, there are no restrictions. + +| Property | Type | Description | +| :--------------- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transforms` | `string[]` | An array of [transform](/reference/hooks/transforms) keys to be performed on the design tokens. These will transform the tokens in a non-destructive way, allowing each platform to transform the tokens. Transforms to apply sequentially to all tokens. Can be a built-in one or you can create your own. | +| `transformGroup` | `string` | A string that maps to an array of transforms. This makes it easier to reference transforms by grouping them together. Can be combined with [transforms](/reference/hooks/transforms). | +| `buildPath` | `string` | Base path to build the files, must end with a trailing slash. | +| `expand` | `ExpandConfig` | Configures whether and how composite (object-value) tokens will be expanded into separate tokens. `false` by default. Supports either `boolean`, `ExpandFilter` function or an Object containing a `typesMap` property and optionally an `include` OR `exclude` property. | +| `preprocessors` | `string[]` | Which [preprocessors](/reference/hooks/preprocessors) (by name) to run on the full token dictionary when building for this particular platform, before any transforms run, can be registered using `.registerPreprocessor`. You can also configure this on the global config. | +| `options` | `Object` | Options that apply to all files in the platform, for example [`outputReferences`](/reference/hooks/format#references-in-output-files) and `showFileHeader` | +| `files` | `File[]` | [Files](#file) to be generated for this platform. | +| `actions` | `string[]` | [Actions](/reference/hooks/actions) to be performed after the files are built for that platform. Actions can be any arbitrary code you want to run like copying files, generating assets, etc. You can use pre-defined actions or create custom actions. | + +### File + +A File configuration object represents a single output file. The `options` object on the file configuration will take precedence over the `options` object defined at the platform level. Apart from the options listed below, any other options can be added, which can then be used inside custom [formats](/reference/hooks/formats). + +| Property | Type | Description | +| :------------------------- | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `destination` | `string` | Location to build the file, will be appended to the buildPath. | +| `format` | `string` | [Format](/reference/hooks/formats) used to generate the file. Can be a built-in one or you can create your own via [registerFormat](/reference/api#registerformat). | +| `filter` | `string \| function \| Object` | A function, string or object used to filter the tokens that will be included in the file. If a function is provided, each design token will be passed to the function and the result (true or false) will determine whether the design token is included. If an object is provided, each design token will be matched against the object using a partial deep comparison. If a match is found, the design token is included. If a string is passed, is considered a custom filter registered via [registerFilter](/reference/api#registerfilter) | +| `options` | `Object` | A set of extra options associated with the file. Includes `showFileHeader` and [`outputReferences`](/reference/hooks/formats#references-in-output-files). | +| `options.showFileHeader` | `boolean` | If the generated file should have a comment at the top about being generated. The default fileHeader comment has "Do not edit + Timestamp". By default is "true". | +| `options.fileHeader` | `string \|function` | A custom fileHeader that can be either a name of a registered file header (string) or an inline [fileHeader](/reference/hooks/formats#customfileheader) function. | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | If the file should keep token [references](/reference/hooks/formats#references-in-output-files). By default this is "false". Also allows passing a function to conditionally output references on a per token basis. | + +### Expand + +You can configure whether and how composite (object-value) tokens will be expanded into separate tokens. +By default, this functionality is disabled and for formats such as CSS where object values are not supported, you'd be relying on either a [custom value transform](/reference/hooks/transforms/#defining-custom-transforms) to turn such token values into strings, or [writing a custom format](/reference/hooks/formats/#custom-formats) to format object values into CSS compatible values. + +#### Expand usage + +Below are examples of how the `expand` property can be used. + +```js +{ + expand: true, // expand all object-value (composite) type tokens + + expand: {}, // equivalent to true + + // conditionally expand, executes this callback for each individual token + expand: (token, config, platformConfig) => true, + + // equivalent to true, but additionally passing a typesMap + expand: { + typesMap: { + width: 'dimension', + }, + }, + + // only expands typography and border tokens, also passes a typesMap + expand: { + include: ['typography', 'border'], + // more info about typesMap later... + typesMap: { + // all width props are mapped to 'dimension' type + width: 'dimension', + typography: { + // fontSize prop is mapped to 'dimension' type if inside a typography composite type token + fontSize: 'dimension', + }, + }, + }, + + // expands everything except for typography and border tokens + expand: { + exclude: ['typography', 'border'], + }, + + // only expands tokens for which this function returns true + expand: { + include: (token, config, platformConfig) => true, + }, + + // expands everything except for tokens for which this function returns true + expand: { + exclude: (token, config, platformConfig) => true, + }, +} +``` + +The value of expand can be multiple things: + +- `boolean`, `false` by default, when set to `true`, any object-value (composite) design token will be expanded into multiple tokens, one for each property. +- a function of type `ExpandFilter`, e.g. `(token, options, platform) => true`, must return a `boolean`, when `true` will expand that individual token, arguments: + - `token`: the design token of which the value is an object (composite) + - `options`: the StyleDictionary config options + - `platform`: this is only passed when expand is used on the platform level, contains the platform specific config options +- An object: + - Empty, which is equivalent of passing `true` + - Containing just a `typesMap`, which is also equivalent of passing `true`, except you're also passing the `typesMap` + - Also containing an `include` or `exclude` property which can be either an array of composite types or an `ExpandFilter` function, to conditionally expand or negate expand of individual tokens + +#### Global vs Platform + +You can enable the expanding of tokens both on a global level and on a platform level. + +One notable difference to keep in mind is that when you configure it on a global level, the token expansion will happen immediately **after** the [parsing hook](/reference/hooks/parsers) and **before** [preprocessing](/reference/hooks/preprocessors) or [transform](/reference/hooks/transforms) hooks.\ +This means that token metadata properties that are added by Style Dictionary such as `name`, `filePath`, `path`, `attributes` etc. are not present yet.\ +The advantage is having the expanded tokens (`sd.tokens` prop) available before doing any exporting to platforms. + +If you configure it on the platform level however, the metadata mentioned earlier is available and can be used to conditionally expand tokens. +It also allows you to expand tokens for some platforms but not for others.\ +The downside there is needing to configure it for every platform separately. + +:::caution +It's also important to note that if you configure expansion on the global level, you cannot undo those token expansions by negating it in the platform-specific expand configs. +::: + +#### Type Mapping + +While our expand utility comes with a `typesMap` out of the box that aligns with the [Design Token Community Group spec](https://design-tokens.github.io/community-group/format/#composite-design-token) to convert composite subtype properties to [defined DTCG types](https://design-tokens.github.io/community-group/format/#types), you can also pass a custom `typesMap` that will allow you to extend or override it. +A `typesMap` allows you to configure how object-value (composite) properties in the original token value should be mapped to the newly expanded individual tokens. + +For example: + +```json title="tokens-input.json" +{ + "value": { + "width": "2px", + "style": "solid", + "color": "#000" + }, + "type": "border" +} +``` + +Here, according to the DTCG spec, you would probably want to map the `"width"` property to type [`"dimension"`](https://design-tokens.github.io/community-group/format/#dimension) and `"style"` property to type [`"strokeStyle"`](https://design-tokens.github.io/community-group/format/#stroke-style). +`"width"` is more of a general property where we always want to map it to `"dimension"` but border `"style"` is more specific to the border composite type, therefore this `typesMap` makes sense: + +```json title="config.json" +{ + "expand": { + "typesMap": { + "width": "dimension", + "border": { + "style": "strokeStyle" + } + } + } +} +``` + +Resulting in the following expanded output: + +```json title="tokens-output.json" +{ + "width": { + "value": "2px", + "type": "dimension" + }, + "style": { + "value": "solid", + "type": "strokeStyle" + }, + "color": { + "value": "#000", + "type": "color" + } +} +``` + +#### Example + +~ sd-playground + +```json tokens +{ + "border": { + "type": "border", + "value": { + "width": "2px", + "style": "solid", + "color": "#000" + } + }, + "typography": { + "type": "typography", + "value": { + "fontWeight": "800", + "fontSize": "16px", + "fontFamily": "Arial Black" + } + } +} +``` + +```json config +{ + "expand": { + "include": ["border"], + "typesMap": { + "border": { + "style": "borderStyle" + } + } + }, + "platforms": { + "css": { + "transformGroup": "css", + "files": [ + { + "destination": "vars.css", + "format": "css/variables" + } + ], + "expand": true + }, + "js": { + "transformGroup": "js", + "files": [ + { + "destination": "tokens.js", + "format": "javascript/es6" + } + ] + } + } +} +``` + +#### DTCG Type Map + +Below is the standard DTCG type map that the expand utility comes out of the box with: + +```js +const DTCGTypesMap = { + // https://design-tokens.github.io/community-group/format/#stroke-style + strokeStyle: { + // does not yet have its own type defined, but is an enum of: "round" | "butt" | "square" + lineCap: 'other', + // note that this is spec'd to be a dimension array, which is unspecified in the spec for dimension + // generally speaking, transforms that match dimension type tokens do not account for this potentially being an array + // therefore we map it to "other" for now... + dashArray: 'other', + }, + // https://design-tokens.github.io/community-group/format/#border + border: { + style: 'strokeStyle', + width: 'dimension', + }, + // https://design-tokens.github.io/community-group/format/#transition + transition: { + delay: 'duration', + // needs more discussion https://github.com/design-tokens/community-group/issues/103 + timingFunction: 'cubicBezier', + }, + // https://design-tokens.github.io/community-group/format/#shadow + shadow: { + offsetX: 'dimension', + offsetY: 'dimension', + blur: 'dimension', + spread: 'dimension', + }, + // https://design-tokens.github.io/community-group/format/#gradient + gradient: { + position: 'number', + }, + // https://design-tokens.github.io/community-group/format/#typography + typography: { + fontSize: 'dimension', + letterSpacing: 'dimension', + lineHeight: 'number', + }, +}; +``` diff --git a/docs/src/content/docs/reference/logging.md b/docs/src/content/docs/reference/logging.md new file mode 100644 index 000000000..cbf607ab0 --- /dev/null +++ b/docs/src/content/docs/reference/logging.md @@ -0,0 +1,54 @@ +--- +title: Logging +sidebar: + order: 3 +--- + +You can customize the logging behavior of Style Dictionary. + +```js +const sd = new StyleDictionary({ + // these are the defaults + log: { + warnings: 'warn', // 'warn' | 'error' | 'disabled' + verbosity: 'default', // 'default' | 'silent' | 'verbose' + errors: { + brokenReferences: 'throw', // 'throw' | 'console' + }, + }, +}); +``` + +> `log` can also be set on platform specific configuration + +| Param | Type | Description | +| ----------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `log` | `Object` | | +| `log.warnings` | `'warn' \| 'error' \| 'disabled'` | Whether warnings should be logged as warnings, thrown as errors or disabled entirely. Defaults to 'warn' | +| `log.verbosity` | `'default' \|'silent' \| 'verbose'` | How verbose logs should be, default value is 'default'. 'silent' means no logs at all apart from fatal errors. 'verbose' means detailed error messages for debugging | +| `log.errors` | `Object` | How verbose logs should be, default value is 'default'. 'silent' means no logs at all apart from fatal errors. 'verbose' means detailed error messages for debugging | +| `log.errors.brokenReferences` | `'throw' \| 'console'` | Whether broken references in tokens should throw a fatal error or only a `console.error` without exiting the process. | + +There are five types of warnings that will be thrown as errors instead of being logged as warnings when `log.warnings` is set to `error`: + +- Token value collisions (in the source) +- Token name collisions (when exporting) +- Missing "undo" function for Actions +- File not created because no tokens found, or all of them filtered out +- Broken references in file when using outputReferences, but referring to a token that's been filtered out + +Verbosity configures whether the following warnings/errors should display in a verbose manner: + +- Token collisions of both types (value & name) +- Broken references due to outputReferences & filters +- Token reference errors + +And through `'silent'` it also configures whether success/neutral logs should be logged at all. + +By default the verbosity ('default') will keep logs relatively brief to prevent noise. + +## CLI + +Log verbosity can be passed as an option in the CLI by passing either `-v` or `--verbose` to get verbose logging, +and `-s` or `--silent` to get silent logging. +Warnings can be disabled by using the `-n` or `--no-warn` flag. diff --git a/docs/src/content/docs/reference/types.md b/docs/src/content/docs/reference/types.md new file mode 100644 index 000000000..6b10ae9e5 --- /dev/null +++ b/docs/src/content/docs/reference/types.md @@ -0,0 +1,5 @@ +--- +title: Types +--- + +Coming soon diff --git a/docs/src/content/docs/version-4/migration.md b/docs/src/content/docs/version-4/migration.md new file mode 100644 index 000000000..a35368ee7 --- /dev/null +++ b/docs/src/content/docs/version-4/migration.md @@ -0,0 +1,765 @@ +--- +title: Migration Guidelines +sidebar: + order: 2 +--- + +Version 4 of Style-Dictionary comes with a good amount of breaking changes compared to version 3. + +In this document, we will outline those breaking changes, ordered from most impactful to least. +Before and after examples are added to enable you to adjust your code to account for the changes. + +## ES Modules instead of CommonJS + +There are different ways to write JavaScript, NodeJS came up with CommonJS format and later browsers brought ES Modules format which NodeJS also supports. +ES Modules is nowadays considered the modern way to write JavaScript, NodeJS/Browser interoperability being only 1 of many reasons for that. + +Therefore, in version 4, Style Dictionary has been entirely rewritten in ES Modules, in a way that is browser-compatible out of the box, allowing you to run it in many more places compared to before. + +What this means for you is that if you are using Style Dictionary in a CommonJS project, you will have to either: + +- convert your project to ESM by putting `"type": "module"` in your `package.json` and migrating your JS files to be ESM format. Note that you usually can still [import CommonJS dependencies](https://nodejs.org/api/module.html#modulecreaterequirefilename) from ESM files, although this is not possible in browser environments. +- use `.mjs` extension for your Style Dictionary consuming code, but keep the rest of your project as CommonJS. +- dynamically import Style Dictionary into your CommonJS files `const StyleDictionary = (await import('style-dictionary')).default;` +- use a bundler tool that allows ESM / CommonJS interoperability, meaning you can combine both syntaxes. If I'm not mistaken, [bun](https://bun.sh/) (NodeJS alternative) supports that by default + +The above options are ordered, the top being the option we recommend the most, but this ordering is highly subjective. + +```js title="build-tokens.js" del={1} ins={2} +const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; +``` + +## Instantiating Style Dictionary + +Style Dictionary has become a class now in version 4 rather than just a regular JS object. +This means that you can create instances using the `new` class instantiator keyword. + +Due to ES Modules being asynchronous by nature, you will need to `await` initialization before you can access properties such as the `tokens` on the instance. + +`.extend()` method is still available on Style Dictionary instances if you want to create an instance (extend) from another instance.\ +[See the extend docs](/reference/api#extend). + +```js title="build-tokens.js" del={1,4} ins={2,5-6} +const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; + +const sd = StyleDictionary.extend('config.json'); +const sd = new StyleDictionary('config.json'); +await sd.hasInitialized; + +console.log(sd.tokens); +``` + +## Asynchronous API + +There are a couple of reasons for making most of Style Dictionary's methods asynchronous but the 2 most important reasons are: + +- ES Modules are asynchronous by nature, so many of the internal processes such as importing a config or token file are now async, causing other methods to become async as well by extension. +- Hooks now support asynchronous methods, to make them easier to work with. Example: you may want to run Prettier on your output files in your custom format, Prettier recently became async which means your format function would need to be async as well. + +The following StyleDictionary class methods are now async: + +- `extend()` +- `exportPlatform()` +- `getPlatform()` +- `buildAllPlatforms()` +- `buildPlatform()` +- `cleanAllPlatforms()` +- `cleanPlatform()` + +All hooks now support async functions as well, this should not be a breaking change for users since sync is also still supported. + +```js title="build-tokens.js" del={7-8} ins={4,9-10} +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +await sd.hasInitialized; +console.log(sd.allTokens); + +sd.cleanAllPlatforms(); +sd.buildAllPlatforms(); +await sd.cleanAllPlatforms(); +await sd.buildAllPlatforms(); +``` + +One exception is our `fileHeader` format helper utility, this is now an async function to support async fileHeaders. + +```js title="build-tokens.js" del={9,13} ins={10,14-15} +import StyleDictionary from 'style-dictionary'; + +// yes, this is another breaking change, more on that later +import { fileHeader } from 'style-dictionary/utils'; + +StyleDictionary.registerFormat({ + name: 'custom/css', + // this can be async now, usually it is if you use fileHeader format helper, since that now always returns a Promise + formatter: function ({ dictionary, file, options }) { + format: async function ({ dictionary, file, options }) { + const { outputReferences } = options; + return ( + fileHeader({ file }) + + // this helper is now async! because the user-passed file.fileHeader might be an async function + (await fileHeader({ file })) + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, +}); +``` + +## Hooks APIs + +We've given a name to all of the things that you can register which will execute custom behavior during the Style Dictionary lifecycle: `hooks`. +Available hooks are: `parsers`, `preprocessors`, `transformGroups`, `transforms`, `formats`, `filters`, `fileHeaders`, `actions`. + +:::note +The other hooks are also going to change similarly to preprocessors, in an effort to align these APIs and make them consistent across. +Hooks are now all grouped under the `hooks` property, they all use plural form vs singular (e.g. `transforms` vs `transform`), and lastly, +they will all use the same signature, with a `name` property and a handler function name that is the same as the hook name (e.g. `transformer` has become `transform`). +Parsers and preprocessors now also have to be applied explicitly in the config. +::: + +### Parsers + +Parsers, when registered, would always apply on a global level, without explicitly applying them in the config. +They are put inside the `hooks.parsers` property now, as opposed to `parsers`. +Lastly, the `parse` function is now `parser`, for consistency. + +Changes: + +```js title="config.js" del={3-10} ins={9-24} /parse(r): (/ +export default { + // register it inline or by SD.registerPreprocessor + parsers: [ + { + pattern: /\.json5$/, + parse: ({ contents, filePath }) => { + return JSON5.parse(contents); + }, + }, + ], + hooks: { + parsers: { + name: 'json5-parser', + pattern: /\.json5$/, + parser: ({ contents, filePath }) => { + return JSON5.parse(contents); + }, + }, + }, + // apply it globally by name reference + parsers: ['json5-parser'], +}; +``` + +### Preprocessors + +Preprocessors, when registered, would always apply on a global level, without explicitly applying them in the config. +They are put inside the `hooks.preprocessors` property now, as opposed to `preprocessors`. + +Changes: + +```js title="config.js" del={3-8} ins={9-24} +export default { + // register it inline or by SD.registerPreprocessor + preprocessors: { + foo: (dictionary) => { + // preprocess it + return dictionary; + }, + }, + hooks: { + preprocessors: { + foo: (dictionary) => { + // preprocess it + return dictionary; + }, + }, + }, + // apply it globally + preprocessors: ['foo'], + platforms: { + css: { + // or apply it per platform + preprocessors: ['foo'], + }, + }, +}; +``` + +### Transform Groups + +Transform groups, when registered, are put inside the `hooks.transformGroups` property now, as opposed to `transformGroup`. +Note the change from singular to plural form here. + +Changes: + +```js title="config.js" del={3-5} ins={6-10} /transformGroup(s): {/ +export default { + // register it inline or by SD.registerTransformGroup + transformGroup: { + foo: ['foo-transform'], + }, + hooks: { + transformGroups: { + foo: ['foo-transform'], + }, + }, + platforms: { + css: { + // apply it per platform + transformGroup: ['foo'], + }, + }, +}; +``` + +### Transforms + +Transforms, when registered, are put inside the `hooks.transforms` property now, as opposed to `transform`. +Note the change from singular to plural form here. + +The name of the filter function is now `filter` instead of `matcher`: + +```js title="build-tokens.js" del={6} ins={7} /filter/ /matcher/ +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerTransform({ + name: 'color-transform', + type: 'value', + matcher: (token) => token.type === 'color', + filter: (token) => token.type === 'color', + transform: (token) => token.value, +}); +``` + +Lastly, the `transformer` handler function has been renamed to `transform` for consistency. + +Changes: + +```js title="config.js" del={3-9} ins={10-18} /transform(s): {/ /filter/ /matcher/ /transform(er)/ /(transform): (/ +export default { + // register it inline or by SD.registerTransform + transform: { + 'color-transform': { + type: 'value', + matcher: (token) => token.type === 'color', + transformer: (token) => token.value, + }, + }, + hooks: { + transforms: { + 'color-transform': { + type: 'value', + filter: (token) => token.type === 'color', + transform: (token) => token.value, + }, + }, + }, + platforms: { + css: { + // apply it per platform + transforms: ['color-transform'], + }, + }, +}; +``` + +### Formats + +Formats, when registered, are put inside the `hooks.formats` property now, as opposed to `format`. +Note the change from singular to plural form here. + +The `formatter` handler function has been renamed to `format` for consistency. + +Lastly, some importable type interfaces have been renamed as well. + +Changes: + +```js title="config.js" del={2,8,14-16} ins={3,9,17-21} /format(s): {/ /format(ter)/ +import StyleDictionary from 'style-dictionary'; +import type { Formatter, FormatterArguments } from 'style-dictionary/types'; +import type { FormatFn, FormatFnArguments } from 'style-dictionary/types'; + +// register it with register method +StyleDictionary.registerFormat({ + name: 'custom/json', + formatter: ({ dictionary }) => JSON.stringify(dictionary, null, 2), + format: ({ dictionary }) => JSON.stringify(dictionary, null, 2), +}) + +export default { + // OR define it inline + format: { + 'custom/json': ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }, + hooks: { + formats: { + 'custom/json': ({ dictionary }) => JSON.stringify(dictionary, null, 2), + }, + }, + platforms: { + json: { + files: [{ + destination: 'output.json', + format: 'custom/json' + }], + }, + }, +}; +``` + +### File headers + +File headers, when registered, are put inside the `hooks.fileHeaders` property now, as opposed to `fileHeader`. +Note the change from singular to plural form here. + +```js title="config.js" del={2-4} ins={5-9} /fileHeader(s)/ +export default { + fileHeader: { + foo: (defaultMessages = []) => ['Ola, planet!', ...defaultMessages, 'Hello, World!'], + }, + hooks: { + fileHeaders: { + foo: (defaultMessages = []) => ['Ola, planet!', ...defaultMessages, 'Hello, World!'], + }, + }, + platforms: { + css: { + options: { + fileHeader: 'foo', + }, + }, + }, +}; +``` + +### Filters + +Filters, when registered, are put inside the `hooks.filters` property now, as opposed to `filter`. +Note the change from singular to plural form here. + +```js title="config.js" del={2-4} ins={5-9} /filter(s)/ +export default { + filter: { + 'colors-only': (token) => token.type === 'color, + }, + hooks: { + filters: { + 'colors-only': (token) => token.type === 'color, + }, + }, + platforms: { + css: { + files: [{ + format: 'css/variables', + destination: '_variables.css', + filter: 'colors-only', + }], + }, + }, +}; +``` + +In addition, when using [`registerFilter`](/reference/api#registerfilter) method, the name of the filter function is now `filter` instead of `matcher`: + +```js title="build-tokens.js" del={5} ins={6} +import StyleDictionary from 'style-dictionary'; + +StyleDictionary.registerFilter({ + name: 'colors-only', + matcher: (token) => token.type === 'color', + filter: (token) => token.type === 'color', +}); +``` + +:::note +These changes also apply for the [filter function inside transforms](#transforms). +::: + +### Actions + +Actions, when registered, are put inside the `hooks.actions` property now, as opposed to `action`. +Note the change from singular to plural form here. + +```js title="config.js" del={2-7} ins={8-15} /action(s): {/ +export default { + action: { + 'copy-assets': { + do: () => {} + undo: () => {} + } + }, + hooks: { + actions: { + 'copy-assets': { + do: () => {} + undo: () => {} + } + }, + }, + platforms: { + css: { + actions: ['copy-assets'], + files: [{ + format: 'css/variables', + destination: '_variables.css', + }], + }, + }, +}; +``` + +## CTI reliance + +[CTI or Category / Type / Item](/info/tokens/#category--type--item) used to be the default way of structuring design tokens in Style Dictionary. +Often, what type of token a token is, would be determined by looking at the "category" part of the token taxonomy. +Most of the [Built-in transforms](/reference/hooks/transforms/predefined) `matcher`/`filter` (filter being the new name for this) function would rely on the token's `attributes.category` property. +This in turn would rely on applying the [`attribute/cti` transform](/reference/hooks/transforms/predefined#attributecti) so that this attribute was set on a token. + +In version 4, we have removed almost all hard-coupling/reliances on CTI structure and instead we will look for a `token.type` property to determine what type of token a design token is. +This aligns more with the [Design Tokens Community Group specification](https://tr.designtokens.org/format/) for standardizing design tokens JSON format. + +```json title="tokens.json" ins={3-4,7} ""type": "color"" +{ + "color": { + // <-- this no longer needs to be "color" in order for + // the tokens inside this group to be considered of type "color" + "red": { + "value": "#FF0000", + "type": "color" + } + } +} +``` + +Additionally, the following transforms have changed: + +- Built-in name transforms are now reliant only on the token path, and are renamed from `name/cti/casing` to just `name/casing`. `name/ti/camel` and `name/ti/constant` have been removed. For example `name/cti/kebab` transform is now `name/kebab`. +- Transform `content/icon` has been renamed to `html/icon` since it targets HTML entity strings, not just any icon content. +- `font/objC/literal`, `font/swift/literal` and `font/flutter/literal` have been removed in favor of `content/objC/literal`, `content/swift/literal` and `content/flutter/literal`, as they do he exact same transformations. + +```json title="config.json" del={6,8,10,12,14,16-18} ins={7,9,11,13,15} +{ + "source": ["tokens.json"], + "platforms": { + "css": { + "transforms": [ + "name/cti/camel", + "name/camel", + "name/cti/kebab", + "name/kebab", + "name/cti/snake", + "name/snake", + "name/cti/human", + "name/human", + "name/cti/human", + "name/human", + "font/objC/literal", + "font/swift/literal", + "font/flutter/literal" + ] + } + } +} +``` + +## Package Entrypoints + +We've adopted [package entrypoints](https://nodejs.org/api/packages.html#package-entry-points), which is also referred to as export maps. + +What this means is, our `package.json` contains the following: + +```json +{ + "exports": { + ".": "./lib/StyleDictionary.js", + "./fs": { + "node": "./lib/fs-node.js", + "default": "./lib/fs.js" + }, + "./utils": "./lib/utils/index.js", + "./types": "./types/index.d.ts" + } +} +``` + +This allows Style Dictionary consumers to only import from those 4 entrypoints specified: + +```ts +import StyleDictionary from 'style-dictionary'; +import { usesReferences } from 'style-dictionary/utils'; +import { fs, setFs } from 'style-dictionary/fs'; +import type { DesignToken } from 'style-dictionary/types'; +``` + +Any other imports e.g. directly from a file path is disallowed and most modern package entrypoints supporting tools will not let you import from them. +This sets a clear and explicit boundary between what is considered public API versus private API, and prevents accidentally running into breaking changes in the future. + +Due to not allowing to import from file paths directly anymore, this is considered a breaking change. + +:::note +In order for your imports to work at all with package entrypoints, the tool you use for resolving bare import specifiers must have package entrypoints.\ +If you use `TypeScript` for example, you will need [`moduleResolution`](https://www.typescriptlang.org/tsconfig#moduleResolution) set to either `'nodenext'`, `'node16'` or `'bundler'`.\ +For `Rollup`, you will need [`@rollup/plugin-node-resolve`](https://github.com/rollup/plugins/tree/master/packages/node-resolve/#readme).\ +For `Webpack`, you will need version 5 at minimum.\ +For `Vite`, version 3. +::: + +## Format Helpers + +We moved the format helpers away from the StyleDictionary module/class into the utils entrypoint, for consistency in our API. + +```js title="build-tokens.js" del={1,3-4} ins={2} +import StyleDictionary from 'style-dictionary'; +import { fileHeader, formattedVariables } from 'style-dictionary/utils'; + +const { fileHeader, formattedVariables } = StyleDictionary.formatHelpers; +``` + +## Formatting options + +Using [file formats](/reference/hooks/formats), it is possible to pass options that influence how your output is created, and these options differ based on which format you are using. + +In v3, the following options were put on the file properties level itself next to `destination` and `format` props, but have been moved into the `options` property: + +- `className` -> for formats: + - `compose/object` + - `flutter/class.dart` + - `ios-swift/any.swift` + - `ios/colors.h` + - `ios/colors.m` + - `ios/singleton.h` + - `ios/singleton.m` + - `ios/static.m` + - `ios/strings.h` + - `ios/strings.m` +- `packageName` -> for formats: + - `compose/object` +- `type` -> for formats: + - `ios/colors.h` + - `ios/colors.m` + - `ios/singleton.h` + - `ios/singleton.m` + - `ios/static.h` + - `ios/static.m` +- `mapName` -> for formats: + - `scss/map-deep` + - `scss/map-flat` +- `name` -> for formats: + - `javascript/object` + - `javascript/umd` +- `resourceType` -> for formats: + - `android/resources` +- `resourceMap` -> for formats: + - `android/resources` + +```json title="config.json" del={9} ins={10-13} +{ + "source": ["tokens.json"], + "platforms": { + "css": { + "transformGroup": "scss", + "files": [ + { + "destination": "map.scss", + "format": "scss/map-deep", + "mapName": "tokens", + "options": { + "mapName": "tokens" + } + } + ] + } + } +} +``` + +## fileHeader default timestamp + +For all formats using the `fileHeader` `formatHelpers` utility (most of the built-ins do), it will no longer display a timestamp in the fileHeader output by default. This is now an opt-in by setting `file.formatting.fileHeaderTimestamp` to `true`. The reason for making this opt-in now is that using Style Dictionary in the context of a CI (continuous integration) pipeline is a common use-case, and when running on pull request event, output files always show a diff in git due to the timestamp changing, which often just means that the diff is bloated by redundancy. + +To achieve the old behavior: + +```json title="config.json" ins={10} +{ + "platforms": { + "css": { + "files": [ + { + "destination": "variables.css", + "format": "css/variables", + "options": { + "formatting": { + "fileHeaderTimestamp": true + } + } + } + ] + } + } +} +``` + +or: + +```js title="config.js" ins={5} +import { fileHeader } from 'style-dictionary/utils'; + +const headerContent = await fileHeader({ + formatting: { + fileHeaderTimestamp: true, + }, +}); +``` + +## Types + +Style Dictionary is entirely strictly typed now, and there will be `.d.ts` files published next to every file, this means that if you import from one of Style Dictionary's entrypoints, you automatically get the types implicitly with it. This is a big win for people using TypeScript, as the majority of the codebase now has much better types, with much fewer `any`s. + +If you need to import some specific type interfaces separately, you can do so from the `style-dictionary/types` entrypoint. + +```js title="build-tokens.js" del={1,3-5} ins={2} +import StyleDictionary from 'style-dictionary'; +import type { DesignToken, Transform } from 'style-dictionary/types'; + +declare type DesignToken = StyleDictionary.DesignToken; +declare type Transform = StyleDictionary.Transform; +``` + +[`typescript/module-declarations` format](/reference/hooks/formats/predefined#typescriptmodule-declarations) is updated with current DesignToken type interface, and type interface changes are technically always breaking, which is why it's mentioned here. + +## Reference utils + +Our reference utilities are now available from `style-dictionary/utils` entrypoint rather than attached to your StyleDictionary instance. +We've also updated the function signatures of the reference utilities to address this change and make them easier to reuse as well as more consistent in their APIs. + +```js title="build-tokens.js" del={9,11} ins={2,10,12} +import StyleDictionary from 'style-dictionary'; +import { usesReferences, getReferences } from 'style-dictionary/utils'; + +StyleDictionary.registerFormat({ + name: `myCustomFormat`, + format: function({ dictionary }) { + return dictionary.allTokens.map(token => { + let value = JSON.stringify(token.value); + if (dictionary.usesReference(token.original.value)) { + if (usesReferences(token.original.value, dictionary.tokens)) { + const refs = dictionary.getReferences(token.original.value); + const refs = getReferences(token.original.value, dictionary.tokens); + refs.forEach(ref => { + value = value.replace(ref.value, function() { + return `${ref.name}`; + }); + }); + } + return `export const ${token.name} = ${value};` + }).join(`\n`) + } +}); +``` + +In addition, we've added a [resolveReferences](/reference/utils/references#resolvereferences) utility to make it easy to get the resolved value of a token. + +## OutputReferences function + +We now allow specifying a `function` for `outputReferences`, conditionally outputting a ref or not per token. +We also published an [`outputReferencesFilter` utility function](/reference/utils/references#outputreferencesfilter) which will determine whether a token should be outputting refs based on whether those referenced tokens were filtered out or not. + +If you are maintaining a custom format that allows `outputReferences` option, you'll need to take into account that it can be a function, and pass the correct options to it. + +```js title="build-tokens.js" del={12} ins={13-17} +StyleDictionary.registerFormat({ + name: 'custom/es6', + format: async (dictionary) => { + const { allTokens, options, file } = dictionary; + const { usesDtcg } = options; + + const compileTokenValue = (token) => { + let value = usesDtcg ? token.$value : token.value; + const originalValue = usesDtcg ? token.original.$value : token.original.value; + + // Look here 👇 + const shouldOutputRefs = outputReferences && usesReferences(originalValue); + const shouldOutputRefs = + usesReferences(original) && + (typeof options.outputReferences === 'function' + ? outputReferences(token, { dictionary, usesDtcg }) + : options.outputReferences); + + if (shouldOutputRefs) { + // ... your code for putting back the reference in the output + value = ... + } + return value; + } + return `${allTokens.reduce((acc, token) => `${acc}export const ${token.name} = ${compileTokenValue(token)};\n`, '')}`; + }, +}); +``` + +## Logging + +Logging has been redesigned a fair bit and is more configurable now, [see Logging docs](/reference/logging). +Instead of only being able to specify `log: "error"` to change the default behavior of the logging to throw warnings as errors, +you can now also customize the verbosity of the logs and silence warnings and success logs. + +```json title="config.json" del={3} ins={4-7} +{ + "source": ["tokens.json"], + "log": "error", + "log": { + "warnings": "error", // "error", "warn", "disabled" -> "warn" is default + "verbosity": "verbose" // "silent", "default", "verbose" -> "default" is default + } +} +``` + +## Assets in CSS + +We no longer wrap tokens of type `asset` in double quotes. +Rather, we added a transform `asset/url` that will wrap such tokens inside `url("")` statements, this transform is applied to transformGroups `scss`, `css` and `less`. + +You may need to update your custom transforms if you were doing this transformation on your end, since it's now being done by default in those transformGroups. + +## Removed Deprecated features + +- `templates` and `registerTemplate`, use `formats` and `registerFormat` instead +- `properties` / `allProperties` props on the StyleDictionary instance + +```js title="build-tokens.js" del={5} ins={6} +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +await sd.hasInitialized; +console.log(sd.allProperties, sd.properties); +console.log(sd.allTokens, sd.tokens); +``` + +- `format.format` old function signature of `(dictionary, platform, file)` in favor of `({ dictionary, platform, options, file })`. + +```js title="build-tokens.js" del={8,10} ins={9,11} +import StyleDictionary from 'style-dictionary'; + +// yes, this is another breaking change, more on that later +import { fileHeader } from 'style-dictionary/utils'; + +StyleDictionary.registerFormat({ + name: 'custom/css', + formatter: async function (dictionary, platform, file) { + format: async function ({ dictionary, file, options }) { + const { outputReferences } = file.options; + const { outputReferences } = options; + return ( + fileHeader({ file }) + + // this helper is now async! because the user-passed file.fileHeader might be an async function + (await fileHeader({ file })) + + ':root {\n' + + formattedVariables({ format: 'css', dictionary, outputReferences }) + + '\n}\n' + ); + }, +}); +``` diff --git a/docs/src/content/docs/version-4/statement.md b/docs/src/content/docs/version-4/statement.md new file mode 100644 index 000000000..1e9f593d8 --- /dev/null +++ b/docs/src/content/docs/version-4/statement.md @@ -0,0 +1,31 @@ +--- +title: Version 4 statement +sidebar: + order: 1 + label: Statement +--- + +In May 2021, we started [an issue / RFC, "What would you like to see in Style Dictionary 4.0?"](https://github.com/amzn/style-dictionary/issues/643) to gather feedback on what the community would like to see. +Fortunately, in August 2023, the folks at [Tokens Studio](https://tokens.studio/) contacted us about co-maintaining this project, and leading the v4 release (and beyond)! + +We have started working on the biggest and most important changes, like migrating to ESM, making the library browser-compatible out of the box, and supporting asynchronicity in Style Dictionary's various APIs. There will be multiple prereleases to battle-test these changes before a final v4.0 is released. + +You can follow [this roadmap board](https://github.com/orgs/amzn/projects/4/views/1?layout=board) to keep an eye on the developments for v4.0, we will also keep adding to this board when we encounter changes we'd like to see in v4.0 that would entail a breaking change. Absence of something in this roadmap does not mean we don't see value in it, but rather that it could also be added in a (non-breaking) minor release within v4.x.x. + +## From the folks at Tokens Studio + +Hi everyone! I'm Joren from Tokens Studio, a big fan of this project (see [Style-Dictionary-Play](https://www.style-dictionary-play.dev/), [Token Configurator](https://configurator.tokens.studio/), [sd-transforms](https://github.com/tokens-studio/sd-transforms)) and the main pusher behind leading a 4.0 release of this project, I think it would be good to explain from our perspective why we've made the move to collaborate with Amazon on this. + +At Tokens Studio, we're a huge fan of Design Tokens and the workflows they enable. We believe exporting design tokens to various platforms is a key ingredient in ensuring that the journey from design to implementation code is smooth. +In our minds, Style Dictionary has been the most popular and most flexible library for reaching that goal, and so we want to build on top of that. +Rather than starting our own spinoff tool, we much prefer bringing Style Dictionary further, together with its vibrant community of contributors, which is why we reached out to Danny Banks. + +I think it's important to stress that it is our shared vision to keep Style Dictionary as an agnostic (so not "Tokens Studio"-specific) and flexible tool. As Tokens Studio, while we are highly incentivized to see this project progress further to strengthen our product journey, we value the open source community highly and want to make sure this library remains the go-to tool for exporting Design Tokens, whether you use Tokens Studio or not. + +We are very open to feedback and collaboration, feel free to reach out to us in [our Slack](https://join.slack.com/t/tokens-studio/shared_invite/zt-1p8ea3m6t-C163oJcN9g3~YZTKRgo2hg) -> `style-dictionary-v4` channel! + +## List of Changes + +The prereleases will contain breaking changes, so it's important to read the list of changes since v3 if you're looking to migrate. + +You can find the list of changes in [our changelog on the v4 branch](https://github.com/amzn/style-dictionary/blob/v4/CHANGELOG.md) diff --git a/docs/src/env.d.ts b/docs/src/env.d.ts new file mode 100644 index 000000000..acef35f17 --- /dev/null +++ b/docs/src/env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/docs/src/monaco/dark-theme.ts b/docs/src/monaco/dark-theme.ts new file mode 100644 index 000000000..6a928e26e --- /dev/null +++ b/docs/src/monaco/dark-theme.ts @@ -0,0 +1,127 @@ +export default { + base: 'vs-dark', + inherit: true, + rules: [ + { + background: '191919', + token: '', + }, + { + foreground: '3c403b', + token: 'comment', + }, + { + foreground: '5d90cd', + token: 'string', + }, + { + foreground: '46a609', + token: 'constant.numeric', + }, + { + foreground: '39946a', + token: 'constant.language', + }, + { + foreground: '927c5d', + token: 'keyword', + }, + { + foreground: '927c5d', + token: 'support.constant.property-value', + }, + { + foreground: '927c5d', + token: 'constant.other.color', + }, + { + foreground: '366f1a', + token: 'keyword.other.unit', + }, + { + foreground: 'a46763', + token: 'entity.other.attribute-name.html', + }, + { + foreground: '4b4b4b', + token: 'keyword.operator', + }, + { + foreground: 'e92e2e', + token: 'storage', + }, + { + foreground: '858585', + token: 'entity.other.inherited-class', + }, + { + foreground: '606060', + token: 'entity.name.tag', + }, + { + foreground: 'a165ac', + token: 'constant.character.entity', + }, + { + foreground: 'a165ac', + token: 'support.class.js', + }, + { + foreground: '606060', + token: 'entity.other.attribute-name', + }, + { + foreground: 'e92e2e', + token: 'meta.selector.css', + }, + { + foreground: 'e92e2e', + token: 'entity.name.tag.css', + }, + { + foreground: 'e92e2e', + token: 'entity.other.attribute-name.id.css', + }, + { + foreground: 'e92e2e', + token: 'entity.other.attribute-name.class.css', + }, + { + foreground: '616161', + token: 'meta.property-name.css', + }, + { + foreground: 'e92e2e', + token: 'support.function', + }, + { + foreground: 'ffffff', + background: 'e92e2e', + token: 'invalid', + }, + { + foreground: 'e92e2e', + token: 'punctuation.section.embedded', + }, + { + foreground: '606060', + token: 'punctuation.definition.tag', + }, + { + foreground: 'a165ac', + token: 'constant.other.color.rgb-value.css', + }, + { + foreground: 'a165ac', + token: 'support.constant.property-value.css', + }, + ], + colors: { + 'editor.foreground': '#fff', + 'editor.background': '#050608', + 'editor.selectionBackground': '#1C2633', + 'editor.lineHighlightBackground': '#D7D7D708', + 'editorCursor.foreground': '#008DCB', + 'editorWhitespace.foreground': '#BFBFBF', + }, +}; diff --git a/docs/src/monaco/github-light-theme.ts b/docs/src/monaco/github-light-theme.ts new file mode 100644 index 000000000..c83812188 --- /dev/null +++ b/docs/src/monaco/github-light-theme.ts @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: BSD-2-Clause +// +// Copyright 2021 Zhu Yun-ling +export default { + base: 'vs', + inherit: true, + rules: [ + { + background: 'ffffff', + token: '', + }, + { + foreground: '6a737d', + token: 'comment', + }, + { + foreground: '6a737d', + token: 'punctuation.definition.comment', + }, + { + foreground: '6a737d', + token: 'string.comment', + }, + { + foreground: '005cc5', + token: 'constant', + }, + { + foreground: '005cc5', + token: 'entity.name.constant', + }, + { + foreground: '005cc5', + token: 'variable.other.constant', + }, + { + foreground: '005cc5', + token: 'variable.language', + }, + { + foreground: '6f42c1', + token: 'entity', + }, + { + foreground: '6f42c1', + token: 'entity.name', + }, + { + foreground: '24292e', + token: 'variable.parameter.function', + }, + { + foreground: '22863a', + token: 'entity.name.tag', + }, + { + foreground: 'd73a49', + token: 'keyword', + }, + { + foreground: 'd73a49', + token: 'storage', + }, + { + foreground: 'd73a49', + token: 'storage.type', + }, + { + foreground: '24292e', + token: 'storage.modifier.package', + }, + { + foreground: '24292e', + token: 'storage.modifier.import', + }, + { + foreground: '24292e', + token: 'storage.type.java', + }, + { + foreground: '032f62', + token: 'string', + }, + { + foreground: '032f62', + token: 'punctuation.definition.string', + }, + { + foreground: '032f62', + token: 'string punctuation.section.embedded source', + }, + { + foreground: '005cc5', + token: 'support', + }, + { + foreground: '005cc5', + token: 'meta.property-name', + }, + { + foreground: 'e36209', + token: 'variable', + }, + { + foreground: '24292e', + token: 'variable.other', + }, + { + foreground: 'b31d28', + fontStyle: 'bold italic underline', + token: 'invalid.broken', + }, + { + foreground: 'b31d28', + fontStyle: 'bold italic underline', + token: 'invalid.deprecated', + }, + { + foreground: 'fafbfc', + background: 'b31d28', + fontStyle: 'italic underline', + token: 'invalid.illegal', + }, + { + foreground: 'fafbfc', + background: 'd73a49', + fontStyle: 'italic underline', + token: 'carriage-return', + }, + { + foreground: 'b31d28', + fontStyle: 'bold italic underline', + token: 'invalid.unimplemented', + }, + { + foreground: 'b31d28', + token: 'message.error', + }, + { + foreground: '24292e', + token: 'string source', + }, + { + foreground: '005cc5', + token: 'string variable', + }, + { + foreground: '032f62', + token: 'source.regexp', + }, + { + foreground: '032f62', + token: 'string.regexp', + }, + { + foreground: '032f62', + token: 'string.regexp.character-class', + }, + { + foreground: '032f62', + token: 'string.regexp constant.character.escape', + }, + { + foreground: '032f62', + token: 'string.regexp source.ruby.embedded', + }, + { + foreground: '032f62', + token: 'string.regexp string.regexp.arbitrary-repitition', + }, + { + foreground: '22863a', + fontStyle: 'bold', + token: 'string.regexp constant.character.escape', + }, + { + foreground: '005cc5', + token: 'support.constant', + }, + { + foreground: '005cc5', + token: 'support.variable', + }, + { + foreground: '005cc5', + token: 'meta.module-reference', + }, + { + foreground: '735c0f', + token: 'markup.list', + }, + { + foreground: '005cc5', + fontStyle: 'bold', + token: 'markup.heading', + }, + { + foreground: '005cc5', + fontStyle: 'bold', + token: 'markup.heading entity.name', + }, + { + foreground: '22863a', + token: 'markup.quote', + }, + { + foreground: '24292e', + fontStyle: 'italic', + token: 'markup.italic', + }, + { + foreground: '24292e', + fontStyle: 'bold', + token: 'markup.bold', + }, + { + foreground: '005cc5', + token: 'markup.raw', + }, + { + foreground: 'b31d28', + background: 'ffeef0', + token: 'markup.deleted', + }, + { + foreground: 'b31d28', + background: 'ffeef0', + token: 'meta.diff.header.from-file', + }, + { + foreground: 'b31d28', + background: 'ffeef0', + token: 'punctuation.definition.deleted', + }, + { + foreground: '22863a', + background: 'f0fff4', + token: 'markup.inserted', + }, + { + foreground: '22863a', + background: 'f0fff4', + token: 'meta.diff.header.to-file', + }, + { + foreground: '22863a', + background: 'f0fff4', + token: 'punctuation.definition.inserted', + }, + { + foreground: 'e36209', + background: 'ffebda', + token: 'markup.changed', + }, + { + foreground: 'e36209', + background: 'ffebda', + token: 'punctuation.definition.changed', + }, + { + foreground: 'f6f8fa', + background: '005cc5', + token: 'markup.ignored', + }, + { + foreground: 'f6f8fa', + background: '005cc5', + token: 'markup.untracked', + }, + { + foreground: '6f42c1', + fontStyle: 'bold', + token: 'meta.diff.range', + }, + { + foreground: '005cc5', + token: 'meta.diff.header', + }, + { + foreground: '005cc5', + fontStyle: 'bold', + token: 'meta.separator', + }, + { + foreground: '005cc5', + token: 'meta.output', + }, + { + foreground: '586069', + token: 'brackethighlighter.tag', + }, + { + foreground: '586069', + token: 'brackethighlighter.curly', + }, + { + foreground: '586069', + token: 'brackethighlighter.round', + }, + { + foreground: '586069', + token: 'brackethighlighter.square', + }, + { + foreground: '586069', + token: 'brackethighlighter.angle', + }, + { + foreground: '586069', + token: 'brackethighlighter.quote', + }, + { + foreground: 'b31d28', + token: 'brackethighlighter.unmatched', + }, + { + foreground: 'b31d28', + token: 'sublimelinter.mark.error', + }, + { + foreground: 'e36209', + token: 'sublimelinter.mark.warning', + }, + { + foreground: '959da5', + token: 'sublimelinter.gutter-mark', + }, + { + foreground: '032f62', + fontStyle: 'underline', + token: 'constant.other.reference.link', + }, + { + foreground: '032f62', + fontStyle: 'underline', + token: 'string.other.link', + }, + ], + colors: { + 'editor.foreground': '#24292e', + 'editor.background': '#ffffff', + 'editor.selectionBackground': '#c8c8fa', + 'editor.inactiveSelectionBackground': '#fafbfc', + 'editor.lineHighlightBackground': '#fafbfc', + 'editorCursor.foreground': '#24292e', + 'editorWhitespace.foreground': '#959da5', + 'editorIndentGuide.background': '#959da5', + 'editorIndentGuide.activeBackground': '#24292e', + 'editor.selectionHighlightBorder': '#fafbfc', + }, +}; diff --git a/docs/src/monaco/monaco.ts b/docs/src/monaco/monaco.ts new file mode 100644 index 000000000..ed6efcf82 --- /dev/null +++ b/docs/src/monaco/monaco.ts @@ -0,0 +1,129 @@ +import type * as monacoType from 'monaco-editor'; +import darkTheme from './dark-theme'; +import githubTheme from './github-light-theme'; + +export let monaco: typeof monacoType; + +declare global { + interface Window { + monaco: typeof monacoType; + require: NodeRequire | undefined; + } +} + +interface LoaderCallback { + resolve: () => void; + reject: (reason?: any) => void; + timeout: NodeJS.Timeout; +} + +let loaderPending = false; +const loaderCallbacks: LoaderCallback[] = []; + +function onAmdLoaderLoad() { + let currentCallback = loaderCallbacks.shift(); + while (currentCallback) { + window.clearTimeout(currentCallback.timeout); + currentCallback.resolve(); + currentCallback = loaderCallbacks.shift(); + } +} + +function onAmdLoaderError(err: any) { + let currentCallback = loaderCallbacks.shift(); + while (currentCallback) { + window.clearTimeout(currentCallback.timeout); + currentCallback.reject(err); + currentCallback = loaderCallbacks.shift(); + } +} + +export function ensureMonacoIsLoaded( + // srcPath = 'https://cdn.jsdelivr.net/npm/monaco-editor@0.29.1/dev' // <-- for debugging + srcPath = 'https://cdn.jsdelivr.net/npm/monaco-editor@0.29.1/min', +) { + return new Promise((resolve, reject) => { + if (monaco) { + resolve(null); + return; + } + const config = { + paths: { + vs: srcPath + '/vs', + vs_dev: srcPath.replace(/\/min$/, '/dev') + '/vs', + }, + }; + const loaderUrl = `${config.paths.vs}/loader.js`; + + const timeout = setTimeout(() => { + reject(new Error("Couldn't load monaco editor after 60s")); + }, 60000); + + loaderCallbacks.push({ + resolve: () => { + if (loaderPending) { + // @ts-expect-error config should be ok? + window.require.config(config); + loaderPending = false; + } + + // Cross domain workaround - https://github.com/Microsoft/monaco-editor/blob/master/docs/integrate-amd-cross.md + window.MonacoEnvironment = { + getWorkerUrl() { + return `data:text/javascript;charset=utf-8,${encodeURIComponent(` + self.MonacoEnvironment = { + baseUrl: '${srcPath}' + }; + importScripts('${srcPath}/vs/base/worker/workerMain.js');`)}`; + }, + }; + + // @ts-expect-error 2nd arg should be ok + window.require(['vs/editor/editor.main'], () => { + monaco = window.monaco; + resolve(null); + }); + }, + timeout, + reject, + }); + + if (!loaderPending) { + const loaderScript = window.document.createElement('script'); + loaderScript.type = 'text/javascript'; + loaderScript.src = loaderUrl; + loaderScript.addEventListener('load', onAmdLoaderLoad); + loaderScript.addEventListener('error', onAmdLoaderError); + window.document.body.appendChild(loaderScript); + loaderPending = true; + } + }); +} + +export async function init(elem: HTMLDivElement) { + await ensureMonacoIsLoaded(); + monaco.editor.defineTheme( + 'my-light-theme', + githubTheme as monacoType.editor.IStandaloneThemeData, + ); + monaco.editor.defineTheme('my-dark-theme', darkTheme as monacoType.editor.IStandaloneThemeData); + + const editor = monaco.editor.create(elem, { + theme: 'my-dark-theme', + }); + const resizeMonacoLayout = () => { + editor.layout({ + width: Math.min(800, elem.getBoundingClientRect().width), + height: 400, + }); + }; + resizeMonacoLayout(); + window.addEventListener('resize', resizeMonacoLayout); + return editor; +} + +export async function changeLang(lang: string, ed: typeof monacoType.editor) { + await ensureMonacoIsLoaded(); + // @ts-expect-error supposedly need to pass URI here... but cant find import to Uri for browser... + monaco.editor.setModelLanguage(ed.getModel(), lang); +} diff --git a/docs/src/remark-playground.ts b/docs/src/remark-playground.ts new file mode 100644 index 000000000..28d295934 --- /dev/null +++ b/docs/src/remark-playground.ts @@ -0,0 +1,80 @@ +import type { FootnoteDefinition, Root, Html, Blockquote, Paragraph, ListItem } from 'mdast'; +import { visit } from 'unist-util-visit'; + +const paragraphVisitor = ( + node: Paragraph, + index?: number, + parent?: Root | Blockquote | FootnoteDefinition | ListItem, +) => { + if ( + node.type === 'paragraph' && + node.children[0].type === 'text' && + node.children[0].value === '~ sd-playground' && + index && + parent + ) { + const serialize = (v: { value?: string; lang?: string }) => + JSON.stringify(v).replace(/"/g, '"'); + let tokensData = serialize({}); + let configData = serialize({}); + let scriptData = serialize({}); + let skipAmount = 1; + let defaultSelected; + + for (const child of parent.children.slice(index + 1, index + 4)) { + if (child.type !== 'code') break; + if (child.meta) { + const metas = child.meta?.split(' '); + switch (metas[0]) { + case 'tokens': + tokensData = serialize({ + value: child.value, + lang: child.lang ?? 'text', + }); + break; + case 'script': + scriptData = serialize({ + value: child.value, + lang: child.lang ?? 'text', + }); + break; + case 'config': + configData = serialize({ + value: child.value, + lang: child.lang ?? 'text', + }); + break; + } + if (metas[1] === 'selected') { + defaultSelected = metas[0]; + } + } + + skipAmount++; + } + + const newNode = { + type: 'html', + value: `
`, + } as Html; + parent.children.splice(index, skipAmount, newNode); + } +}; + +export function remarkPlayground() { + function transformer(tree: Root) { + visit(tree, 'paragraph', paragraphVisitor); + return tree; + } + + return transformer; +} diff --git a/docs/src/setup.ts b/docs/src/setup.ts new file mode 100644 index 000000000..b98f7bdf9 --- /dev/null +++ b/docs/src/setup.ts @@ -0,0 +1,129 @@ +import dark from '@shoelace-style/shoelace/dist/themes/dark.css?raw' assert { type: 'css' }; +import light from '@shoelace-style/shoelace/dist/themes/light.css?raw' assert { type: 'css' }; +import mermaid from 'mermaid'; +import { registeredComponents } from './components/sd-playground.ts'; + +type Theme = 'dark' | 'light'; +type EnhancedCSSSheet = CSSStyleSheet & { theme?: boolean }; + +// Load the theme css as strings and create adopted stylesheets +const themeAttr = 'data-theme'; // starlight theme attribute +let currTheme: Theme; +const sheets = { + dark: new CSSStyleSheet() as EnhancedCSSSheet, + light: new CSSStyleSheet() as EnhancedCSSSheet, +}; +sheets.dark.replaceSync(dark); +sheets.light.replaceSync(light); +// mark the stylesheets so it's easier to remove them later +sheets.dark.theme = true; +sheets.light.theme = true; + +// 77rem +const VP_THRESHOLD = 1231; +const getViewportWidth = () => + Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); + +async function renderMermaid() { + const theme = getSelectedTheme(); + const direction = getViewportWidth() > VP_THRESHOLD ? 'LR' : 'TB'; + mermaid.initialize({ + startOnLoad: false, + theme, + }); + const elements = [...document.querySelectorAll('.mermaid')] as HTMLPreElement[]; + await Promise.all( + [...elements].map((el) => { + // we're storing the original graph definition as a data attribute + // because mermaid's render will change the innerText + // and we need to be able to re-render on theme swap or window resize + const graphDefinition = el.getAttribute('data-mermaid-graph-definition') ?? el.innerText; + el.setAttribute('data-mermaid-graph-definition', graphDefinition); + return mermaid + .render('graphDiv', graphDefinition.replace('flowchart LR', `flowchart ${direction}`)) + .then(({ svg }) => { + el.innerHTML = svg; + }); + }), + ); + [...elements].forEach((el) => { + el.classList.remove('hidden'); + }); +} + +function getSelectedTheme() { + return document.documentElement.getAttribute(themeAttr) as Theme; +} + +async function swapTheme(theme: Theme) { + currTheme = theme; + // shoelace theme class + document.documentElement.classList.add(`sl-theme-${theme}`); + // swap out the shoelace adopted stylesheets + document.adoptedStyleSheets = [ + ...(document.adoptedStyleSheets as EnhancedCSSSheet[]).filter((sheet) => !sheet.theme), + sheets[theme], + ]; + + // change monaco theme for all sd playground instances + registeredComponents.forEach((comp) => { + comp.hasInitialized.then(() => { + comp.editor._themeService.setTheme(`my-${theme}-theme`); + }); + }); + await renderMermaid(); +} + +function handleThemeChange() { + // MutationObserver that watches the starlight theme attribute for changes, which is handled by the theme toggler + const themeObserver = new MutationObserver(() => { + const selectedTheme = getSelectedTheme(); + if (currTheme !== selectedTheme && (selectedTheme === 'dark' || selectedTheme === 'light')) { + swapTheme(selectedTheme); + } + }); + themeObserver.observe(document.documentElement, { + attributes: true, + attributeFilter: [themeAttr], + }); +} + +function lazilyLoadCEs(CEs: string[]) { + CEs.forEach((CE) => { + const firstInstance = document.querySelector(CE); + if (firstInstance) { + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + // Conditionally load the Web Component definition if we find an instance of it. + import(`./components/${CE}.ts`); + } + }); + }); + observer.observe(firstInstance); + } + }); +} + +function handleResize() { + let prevVPWidth = getViewportWidth(); + window.addEventListener('resize', () => { + const currVWWidth = getViewportWidth(); + if ( + (prevVPWidth >= VP_THRESHOLD && currVWWidth < VP_THRESHOLD) || + (prevVPWidth <= VP_THRESHOLD && currVWWidth > VP_THRESHOLD) + ) { + renderMermaid(); + } + prevVPWidth = currVWWidth; + }); +} + +async function setup() { + handleThemeChange(); + lazilyLoadCEs(['sd-playground', 'sd-dtcg-convert']); + handleResize(); + // initial + await swapTheme(getSelectedTheme()); +} +setup(); diff --git a/docs/src/styles.css b/docs/src/styles.css new file mode 100644 index 000000000..75a496d87 --- /dev/null +++ b/docs/src/styles.css @@ -0,0 +1,93 @@ +/* Dark mode colors. */ +:root { + --sl-color-accent-low: #074947; + --sl-color-accent: #3fc6bf; + --sl-color-accent-high: #80d9d6; +} + +/* Light mode colors. */ +:root[data-theme='light'] { + --sl-color-accent-low: #55b3af; + --sl-color-accent: #047771; + --sl-color-accent-high: #07524f; +} + +:root { + /* Changes the primary theme color to purple using primitives */ + --sl-color-primary-50: var(--sl-color-teal-50) !important; + --sl-color-primary-100: var(--sl-color-teal-100) !important; + --sl-color-primary-200: var(--sl-color-teal-200) !important; + --sl-color-primary-300: var(--sl-color-teal-300) !important; + --sl-color-primary-400: var(--sl-color-teal-400) !important; + --sl-color-primary-500: var(--sl-color-teal-500) !important; + --sl-color-primary-600: var(--sl-color-teal-600) !important; + --sl-color-primary-700: var(--sl-color-teal-700) !important; + --sl-color-primary-800: var(--sl-color-teal-800) !important; + --sl-color-primary-900: var(--sl-color-teal-900) !important; + --sl-color-primary-950: var(--sl-color-teal-950) !important; +} + +table code { + overflow-wrap: break-word; +} + +.monaco-editor div { + margin-top: 0 !important; +} + +.sl-container { + max-width: 900px; +} + +a { + display: inline-block; +} + +@media (min-width: 77rem) { + [data-has-sidebar][data-has-toc] .main-pane { + width: auto; + } +} + +@media (min-width: 77rem) { + .right-sidebar-container { + width: 400px; + } +} + +@media (max-width: 93rem) { + .right-sidebar-container { + display: none; + } +} + +@media (min-width: 77rem) { + .lg\:sl-flex { + display: flex; + justify-content: center; + } +} + +@media (max-width: 77rem) { + .lg\:sl-flex { + display: block; + } +} + +@media (min-width: 50rem) { + .hero { + grid-template-columns: 8fr 4fr; + } +} +.expressive-code pre.mermaid *:not(path) { + all: revert-layer; +} + +#graphDiv .clickable:hover .label-container { + stroke: #3fc6bf; + stroke-width: 3px; +} + +.hidden { + display: none !important; +} diff --git a/docs/src/utils/analyzeDependencies.ts b/docs/src/utils/analyzeDependencies.ts new file mode 100644 index 000000000..2a284420d --- /dev/null +++ b/docs/src/utils/analyzeDependencies.ts @@ -0,0 +1,36 @@ +import { parse } from 'acorn'; +import { asyncWalk } from 'estree-walker'; + +import type { Node } from 'estree-walker'; + +export async function analyzeDependencies(code: string) { + let dependencies: Array<{ + source: string; + specifiers: Array<{ name: string; default: boolean }>; + package: string; + }> = []; + const ast = parse(code, { + allowImportExportEverywhere: true, + ecmaVersion: 'latest', + }) as Node; + + await asyncWalk(ast, { + enter: async (node) => { + if (node.type === 'ImportDeclaration') { + const source = `${node.source.value}`; + dependencies.push({ + source: source, + specifiers: node.specifiers.map((spec) => ({ + name: spec.local.name, + default: spec.type === 'ImportDefaultSpecifier', + })), + package: source + .split('/') + .slice(0, source.startsWith('@') ? 2 : 1) + .join('/'), + }); + } + }, + }); + return dependencies; +} diff --git a/docs/src/utils/rollup-bundle.ts b/docs/src/utils/rollup-bundle.ts new file mode 100644 index 000000000..4239ab216 --- /dev/null +++ b/docs/src/utils/rollup-bundle.ts @@ -0,0 +1,95 @@ +import * as sdFs from 'style-dictionary/fs'; +import * as sdUtils from 'style-dictionary/utils'; +import { fs } from 'style-dictionary/fs'; +import { rollup } from '@rollup/browser'; +import { v4 as uuidv4 } from 'uuid'; +import StyleDictionary from 'style-dictionary'; +import virtual from '@rollup/plugin-virtual'; +import type { Plugin } from '@rollup/browser'; + +/** + * We bundle Javascript strings as if they were actual Javascript files + * - input as string instead of filepath (using virtual plugin) + * - resolve imports to bare modules as third party dependencies to esm.run CDN, + * has some limitations of course, see esm.run for info + * - any imports to style-dictionary are resolved to our version of style-dictionary in this app + * this is a bit spaghetti-written atm (abusing globals), and have to hardcode the different entrypoints, + * but it works :) + * - we used to support relative imports to other JS files but for studio we don't need this, we have only + * one config, one functions file, and tokens are JSON + */ +export async function bundle(inputString: string, _fs = fs) { + const sdName = uuidv4(); + const sdFsName = uuidv4(); + const sdUtilsName = uuidv4(); + // @ts-expect-error not allowed to put stuff on global with generated type string index + globalThis[sdName] = StyleDictionary; + // @ts-expect-error not allowed to put stuff on global with generated type string index + globalThis[sdFsName] = sdFs; + // @ts-expect-error not allowed to put stuff on global with generated type string index + globalThis[sdUtilsName] = sdUtils; + + const rollupCfg = await rollup({ + input: 'mod', + plugins: [ + virtual({ + mod: inputString, + }) as Plugin, + { + name: 'resolve-bare-esm-run', + async resolveId(id) { + // if id is not relative or absolute or style-dictionary -> bare import to resolve from esm.run + if (!id.match(/^(\/|\.).+$/g) && id !== 'style-dictionary') { + return { id: `https://esm.run/${id}`, external: true }; + } + return null; + }, + }, + { + name: 'sd-external', + // Naive and simplified regex version of rollup externals global plugin just for style-dictionary imports.. + transform(code) { + let rewrittenCode = code; + const reg = /import (?.+?) from [',"]style-dictionary(?\/.+?)?[',"];?/; + let matchRes; + while ((matchRes = reg.exec(rewrittenCode)) !== null) { + if (matchRes.groups) { + let { id, entrypoint } = matchRes.groups; + let namedImport = id; + let originalNamedImport = id; + let replacement = ''; + + if (id.startsWith('{') && id.endsWith('}') && entrypoint) { + id = id.replace('{', '').replace('}', '').trim(); + const entry = entrypoint.replace(/^\//, ''); + const asMatch = /(.+?) as (.+)/.exec(id); + + if (asMatch && asMatch[2]) { + [, originalNamedImport, namedImport] = asMatch; + } else { + originalNamedImport = namedImport = id; + } + + if (entry === 'fs') { + replacement = `globalThis['${sdFsName}']['${originalNamedImport}']`; + } else if (entry === 'utils') { + replacement = `globalThis['${sdUtilsName}']['${originalNamedImport}']`; + } + } else { + // Remove the import statement, replace the id wherever used with the global + replacement = `globalThis['${sdName}']`; + } + rewrittenCode = rewrittenCode + .replace(matchRes[0], '') + .replace(new RegExp(namedImport, 'g'), replacement); + } + } + + return rewrittenCode; + }, + }, + ], + }); + const bundle = await rollupCfg.generate({ format: 'es' }); + return bundle.output[0].code; +} diff --git a/docs/starlight-config.ts b/docs/starlight-config.ts new file mode 100644 index 000000000..eb86774c5 --- /dev/null +++ b/docs/starlight-config.ts @@ -0,0 +1,165 @@ +import type { StarlightUserConfig } from '@astrojs/starlight/types'; +import { pluginLanguageClass } from './expressive-code-plugin-language-class.ts'; + +export default { + expressiveCode: { + plugins: [ + // Call the plugin initialization function inside the `plugins` array + pluginLanguageClass(), + ], + styleOverrides: { + textMarkers: { + defaultLuminance: ['15%', '85%'], + }, + }, + }, + title: 'Style Dictionary', + description: + 'Export your Design Tokens to any platform. iOS, Android, CSS, JS, HTML, sketch files, style documentation, or anything you can think of. Forward-compatible with Design Token Community Group spec.', + logo: { src: './src/assets/logo.png', alt: 'Style-Dictionary logo, Pascal the chameleon.' }, + editLink: { + baseUrl: 'https://github.com/amzn/style-dictionary/edit/v4/docs/src/content/docs/', + }, + favicon: '/favicon.png', + social: { + github: 'https://github.com/amzn/style-dictionary/tree/v4', + slack: + 'https://join.slack.com/t/tokens-studio/shared_invite/zt-1p8ea3m6t-C163oJcN9g3~YZTKRgo2hg', + }, + tableOfContents: { + maxHeadingLevel: 4, + }, + sidebar: [ + { + label: 'Getting Started', + autogenerate: { directory: 'getting-started' }, + }, + { + label: 'More info', + autogenerate: { directory: 'info' }, + }, + { + label: 'Version 4', + autogenerate: { directory: 'version-4' }, + }, + { + label: 'Reference', + items: [ + { + label: 'API', + link: '/reference/api', + }, + { + label: 'Configuration', + link: '/reference/config', + }, + { + label: 'Logging', + link: '/reference/logging', + }, + { + label: 'Hooks', + collapsed: true, + items: [ + { label: 'Parsers', link: '/reference/hooks/parsers' }, + { label: 'Preprocessors', link: '/reference/hooks/preprocessors' }, + { + label: 'Transforms', + collapsed: true, + items: [ + { label: 'Overview', link: '/reference/hooks/transforms/' }, + { + label: 'Built-in Transforms', + link: '/reference/hooks/transforms/predefined', + }, + ], + }, + { + label: 'Transform Groups', + collapsed: true, + items: [ + { label: 'Overview', link: '/reference/hooks/transform-groups/' }, + { + label: 'Built-in Transform Groups', + link: '/reference/hooks/transform-groups/predefined', + }, + ], + }, + { + label: 'Formats', + collapsed: true, + items: [ + { label: 'Overview', link: '/reference/hooks/formats/' }, + { + label: 'Format Helpers', + link: '/reference/hooks/formats/helpers', + }, + { + label: 'Built-in Formats', + link: '/reference/hooks/formats/predefined', + }, + ], + }, + { label: 'Filters', link: '/reference/hooks/filters' }, + { label: 'File Headers', link: '/reference/hooks/file-headers' }, + { label: 'Actions', link: '/reference/hooks/actions' }, + ], + }, + { + label: 'Utils', + collapsed: true, + items: [ + { label: 'Overview', link: '/reference/utils/' }, + { label: 'References', link: '/reference/utils/references' }, + { label: 'Tokens', link: '/reference/utils/tokens' }, + { label: 'Format Helpers', link: '/reference/utils/format-helpers' }, + { label: 'Design Token Community Group', link: '/reference/utils/dtcg' }, + ], + }, + { + label: 'Types', + link: '/reference/types', + }, + ], + }, + { + label: 'Examples', + autogenerate: { directory: 'examples' }, + }, + ], + head: [ + { + tag: 'meta', + attrs: { + name: 'keywords', + content: + 'style-dictionary, style dictionary, style, dictionary, design, tokens, design tokens, design system, DTCG, W3C, Design Token Community Group', + }, + }, + { + tag: 'meta', + attrs: { + name: 'theme-color', + content: '#11aea7', + }, + }, + { + tag: 'meta', + attrs: { + name: 'og:image', + content: '/meta-img.png', + }, + }, + { + tag: 'meta', + attrs: { + name: 'og:image:alt', + content: 'Image of Style-Dictionary docs site', + }, + }, + ], + customCss: ['./src/styles.css'], + components: { + Head: './src/components/Head.astro', + }, +} as StarlightUserConfig; diff --git a/docs/templates.md b/docs/templates.md deleted file mode 100644 index 1f7bd1095..000000000 --- a/docs/templates.md +++ /dev/null @@ -1,7 +0,0 @@ -# Templates - -Templates are deprecated in favor of [Formats](formats.md) and will be removed in the future. If you want to use a template, create a [Format that uses templating](formats.md?id=using-a-template-templating-engine-to-create-a-format). - ->*__Why are Templates being deprecated in favor of Formats?__* - ->It is a simplification for users, no power is being removed. Anything you could do in a Template you can do in a Format. Since they both did the same thing people became confused on which method they were supposed to use for output. Even worse, we actually required you to specify if the output you wanted was defined as a format or as a template, even for those formats and templates included in Style Dictionary by default. This was a bad plan and caused problems for many users. Lastly, Style Dictionary aims to provide power and flexibility without forcing you to use any particular system, but only Lodash Templates were supported under the old template system. Using formats, you can use any templating engine you would like. diff --git a/docs/tokens.md b/docs/tokens.md deleted file mode 100644 index ae06d6928..000000000 --- a/docs/tokens.md +++ /dev/null @@ -1,400 +0,0 @@ -# Design Tokens - -> Synonyms: style properties, design variables, design constants, atoms - -Design tokens are the platform-agnostic way to define the input for Style Dictionary. A design token is a collection of attributes that describe any fundamental/atomic visual style. Each attribute is a key-value pair. - -![Terminology for different parts of a JSON property](assets/property-definitions.png) - -A design token is transformed for use in different platforms, languages, and contexts. A simple example is color. A color can be represented in many ways, all of these are the same color: `#ffffff`, `rgb(255,255,255)`, `hsl(0,0,1)`. - -A collection of design tokens which are organized in a nested object make the Style Dictionary. Here is an example of design tokens written for Style Dictionary: - -```json -{ - "color": { - "font": { - "base": { "value": "#111111" }, - "secondary": { "value": "#333333" }, - "tertiary": { "value": "#666666" }, - "inverse": { - "base": { "value": "#ffffff" } - } - } - } -} -``` - -Any node in the object that has a `value` attribute on it is a design token. In this example there are 4 style design tokens: `color.font.base`, `color.font.secondary`, `color.font.tertiary`, and `color.font.inverse.base`. - -## Design token attributes - -For any design tokens you wish to output, the "value" attribute is required. This provides the data that will be used throughout the build process (and ultimately used for styling in your deliverables). You can optionally include any custom attributes you would like (e.g. "comment" with a string or "metadata" as an object with its own attributes). - -| Attribute | Type | Description | -| :--- | :--- | :--- | -| value | Any | The value of the design token. This can be any type of data, a hex string, an integer, a file path to a file, even an object or array. -| comment | String (optional) | The comment attribute will show up in a code comment in output files if the format supports it. -| themeable | Boolean (optional) | This is used in formats that support override-able or themable values like the `!default` flag in Sass. -| name | String (optional) | Usually the name for a design token is generated with a [name transform](transforms.md#transform-types), but you can write your own if you choose. By default Style Dictionary will add a default name which is the key of the design token object. -| attributes | Object (optional) | Extra information about the design token you want to include. [Attribute transforms](transforms.md#transform-types) will modify this object so be careful - -You can add any attributes or data you want in a design token and Style Dictionary will pass it along to transforms and formats. For example, you could add a `deprecated` flag like in [this example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation). Other things you can do is add documentation information about each design token or information about color contrast. - -### Default design token metadata - -Style Dictionary adds some default metadata on each design token that helps with transforms and formats. Here is what Style Dictionary adds onto each design token: - -| Attribute | Type | Description | -| :--- | :--- | :--- | -| name | String | A default name of the design token that is set to the key of the design token. This is only added if you do not provide one. -| path | Array[String] | The object path of the design token. `color: { background: { primary: { value: "#fff" } } }` will have a path of `['color','background', 'primary']`. -| original | Object | A pristine copy of the original design token object. This is to make sure transforms and formats always have the unmodified version of the original design token. -| filePath | String | The file path of the file the token is defined in. This file path is derived from the `source` or `include` file path arrays defined in the [configuration](config.md). -| isSource | Boolean | If the token is from a file defined in the `source` array as opposed to `include` in the [configuration](config.md). - -Given this configuration: - -```json5 -{ - "source": ["tokens/**/*.json"] - //... -} -``` - -This design token: - -```json5 -// tokens/color/background.json -{ - "color": { - "background": { - "primary": { "value": "#fff" } - } - } -} -``` - -becomes: - -```json5 -{ - "color": { - "background": { - "primary": { - "name": "primary", - "value": "#fff", - "path": ["color","background","primary"], - "original": { - "value": "#fff" - }, - "filePath": "tokens/color/background.json", - "isSource": true - } - } - } -} -``` - - ----- - - -## Referencing / Aliasing - -You can reference (alias) existing values by using the dot-notation object path (the fully articulated design token name) in curly brackets. Note that this only applies to values; referencing a non-value design token will cause unexpected results in your output. - -```json -{ - "size": { - "font": { - "small" : { "value": "10" }, - "medium": { "value": "16" }, - "large" : { "value": "24" }, - "base" : { "value": "{size.font.medium.value}" } - } - } -} -``` - -See more in the advanced [referencing-aliasing example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing). - - ----- - - -## Defining design tokens - -Design token files can included inline in the configuration, or be written in separate files. Style Dictionary supports these languages for design token files: - -* JSON -* [JSONC](https://code.visualstudio.com/docs/languages/json#_json-with-comments) -* [JSON5](https://json5.org) -* CommonJS modules -* Potentially any language with [custom parsers](#customfileparsers) - -Tokens can be defined *inline* in the Style Dictionary configuration, or in files. You can add a `tokens` object to your Style Dictionary configuration like this: - -```javascript -// config.js -module.exports = { - tokens: { - color: { - background: { - primary: { value: "#fff" } - } - } - }, - platforms: { - //... - } -} -``` - -Generally you will have too many design tokens to include them all inline, so you can separate them out into their own files. You can tell Style Dictionary where to find your design token files with the `source` and `include` attributes in the configuration like this: - -```javascript -module.exports = { - include: [ - // you can list singular files: - `node_modules/my-other-style-dictionary/tokens.json` - ], - source: [ - // or use file path [globs](https://www.npmjs.com/package/glob) - // this says grab all files in the tokens directory with a .json extension - `tokens/**/*.json` - ] - // ... -} -``` - -**You can organize your design token files in any way as long as you can tell Style Dictionary where to find them.** The directory and file structure of design token files does not have any effect on the object structure of the tokens because Style Dictionary does a deep merge on all design token files. Separating tokens into files and folders is to make the authoring experience cleaner and more flexible. - -### Collision warnings - -Style Dictionary takes all the files it finds in the include and source arrays and performs a deep merge on them. It will first add files in the include array, in order, and then the source array in order. Later files will take precedence. For example if you defined 2 source files like this: - -```javascript -module.exports = { - source: [ - `tokens.json`, - `tokens2.json` - ] -} -``` - -```json5 -// tokens.json -{ - "color": { - "background": { - "primary": { "value": "#fff" }, - "secondary": { "value": "#ccc" } - } - } -} -``` - -```json5 -// tokens2.json -{ - "color": { - "background": { - "primary": { "value": "#eee" }, - "tertiary": { "value": "#999" } - } - } -} -``` - -The resulting merged dictionary would be: - -```json5 -{ - "color": { - "background": { - "primary": { "value": "#eee" }, - "secondary": { "value": "#ccc" }, - "tertiary": { "value": "#999" } - } - } -} -``` - -This example would show a warning in the console that you have a collision at `color.background.primary` because 2 source files defined the same design token. A file in source overriding a file in include will not show a warning because the intent is that you include files you want to potentially override. For example, if you had multiple brands and you wanted to share a default theme, you could include the default theme and then override certain parts. - -### CommonJS modules - -One way to write your design token files is to write them in Javascript rather than JSON. The only requirement for writing your source files in Javascript is to use a CommonJS module to export a plain object. For example: - -```javascript -module.exports = { - color: { - base: { - red: { value: '#ff0000' } - } - } -} -``` - -is equivalent to this JSON file: - -```json -{ - "color": { - "base": { - "red": { "value": "#ff0000" } - } - } -} -``` - -You might prefer authoring your design token files in Javascript because it can be a bit more friendly to read and write (don't have to quote keys, can leave dangling commas, etc.). Writing your design token files as Javascript gives you more freedom to do complex things like generating many tokens based on code: - -```javascript -const Color = require('tinycolor2'); - -const baseColors = { - red: {h: 4, s: 62, v: 90}, - purple: {h: 262, s: 47, v: 65}, - blue: {h: 206, s: 70, v: 85}, - teal: {h: 178, s: 75, v: 80}, - green: {h: 119, s: 47, v: 73}, - yellow: {h: 45, s: 70, v: 95}, - orange: {h: 28, s: 76, v: 98}, - grey: {h: 240, s: 14, v: 35}, -} - -// Use a reduce function to take the array of keys in baseColor -// and map them to an object with the same keys. -module.exports = Object.keys(baseColors).reduce((ret, color) => { - return Object.assign({}, ret, { - [color]: { - // generate the shades/tints for each color - "20": { value: Color(baseColors[color]).lighten(30).toString()}, - "40": { value: Color(baseColors[color]).lighten(25).toString()}, - "60": { value: Color(baseColors[color]).lighten(20).toString()}, - "80": { value: Color(baseColors[color]).lighten(10).toString()}, - "100": { value: baseColors[color]}, - "120": { value: Color(baseColors[color]).darken(10).toString()}, - "140": { value: Color(baseColors[color]).darken(20).toString()} - } - }) -}, {}); -``` - -Take a look at the [this example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) if you want to see a more in-depth example of using Javascript files as input. - -### Custom file parsers - -Starting in 3.0, you can define custom parsers to parse your source files. This allows you to author your design token files in other languages like [YAML](https://yaml.org/). Custom parsers run on certain input files based on a file path pattern regular expression (similar to how Webpack loaders work). The parser function gets the contents of the file and is expected to return an object of the data of that file for Style Dictionary to merge with the other input file data. - -```javascript -const StyleDictionary = require('style-dictionary'); - -StyleDictionary.registerParser({ - pattern: /.json$/, - parse: ({contents, filePath}) => { - return JSON.parse(contents); - } -}); -``` - -[Here is a complete custom file parser example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) - -[yaml-tokens example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) - - ----- - - -## Design token structure - -You can structure your tokens any way you want. You could have a flat object rather than a nested one: - -```json -{ - "colorBackgroundPrimary": { "value": "#fff" }, - "sizePaddingLarge": { "value": 4 } -} -``` - -### Category / Type / Item - -**This structure is not required.** This is just one example of how to structure your design tokens. - -Design tokens are organized into a hierarchical tree structure with 'category' defining the primitive nature of the design token. For example, we have the color category and every design token underneath is always a color. As you proceed down the tree, you get more specific about what that color is. Is it a background color, a text color, or a border color? What kind of text color is it? You get the point. It's like the animal kingdom classification: - -![](assets/cti.png) - -Now you can structure your tokens in a nested object like this: - -```json -{ - "size": { - "font": { - "base": { "value": "16" }, - "large": { "value": "20" } - } - } -} -``` - -The CTI is implicit in the structure, the category is 'size' and the type is 'font', and there are 2 tokens 'base' and 'large'. - -Structuring design tokens in this manner gives us consistent naming and accessing of these tokens. You don't need to remember if it is `button_color_error` or `error_button_color`, it is `color_background_button_error`! - -You can organize and name your design tokens however you want, **there are no restrictions**. But there are a good amount of helpers if you do use this structure, like the 'attribute/cti' transform which adds attributes to the design token of its CTI based on the path in the object. There are a lot of names transforms as well for when you want a flat structure like for Sass variables. - -Also, the CTI structure provides a good mechanism to target transforms for specific kinds of tokens. All of the transforms provided by the framework use the CTI structure to know if it should be applied. For instance, the 'color/hex' transform only applies to tokens of the category 'color'. - -Here are the categories and types the built-in transforms and formats use: - -#### Category: color -Everything under this category is a color. You can further organize by background, font, border, etc. if you want. The built-ins only look for a category of `color` -* [`color/rgb`](transforms.md#colorrgb) -* [`color/hsl`](transforms.md#colorhsl) -* [`color/hsl-4`](transforms.md#colorhsl-4) -* [`color/hex`](transforms.md#colorhex) -* [`color/hex8`](transforms.md#colorhex8) -* [`color/hex8android`](transforms.md#colorhex8android) -* [`color/UIColor`](transforms.md#coloruicolor) -* [`color/UIColorSwift`](transforms.md#coloruicolorswift) -* [`color/ColorSwiftUI`](transforms.md#colorcolorswiftui) -* [`color/css`](transforms.md#colorcss) -* [`color/sketch`](transforms.md#colorsketch) -* [`color/hex8flutter`](transforms.md#colorhex8flutter) - -#### Category: size -Most platforms any type of size is treated the same. On Android it is common to use SP for font sizes and DP for paddings and dimensions. -* [`size/sp`](transforms.md#sizesp) -* [`size/dp`](transforms.md#sizedp) -* [`size/object`](transforms.md#sizeobject) -* [`size/remToSp`](transforms.md#sizeremtosp) -* [`size/remToDp`](transforms.md#sizeremtodp) -* [`size/px`](transforms.md#sizepx) -* [`size/rem`](transforms.md#sizerem) -* [`size/remToPt`](transforms.md#sizeremtopt) -* [`size/swift/remToCGFloat`](transforms.md#sizeswiftremtocgfloat) -* [`size/remToPx`](transforms.md#sizeremtopx) -* [`size/pxToRem`](transforms.md#sizepxtorem) -* [`size/flutter/remToDouble`](transforms.md#sizeflutterremtodouble) - -#### Category: time -* [`time/seconds`](transforms.md#timeseconds) - -#### Category: asset -These should be file paths used for images and font files -* [`asset/base64`](transforms.md#assetbase64) -* [`asset/path`](transforms.md#assetpath) -* [`asset/objC/literal`](transforms.md#assetobjcliteral) -* [`asset/swift/literal`](transforms.md#assetswiftliteral) -* [`asset/flutter/literal`](transforms.md#assetflutterliteral) - -#### Category: content -These should be strings -* [`content/icon`](transforms.md#contenticon) -* [`content/quote`](transforms.md#contentquote) -* [`content/objC/literal`](transforms.md#contentobjcliteral) -* [`content/swift/literal`](transforms.md#contentswiftliteral) -* [`content/flutter/literal`](transforms.md#contentflutterliteral) diff --git a/docs/transform_groups.md b/docs/transform_groups.md deleted file mode 100644 index 2b13eda73..000000000 --- a/docs/transform_groups.md +++ /dev/null @@ -1,245 +0,0 @@ - -# Transform Groups - -Transform Groups are a way to easily use multiple transforms at once. They are an array of transforms. You can define a custom transform group with the [`registerTransformGroup`](api.md#registertransformgroup). - -You use transformGroups in your config file under platforms > [platform] > transformGroup - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "android": { - "transformGroup": "android" - } - } -} -``` - ----- - -## Pre-defined Transform groups - -[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transformGroups.js) - -### web - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/kebab](transforms.md#namectikebab) -[size/px](transforms.md#sizepx) -[color/css](transforms.md#colorcss) - - -* * * - -### js - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/pascal](transforms.md#namectipascal) -[size/rem](transforms.md#sizerem) -[color/hex](transforms.md#colorhex) - - -* * * - -### scss - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/kebab](transforms.md#namectikebab) -[time/seconds](transforms.md#timeseconds) -[content/icon](transforms.md#contenticon) -[size/rem](transforms.md#sizerem) -[color/css](transforms.md#colorcss) - - -* * * - -### css - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/kebab](transforms.md#namectikebab) -[time/seconds](transforms.md#timeseconds) -[content/icon](transforms.md#contenticon) -[size/rem](transforms.md#sizerem) -[color/css](transforms.md#colorcss) - - -* * * - -### less - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/kebab](transforms.md#namectikebab) -[time/seconds](transforms.md#timeseconds) -[content/icon](transforms.md#contenticon) -[size/rem](transforms.md#sizerem) -[color/hex](transforms.md#colorhex) - - -* * * - -### html - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[attribute/color](transforms.md#attributecolor) -[name/human](transforms.md#namehuman) - - -* * * - -### android - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/snake](transforms.md#namectisnake) -[color/hex8android](transforms.md#colorhex8android) -[size/remToSp](transforms.md#sizeremtosp) -[size/remToDp](transforms.md#sizeremtodp) - - -* * * - -### compose - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/camel](transforms.md#namecticamel) -[color/composeColor](transforms.md#colorcomposecolor) -[size/compose/em](transforms.md#sizecomposeem) -[size/compose/remToSp](transforms.md#sizecomposeremtosp) -[size/compose/remToDp](transforms.md#sizecomposeremtodp) - - -* * * - -### ios - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/pascal](transforms.md#namectipascal) -[color/UIColor](transforms.md#coloruicolor) -[content/objC/literal](transforms.md#contentobjcliteral) -[asset/objC/literal](transforms.md#assetobjcliteral) -[size/remToPt](transforms.md#sizeremtopt) -[font/objC/literal](transforms.md#fontobjcliteral) - - -* * * - -### ios-swift - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/camel](transforms.md#namecticamel) -[color/UIColorSwift](transforms.md#coloruicolorswift) -[content/swift/literal](transforms.md#contentswiftliteral) -[asset/swift/literal](transforms.md#assetswiftliteral) -[size/swift/remToCGFloat](transforms.md#sizeswiftremtocgfloat) -[font/swift/literal](transforms.md#fontswiftliteral) - - -* * * - -### ios-swift-separate - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/ti/camel](transforms.md#nameticamel) -[color/UIColorSwift](transforms.md#coloruicolorswift) -[content/swift/literal](transforms.md#contentswiftliteral) -[asset/swift/literal](transforms.md#assetswiftliteral) -[size/swift/remToCGFloat](transforms.md#sizeswiftremtocgfloat) -[font/swift/literal](transforms.md#fontswiftliteral) - -This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the token (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). - - -* * * - -### assets - - -Transforms: - -[attribute/cti](transforms.md#attributecti) - - -* * * - -### flutter - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/cti/camel](transforms.md#namecticamel) -[color/hex8flutter](transforms.md#colorhex8flutter) -[size/flutter/remToDouble](transforms.md#sizeflutterremToDouble) -[content/flutter/literal](transforms.md#contentflutterliteral) -[asset/flutter/literal](transforms.md#assetflutterliteral) -[font/flutter/literal](transforms.md#fontflutterliteral) - - -* * * - -### flutter-separate - - -Transforms: - -[attribute/cti](transforms.md#attributecti) -[name/ti/camel](transforms.md#nameticamel) -[color/hex8flutter](transforms.md#colorhex8flutter) -[size/flutter/remToDouble](transforms.md#sizeflutterremToDouble) -[content/flutter/literal](transforms.md#contentflutterliteral) -[asset/flutter/literal](transforms.md#assetflutterliteral) -[font/flutter/literal](transforms.md#fontflutterliteral) - -This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the token (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). - - -* * * - -### react-native - - -Transforms: - -[name/cti/camel](transforms.md#namecticamel) -[size/object](transforms.md#sizeobject) -[color/css](transforms.md#colorcss) - - -* * * - diff --git a/docs/transforms.md b/docs/transforms.md deleted file mode 100644 index 23824a38e..000000000 --- a/docs/transforms.md +++ /dev/null @@ -1,849 +0,0 @@ - -# Transforms - -Transforms are functions that modify a [token](tokens.md) so that it can be understood by a specific platform. It can modify the name, value, or attributes of a token - enabling each platform to use the design token in different ways. A simple example is changing pixel values to point values for iOS and dp or sp for Android. - -Transforms are isolated per platform; each platform begins with the same design token and makes the modifications it needs without affecting other platforms. The order you use transforms matters because transforms are performed sequentially. Transforms are used in your [configuration](config.md), and can be either [pre-defined transforms](transforms.md?id=pre-defined-transforms) supplied by Style Dictionary or [custom transforms](transforms.md?id=defining-custom-transforms). - -Some platform configuration attributes apply a broader effect over the transforms applied. For example, the `size/remToDp` transform will scale a number by 16, or by the value of `options.basePxFontSize` if it is present. Check individual transform documentation to see where this is applicable. - - - -## Using Transforms -You use transforms in your config file under platforms > [platform] > transforms - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "android": { - "transforms": ["attribute/cti", "name/cti/kebab", "color/hex", "size/rem"] - } - } -} -``` - -A transform consists of 4 parts: type, name, matcher, and transformer. Transforms are run on all design tokens where the matcher returns true. *NOTE: if you don't provide a matcher function, it will match all tokens.* - -## Transform Types -There are 3 types of transforms: attribute, name, and value. - -**Attribute:** An attribute transform adds to the attributes object on a design token. This is for including any meta-data about a design token such as it's CTI or other information. - -**Name:** A name transform transform the name of a design token. You should really only be apply one name transformer because they will override each other if you use more than one. - -**Value:** The value transform is the most important as this is the one that changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a matcher function that filter which tokens that transform runs on. This allows us to only run a color transform on only the colors and not every design token. - -## Defining Custom Transforms -You can define custom transforms with the [`registerTransform`](api.md#registertransform). Style Dictionary adds some [default metadata](tokens.md?id=default-design-token-metadata) to each design token to provide context that may be useful for some transforms. - -## Transitive Transforms -Starting in version 3.0, you can define transitive transforms which allow you to transform a referenced value. Normally, value transforms only transform non-referenced values and because transforms happen before references are resolved, the transformed value is then used to resolve references. - -```javascript -const StyleDictionary = require('style-dictionary'); - -StyleDictionary.registerTransform({ - type: `value`, - transitive: true, - name: `myTransitiveTransform`, - matcher: (token) => {}, - transformer: (token) => { - // token.value will be resolved and transformed at this point - } -}) -``` - -There is one thing to be mindful of with transitive transforms. The token's value will be resolved and *transformed* already at the time the transitive transform. What happens is Style Dictionary will transform and resolve values iteratively. First it will transform any non-referenced values, then it will resolve any references to non-referenced values, then it will try to transform any non-referenced values, and so on. Let's take a look at an example: - -```json -{ - "color": { - "red": { "value": "#f00" }, - "danger": { "value": "{color.red}" }, - "error": { "value": "{color.danger}" } - } -} -``` - -Style dictionary will first transform the value of `color.red`, then resolve `color.danger` to the transformed `color.red` value. Then it will transform `color.danger` and resolve `color.error` to the transformed `color.danger`. Finally, it will transform `color.error` and see that there is nothing left to transform or resolve. - -This allows you to modify a reference that modifies another reference. For example: - -```json -{ - "color": { - "red": { "value": "#f00" }, - "danger": { "value": "{color.red}", "darken": 0.75 }, - "error": { "value": "{color.danger}", "darken": 0.5 } - } -} -``` - -Using a custom transitive transform you could have `color.danger` darken `color.red` and `color.error` darken `color.danger`. The pre-defined transforms are *not transitive* to be backwards compatible with Style Dictionary v2 - an upgrade should not cause breaking changes. - -If you want to learn more about transitive transforms, take a look at the [transitive transforms example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms). - - -## Pre-defined Transforms - -[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transforms.js) - -> All the pre-defined transforms included use the [CTI structure](tokens.md?id=category-type-item) for matching tokens. If you structure your design tokens differently you will need to write [custom transforms](transforms.md?id=defining-custom-transforms) or make sure the proper CTIs are on the attributes of your design tokens. - -### attribute/cti - - -Adds: category, type, item, subitem, and state on the attributes object based on the location in the style dictionary. - -```js -// Matches: all -// Returns: -{ - "category": "color", - "type": "background", - "item": "button", - "subitem": "primary", - "state": "active" -} -``` - - -* * * - -### attribute/color - - -Adds: hex, hsl, hsv, rgb, red, blue, green. - -```js -// Matches: token.attributes.category === 'color' -// Returns -{ - "hex": "009688", - "rgb": {"r": 0, "g": 150, "b": 136, "a": 1}, - "hsl": {"h": 174.4, "s": 1, "l": 0.294, "a": 1}, - "hsv": {"h": 174.4, "s": 1, "l": 0.588, "a": 1}, -} -``` - - -* * * - -### name/human - - -Creates a human-friendly name - -```js -// Matches: All -// Returns: -"button primary" -``` - - -* * * - -### name/cti/camel - - -Creates a camel case name. If you define a prefix on the platform in your config, it will prepend with your prefix - -```js -// Matches: all -// Returns: -"colorBackgroundButtonPrimaryActive" -"prefixColorBackgroundButtonPrimaryActive" -``` - - -* * * - -### name/ti/camel - - -Creates a camel case name without the category at the front. This is most useful when there is a class, struct, enum, etc. -that already has the category in it (e.g., StyleDictionaryColors.baseDarkRed instad of StyleDictionaryColors.colorBaseDarkRed). -If you define a prefix on the platform in your config, it will prepend with your prefix - -```js -// Matches: all -// Returns: -"backgroundButtonPrimaryActive" -"prefixBackgroundButtonPrimaryActive" -``` - - -* * * - -### name/cti/kebab - - -Creates a kebab case name. If you define a prefix on the platform in your config, it will prepend with your prefix - -```js -// Matches: all -// Returns: -"color-background-button-primary-active" -"prefix-color-background-button-primary-active" -``` - - -* * * - -### name/cti/snake - - -Creates a snake case name. If you define a prefix on the platform in your config, it will prepend with your prefix - -```js -// Matches: all -// Returns: -"color_background_button_primary_active" -"prefix_color_background_button_primary_active" -``` - - -* * * - -### name/cti/constant - - -Creates a constant-style name based on the full CTI of the token. If you define a prefix on the platform in your config, it will prepend with your prefix - -```js -// Matches: all -// Returns: -"COLOR_BACKGROUND_BUTTON_PRIMARY_ACTIVE" -"PREFIX_COLOR_BACKGROUND_BUTTON_PRIMARY_ACTIVE" -``` - - -* * * - -### name/ti/constant - - -Creates a constant-style name on the type and item of the token. This is useful if you want to create different static classes/files for categories like `Color.BACKGROUND_BASE`. If you define a prefix on the platform in your config, it will prepend with your prefix. - -```js -// Matches: all -// Returns: -"BACKGROUND_BUTTON_PRIMARY_ACTIVE" -"PREFIX_BACKGROUND_BUTTON_PRIMARY_ACTIVE" -``` - - -* * * - -### name/cti/pascal - - -Creates a Pascal case name. If you define a prefix on the platform in your config, it will prepend with your prefix - -```js -// Matches: all -// Returns: -"ColorBackgroundButtonPrimaryActive" -"PrefixColorBackgroundButtonPrimaryActive" -``` - - -* * * - -### color/rgb - - -Transforms the value into an RGB string - -```js -// Matches: token.attributes.category === 'color' -// Returns: -"rgb(0, 150, 136)" -``` - - -* * * - -### color/hsl - - -Transforms the value into an HSL string or HSLA if alpha is present. Better browser support than color/hsl-4 - -```js -// Matches: token.attributes.category === 'color' -// Returns: -"hsl(174, 100%, 29%)" -"hsl(174, 100%, 29%, .5)" -``` - - -* * * - -### color/hsl-4 - - -Transforms the value into an HSL string, using fourth argument if alpha is present. - -```js -// Matches: token.attributes.category === 'color' -// Returns: -"hsl(174 100% 29%)" -"hsl(174 100% 29% / .5)" -``` - - -* * * - -### color/hex - - -Transforms the value into an 6-digit hex string - -```js -// Matches: token.attributes.category === 'color' -// Returns: -"#009688" -``` - - -* * * - -### color/hex8 - - -Transforms the value into an 8-digit hex string - -```js -// Matches: token.attributes.category === 'color' -// Returns: -"#009688ff" -``` - - -* * * - -### color/hex8android - - -Transforms the value into an 8-digit hex string for Android because they put the alpha channel first - -```js -// Matches: token.attributes.category === 'color' -// Returns: -"#ff009688" -``` - - -* * * - -### color/composeColor - - -Transforms the value into a Color class for Compose - -```kotlin -// Matches: token.attributes.category === 'color' -// Returns: -Color(0xFF009688) -``` - - -* * * - -### color/UIColor - - -Transforms the value into an UIColor class for iOS - -```objectivec -// Matches: token.attributes.category === 'color' -// Returns: -[UIColor colorWithRed:0.114f green:0.114f blue:0.114f alpha:1.000f] -``` - - -* * * - -### color/UIColorSwift - - -Transforms the value into an UIColor swift class for iOS - -```swift -// Matches: token.attributes.category === 'color' -// Returns: -UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha: 0.6) -``` - - -* * * - -### color/ColorSwiftUI - - -Transforms the value into an UIColor swift class for iOS - -```swift -// Matches: token.attributes.category === 'color' -// Returns: -Color(red: 0.667, green: 0.667, blue: 0.667, opacity: 0.6) -``` - - -* * * - -### color/css - - -Transforms the value into a hex or rgb string depending on if it has transparency - -```css -// Matches: token.attributes.category === 'color' -// Returns: -#000000 -rgba(0,0,0,0.5) -``` - - -* * * - -### color/sketch - - -Transforms a color into an object with red, green, blue, and alpha -attributes that are floats from 0 - 1. This object is how Sketch stores -colors. - -```js -// Matches: token.attributes.category === 'color' -// Returns: -{ - red: 0.5, - green: 0.5, - blue: 0.5, - alpha: 1 -} -``` - - -* * * - -### size/sp - - -Transforms the value into a scale-independent pixel (sp) value for font sizes on Android. It will not scale the number. - -```js -// Matches: token.attributes.category === 'size' && token.attributes.type === 'font' -// Returns: -"10.0sp" -``` - - -* * * - -### size/dp - - -Transforms the value into a density-independent pixel (dp) value for non-font sizes on Android. It will not scale the number. - -```js -// Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' -// Returns: -"10.0dp" -``` - - -* * * - -### size/object - - -Transforms the value into a usefull object ( for React Native support ) - -```js -// Matches: token.attributes.category === 'size' -// Returns: -{ - original: "10px", - number: 10, - decimal: 0.1, // 10 divided by 100 - scale: 160, // 10 times 16 -} -``` - - -* * * - -### size/remToSp - - -Transforms the value from a REM size on web into a scale-independent pixel (sp) value for font sizes on Android. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). - -```js -// Matches: token.attributes.category === 'size' && token.attributes.type === 'font' -// Returns: -"16.0sp" -``` - - -* * * - -### size/remToDp - - -Transforms the value from a REM size on web into a density-independent pixel (dp) value for font sizes on Android. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). - -```js -// Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' -// Returns: -"16.0dp" -``` - - -* * * - -### size/px - - -Adds 'px' to the end of the number. Does not scale the number - -```js -// Matches: token.attributes.category === 'size' -// Returns: -"10px" -``` - - -* * * - -### size/rem - - -Adds 'rem' to the end of the number. Does not scale the number - -```js -// Matches: token.attributes.category === 'size' -// Returns: -"10rem" -``` - - -* * * - -### size/remToPt - - -Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'pt' to the end. - -```js -// Matches: token.attributes.category === 'size' -// Returns: -"16pt" -``` - - -* * * - -### size/compose/remToSp - - -Transforms the value from a REM size on web into a scale-independent pixel (sp) value for font sizes in Compose. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). - -```kotlin -// Matches: token.attributes.category === 'size' && token.attributes.type === 'font' -// Returns: -"16.0.sp" -``` - - -* * * - -### size/compose/remToDp - - -Transforms the value from a REM size on web into a density-independent pixel (dp) value for font sizes in Compose. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). - -```kotlin -// Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' -// Returns: -"16.0.dp" -``` - - -* * * - -### size/compose/em - - -Adds the .em Compose extension to the end of a number. Does not scale the value - -```kotlin -// Matches: token.attributes.category === 'size' && token.attributes.type === 'font' -// Returns: -"16.0em" -``` - - -* * * - -### size/swift/remToCGFloat - - -Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Swift and initializes a CGFloat - -```js -// Matches: token.attributes.category === 'size' -// Returns: "CGFloat(16.00)"" -``` - - -* * * - -### size/remToPx - - -Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'px' to the end. - -```js -// Matches: token.attributes.category === 'size' -// Returns: -"16px" -``` - - -* * * - -### size/pxToRem - - -Scales non-zero numbers to rem, and adds 'rem' to the end. If you define a "basePxFontSize" on the platform in your config, it will be used to scale the value, otherwise 16 (default web font size) will be used. - -```js -// Matches: token.attributes.category === 'size' -// Returns: -"0" -"1rem" -``` - - -* * * - -### content/icon - - -Takes a unicode point and transforms it into a form CSS can use. - -```js -// Matches: token.attributes.category === 'content' && token.attributes.type === 'icon' -// Returns: -"'\\E001'" -``` - - -* * * - -### content/quote - - -Wraps the value in a single quoted string - -```js -// Matches: token.attributes.category === 'content' -// Returns: -"'string'" -``` - - -* * * - -### content/objC/literal - - -Wraps the value in a double-quoted string and prepends an '@' to make a string literal. - -```objectivec -// Matches: token.attributes.category === 'content' -// Returns: - -**"string"**: ``` - -* * * - -### content/swift/literal - - -Wraps the value in a double-quoted string to make a string literal. - -```swift -// Matches: token.attributes.category === 'content' -// Returns: -"string" -``` - - -* * * - -### font/objC/literal - - -Wraps the value in a double-quoted string and prepends an '@' to make a string literal. - -```objectivec -// Matches: token.attributes.category === 'font' -// Returns: @"string" -``` - - -* * * - -### font/swift/literal - - -Wraps the value in a double-quoted string to make a string literal. - -```swift -// Matches: token.attributes.category === 'font' -// Returns: "string" -``` - - -* * * - -### time/seconds - - -Assumes a time in miliseconds and transforms it into a decimal - -```js -// Matches: token.attributes.category === 'time' -// Returns: -"0.5s" -``` - - -* * * - -### asset/base64 - - -Wraps the value in a double-quoted string and prepends an '@' to make a string literal. - -```js -// Matches: token.attributes.category === 'asset' -// Returns: -'IyBlZGl0b3Jjb25maWcub3JnCnJvb3QgPSB0cnVlCgpbKl0KaW5kZW50X3N0eWxlID0gc3BhY2UKaW5kZW50X3NpemUgPSAyCmVuZF9vZl9saW5lID0gbGYKY2hhcnNldCA9IHV0Zi04CnRyaW1fdHJhaWxpbmdfd2hpdGVzcGFjZSA9IHRydWUKaW5zZXJ0X2ZpbmFsX25ld2xpbmUgPSB0cnVlCgpbKi5tZF0KdHJpbV90cmFpbGluZ193aGl0ZXNwYWNlID0gZmFsc2U=' -``` - - -* * * - -### asset/path - - -Prepends the local file path - -```js -// Matches: token.attributes.category === 'asset' -// Returns: -"path/to/file/asset.png" -``` - - -* * * - -### asset/objC/literal - - -Wraps the value in a double-quoted string and prepends an '@' to make a string literal. - -```objectivec -// Matches: token.attributes.category === 'asset' -// Returns: @"string" -``` - - -* * * - -### asset/swift/literal - - -Wraps the value in a double-quoted string to make a string literal. - -```swift -// Matches: token.attributes.category === 'asset' -// Returns: "string" -``` - - -* * * - -### color/hex8flutter - - -Transforms the value into a Flutter Color object using 8-digit hex with the alpha chanel on start - ```js - // Matches: token.attributes.category === 'color' - // Returns: - Color(0xFF00FF5F) - ``` - - -* * * - -### content/flutter/literal - - -Wraps the value in a double-quoted string to make a string literal. - -```dart -// Matches: token.attributes.category === 'content' -// Returns: "string" -``` - - -* * * - -### asset/flutter/literal - - -Wraps the value in a double-quoted string to make a string literal. - -```dart -// Matches: token.attributes.category === 'asset' -// Returns: "string" -``` - - -* * * - -### font/flutter/literal - - -Wraps the value in a double-quoted string to make a string literal. - -```dart -// Matches: token.attributes.category === 'font' -// Returns: "string" -``` - - -* * * - -### size/flutter/remToDouble - - -Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Flutter - -```dart -// Matches: token.attributes.category === 'size' -// Returns: 16.00 -``` - - -* * * - diff --git a/docs/using_the_cli.md b/docs/using_the_cli.md deleted file mode 100644 index 692ec7b51..000000000 --- a/docs/using_the_cli.md +++ /dev/null @@ -1,107 +0,0 @@ -# Using the CLI - -The Style Dictionary command line interface (CLI) provides an executable system to create and act upon style dictionaries. - - -# Installation - -To use the CLI, you can install it globally via npm: - -```bash -$ npm install -g style-dictionary -``` - -Most of the time you will want to install Style Dictionary as a dev dependency in your NPM package. The reason to have it as a dev dependency rather than a regular dependency is that Style Dictionary is a build tool rather than a runtime tool because it is used to *generate* files rather than used directly in an application. - -```bash -$ npm install --save-dev style-dictionary -``` - -In your `package.json` file you can add an NPM script that runs Style Dictionary: - -```json - "scripts": { - "build": "style-dictionary build" - } -``` - - -# CLI Quick Start - -This will create a new folder called 'quick-start' and populate it with a Style Dictionary configuration and tokens. - -```bash -$ mkdir quick-start && cd quick-start -$ style-dictionary init basic -``` - -You can then modify the design tokens in the tokens directory and run the build command below. See the changes in the output generated in the build folder. - -```bash -$ style-dictionary build -``` - -# Commands - -The CLI provides three basic commands: - -* [build](using_the_cli.md?id=build) Builds a style dictionary package from the current directory. -* [clean](using_the_cli.md?id=clean) Removes files specified in the config of the style dictionary package of the current directory. -* [init](using_the_cli.md?id=init) Generates a starter style dictionary - -These commands can be run using: - -```bash -$ style-dictionary [command] [options] -``` - -## build - -Builds a style dictionary package from the current directory. Usage: - -```bash -$ style-dictionary build [options] -``` - -Options: - -| Name | Usage | Description | -| :--- | :--- | :--- | -| Configuration Path | -c , --config | Set the path to the configuration file. Defaults to './config.json'. | -| Platform | -p , --platform | Only build a specific platform. If not supplied, builds all platform found in the configuration file. | - -## clean - -Removes files and folders generated by a previously run 'build' command. Usage: - -```bash -$ style-dictionary clean [options] -``` - -Options: - -| Name | Usage | Description | -| :--- | :--- | :--- | -| Configuration Path | -c , --config | Set the path to the configuration file. Defaults to './config.json'. | -| Platform | -p , --platform | Only clean a specific platform. If not supplied, cleans all platform found in the configuration file. | - -## init - -Generates a starter style dictionary, based on the supplied example type. Usage: - -```bash -$ style-dictionary init -``` - -Where example-type is one of: -* `basic` -* `complete` - - -## version - -To see what version of Style Dictionary you have, run this command: - -```bash -$ style-dictionary --version -``` diff --git a/docs/using_the_npm_module.md b/docs/using_the_npm_module.md deleted file mode 100644 index de69fec8a..000000000 --- a/docs/using_the_npm_module.md +++ /dev/null @@ -1,109 +0,0 @@ -# Using the NPM Module - -The Style Dictionary npm module exposes an [API](api.md) to interact with style dictionaries. - -## Installation - -To use the npm module, install it like a normal npm dependency. You are most likely going to want to save it as a dev dependency (The -D option) because it's a build tool: - -```bash -$ npm install -D style-dictionary -``` - -## NPM Module Quick Start - -To use the style dictionary build system in node, there are generally three steps: - -1. Require/import the StyleDictionary module -1. Extend the module with a configuration, creating the fully defined dictionary (importing all properties and intended outputs) -1. Call one or more build calls for various platforms - -To use the NPM module you will need to update your NPM script that runs Style Dictionary from using the CLI command to running Node on the file you are using. - -```json5 -// package.json - "scripts": { - "build": "style-dictionary build" - } -``` - -becomes - -```json5 -// package.json - "scripts": { - "build": "node build.js" - } -``` - -Update "build.js" to the name of the file you created. - -Using a JSON [configuration](config.md) file, that looks like this: - -```javascript -const StyleDictionary = require('style-dictionary').extend('config.json'); - -StyleDictionary.buildAllPlatforms(); -``` - -Alternatively, you can pass in a [configuration](config.md) object to the extend call. The `buildAllPlatforms` call is the same. - -```javascript -const StyleDictionary = require('style-dictionary').extend({ - source: ['properties/**/*.json'], - platforms: { - scss: { - transformGroup: 'scss', - buildPath: 'build/', - files: [{ - destination: 'variables.scss', - format: 'scss/variables' - }] - } - // ... - } -}); - -StyleDictionary.buildAllPlatforms(); -``` - -You can `extend` Style Dictionary multiple times and call `buildAllPlatforms` as many times as you need. This can be useful if you are creating nested (parent-child) themes with Style Dictionary. - -```javascript -const StyleDictionary = require('style-dictionary'); - -const styleDictionary = StyleDictionary.extend({ - // add custom formats/transforms -}); - -styleDictionary.extend({ - // ... -}).buildAllPlatforms(); - -styleDictionary.extend({ - // ... -}).buildAllPlatforms(); -``` - -Another way to do this is to loop over an array and apply different configurations to Style Dictionary: - -```javascript -const StyleDictionary = require('style-dictionary'); - -const brands = [`brand-1`, `brand-2`, `brand-3`]; -brands.forEach(brand => { - StyleDictionary.extend({ - include: [`tokens/default/**/*.json`], - source: [`tokens/${brand}/**/*.json`], - // ... - }).buildAllPlatforms(); -}); -``` - -The [multi-brand-multi-platform example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) uses this method. - ----- - -## NPM Module API - -The [complete npm module API is documented here](api.md). diff --git a/docs/version_3.md b/docs/version_3.md deleted file mode 100644 index 2a00e093d..000000000 --- a/docs/version_3.md +++ /dev/null @@ -1,418 +0,0 @@ -# Version 3.0! - -Version 3.0 is now publicly released! We have been working hard the past few months on a number of features and improvements we wanted to combine into a major release. Though we intend that 3.0 to be backwards compatible, we thought it was a good idea to move to a new major version because we are changing a core part of how Style Dictionary works. - -If you are starting a new project, you can install Style Dictionary and it will give you the latest version: - -`npm install --save-dev style-dictionary` - -If you have an existing project, you can upgrade to 3.0 by updating the version in your `package.json` file to `"style-dictionary": "^3.0.0"` and then run `npm install` or you can use the `latest` tag to update both your `package.json` and `package-lock.json` files: - -`npm install --save-dev style-dictionary@latest` - -[If you find any bugs or issues, please file a ticket](https://github.com/amzn/style-dictionary/issues/new) so we can get things fixed. We have tested and reviewed 3.0 extensively, but there may be things we missed. Thanks! - - -## What's new in 3.0: - -* [Style Properties → Design Tokens](#style-properties-→-design-tokens) -* [Transitive transforms](#transitive-transforms) -* [Output references](#output-references) -* [Custom parser support](#custom-parser-support) -* [Adding filePath and isSource entries on tokens](#adding-filepath-and-issource-entries-on-tokens) -* [Format helpers](#format-helpers) -* [Updated format method arguments](#updated-format-method-arguments) -* [Custom file headers](#custom-file-headers) -* [Typescript support](#typescript-support) -* [More built-ins](#more-built-ins) -* [Bug fixes](#bug-fixes) -* [Other features](#other-features) -* [Better testing](#better-testing) -* [Dropping support for older versions of node](#dropping-support-for-older-versions-of-node) - -### Style Properties → Design Tokens - -Style Dictionary is moving to the term "design tokens", both in documentation and in code. This has become the industry standard term for a while and it is time we respect that. Until now, Style Dictionary had called these "style properties" or just "properties", with some parts of the documentation also mentioning "design tokens". We want to be consistent with the direction of the community as well as in our documentation and code. We use the terms `properties` and `allProperties` in different APIs in Style Dictionary. To be consistent in documentation as well as code, we will be moving to using `tokens` and `allTokens`. - -Don't worry! This change is backwards-compatible; you will still be able to use `properties` and `allProperties` wherever you currently do in your code. If you want, you can update those to tokens and allTokens and everything will work as expected. Moving forward, all examples and documentation will use the term "design tokens" and "tokens" rather than "style properties" and "properties". We do recommend using `tokens` and `allTokens` in new code from here on out! - -### Transitive transforms - -This is the big one that required a big re-architecture of how the Style Dictionary build process works. - -Up until now the build process would merge all token files, then iterate through the merged object and transform tokens it found, but only do value transforms on tokens that did not reference another token. The original intent here was that a value of any reference should be the same for all references of it, so we only need to do a value transform once. Then after all tokens are transformed, Style Dictionary would resolve all aliases/references. - -However, we heard from the community there were a number of reasons why someone might want to transform the value of an aliased token. - -* https://github.com/amzn/style-dictionary/issues/451 -* https://github.com/amzn/style-dictionary/issues/452 -* https://github.com/amzn/style-dictionary/issues/208 - -The new build process is similar, except that it recursively transforms and resolves aliases, only deferring a transform to the next cycle if the token has an unresolved alias. Each pass might reveal tokens that are ready to be transformed in the next pass. Take this example: - -```json -{ - "color": { - "black": { "value": "#000000" }, - "font": { - "primary": { "value": "{color.black.value}" }, - "input": { "value": "{color.font.primary.value}" } - } - } -} -``` - -The first pass will transform the `color.black` token because it doesn't have a reference. It will defer the transforms of `color.font.primary` and `color.font.input` because they do have references. Then it will resolve references to `color.black.value` because it has been transformed. - -The second pass will transform `color.font.primary` because it no longer has a reference. It will then resolve the reference to `color.font.primary.value` because it has been transformed. - -The final pass will transform `color.font.input` because it no longer has a reference. Now the build is complete because there are no more deferred transforms left. - -Use cases this change opens up: - -* Having variable references in outputs -* Combining values like using HSL for colors -* Modifying aliases like making a color lighter or darker - -Example: https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms - -Thanks [@mfal](https://github.com/mfal)! - -### Output references - -https://github.com/amzn/style-dictionary/pull/504 - -This is another big one. This has been one of the first issues we made back in 2017, [issue 17](https://github.com/amzn/style-dictionary/issues/17)! This adds support for outputting references in exported files. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens: - -```json5 -// tokens.json -{ - "color": { - "red": { "value": "#ff0000" }, - "danger": { "value": "{color.red.value}" }, - "error": { "value": "{color.danger.value}" } - } -} -``` - -With this configuration: - -```json5 -// config.json -{ - "source": ["tokens.json"] - "platforms": { - "css": { - "transformGroup": "css", - "files": [{ - "destination": "variables.css", - "format": "css/variables", - "options": { - // Look here 👇 - "outputReferences": true - } - }] - } - } -} -``` - -This would be the output: - -```css -:root { - --color-red: #ff0000; - --color-danger: var(--color-red); - --color-error: var(--color-danger); -} -``` - -The css variables file now keeps the references you have in your Style Dictionary! This is useful for outputting themeable and dynamic code. - -Without `outputReferences: true` Style Dictionary would resolve all references and the output would be: - -```css -:root { - --color-red: #ff0000; - --color-danger: #ff0000; - --color-error: #ff0000; -} -``` - -Not all formats use the `outputReferences` option because that file format might not support it (like JSON for example). The current list of formats that handle `outputReferences`: - -* css/variables -* scss/variables -* less/variables -* compose/object -* android/resources -* ios-swift/class.swift -* ios-swift/enum.swift -* flutter/class.dart - -If you have custom formats you can make use of this feature too! The `dictionary` object that is passed as an argument to the formatter function has 2 new methods on it: `usesReference()` and `getReferences()` which you can use to get the reference name. Here is an example of that: - -```javascript -StyleDictionary.registerFormat({ - name: `myCustomFormat`, - formatter: function({ dictionary }) { - return dictionary.allTokens.map(token => { - let value = JSON.stringify(token.value); - // the `dictionary` object now has `usesReference()` and - // `getReferences()` methods. `usesReference()` will return true if - // the value has a reference in it. `getReferences()` will return - // an array of references to the whole tokens so that you can access - // their names or any other attributes. - if (dictionary.usesReference(token.original.value)) { - const refs = dictionary.getReferences(token.original.value); - refs.forEach(ref => { - value = value.replace(ref.value, function() { - return `${ref.name}`; - }); - }); - } - return `export const ${token.name} = ${value};` - }).join(`\n`) - } -}) -``` - -Example: https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs - -### Custom parser support - -https://github.com/amzn/style-dictionary/pull/429 - -We are pretty excited about this. Until now you could only define your design tokens in either JSON, JSON5, or plain Node modules. The addition of custom parser support allows you to define your tokens in any language you like! The most obvious use-case is to use YAML which has a cleaner and less verbose syntax than JSON. Now, the sky is the limit. Your source of truth can be in any file format you like as long as you can parse it into an object that Style Dictionary can understand. You register a custom parser the same way as you register a custom transform or format. A parser consists of a pattern to match against files, similar to the test attribute in a loader in Webpack, and a parse function which gets the file path and its contents and is expected to return an object. - -* Example: https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser -* YAML example: https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens - - -### Adding filePath and isSource entries on tokens - -https://github.com/amzn/style-dictionary/pull/356 - -Style Dictionary adds some metadata on each token before any transforms take place in order to give more context for transforming and formatting tokens. For example, this design token: - -```json5 -{ - "color": { - "red": { "value": "#ff0000" } - } -} -``` - -Turns into this: - -```json5 -{ - "color": { - "red": { - "value": "#ff0000", - "name": "red", // adds a default 'name', which is the object key - "path": ["color","red"], // object path - "original": { - "value": "#ff0000" - } // copies the original object so you always have a clean copy - } - } -} -``` - -We are adding 2 new pieces of metadata to each token: - -* **filePath:** A string representing the absolute path of the file that defines the token. This will help with debugging and if you want to output files based on the source files. -* **isSource:** A boolean representing if this file was defined as ‘source’ in the configuration as opposed to ‘include’ (or directly setting the ‘properties’ object). This can also help filtering tokens from output files you don't want to include. - -Thanks [@7studio](https://github.com/7studio)! - -### Format helpers - -Style Dictionary comes with built-in formats to generate basic files like CSS, Sass, and Less variables. We know that we can't build formats to fit everyone's exact needs, so you can write your own formats to output exactly what you want. However, one common ask was to use 90% of a built-in format, but tweak small parts of it. Before 3.0, the only way to do that would be to copy and paste the format source code from Style Dictionary into your own custom format and then make your tweaks. - -In 3.0, we have added format helpers. Format helpers are functions that the built-in formats use for things like formatting each token definition line, sorting the tokens, and displaying a file header comment. These functions are now part of the public API, which you can access with StyleDictionary.formatHelpers. Format helpers should make it simple to build custom formats. - -```javascript -const StyleDictionary = require('style-dictionary'); - -const { formattedVariables } = StyleDictionary.formatHelpers; - -module.exports = { - format: { - myFormat: ({ dictionary, options, file }) => { - const { outputReferences } = options; - return formattedVariables({ - dictionary, - outputReferences, - formatting: { - prefix: '$', - separator: ':', - suffix: ';' - } - }); - } - } -} -``` - -Example: https://github.com/amzn/style-dictionary/tree/main/examples/advanced/format-helpers - -### Updated format method arguments - -https://github.com/amzn/style-dictionary/pull/533 - -We wanted to make the format method signature easier to work with by not relying on positional arguments and instead used named arguments in the form of an object that can be destructured. But we also didn't want to break anyone's custom formats so we did it in a backwards compatible way. We did this by overloading the first argument sent to the formatter method, which is the dictionary object. - -Old way: - -```javascript -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: (dictionary, platform, file) { - // ... - } -}); -``` - -New way: - -```javascript -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: ({dictionary, platform, file, options}) { - // ... - } -}); -``` - -The old way will continue to work, but we recommend changing to the new way at some point. For a full list of the information sent to the formatter function, see: https://github.com/amzn/style-dictionary/blob/3.0/docs/formats.md#creating-formats - -You might also notice a new part of the information sent to the formatter method: `options`. This object will a merged version of an `options` object at the platform-level configuration and file-level configuration where the file takes precedence. This allows for a cascading of configuration from the platform to the file and so you don't have to repeat the same options for multiple files like the `showFileHeader` option. - -```json5 -{ - "source": ["tokens/**/*.json"], - "platforms": { - "css": { - "options": { - "showFileHeader": false, - // ouputReferences is a new option added in 3.0! - "outputReferences": true - }, - "transformGroup": "css", - "files": [{ - // this file will inherit the platform options above - "destination": "variables.css", - "format": "css/variables" - },{ - // this file overrides the platform options - "destination": "variablesWithoutReferences.css", - "format": "css/variables", - "options": { - "showFileHeader": true, - "outputReferences": false - } - }] - } - } -} -``` - -Previously, there wasn't much convention around adding extra configuration at the platform and file-level for transforms, formats, and actions. We want to start correcting that a bit by using an `options` object at the file and platform level. - -### Custom file headers - -When we started Style Dictionary, our intention was that the code it generates would not be checked into version control. To make that very apparent we added a code comment at the top of every built-in format that says it is a generated file with a timestamp of when it was generated. Over the years we have seen many different use-cases and patterns emerge from using Style Dictionary. One of those is actually checking in generated files to version control and using a pull request to review and verify the results. Having a time-stamped comment in generated files now becomes a bit of an obstacle. In the principle of extensibility and customization, you can now define your own file header comments for output files! This allows you to remove the timestamp if you want, write a custom message, use the version number of the package, or even use a hash of the source so that it only changes when the source changes. - -You can use the custom file headers on any built-in format, or even use them in a custom format with the formatHelper.fileHeader function. - -```javascript -module.exports = { - //... - fileHeader: { - myFileHeader: (defaultMessage) => { - return [ - ...defaultMessage, - 'hello, world!' - ] - } - }, - - platforms: { - css: { - transformGroup: `css`, - files: [{ - destination: `variables.css`, - format: `css/variables`, - fileHeader: `myFileHeader` - }] - } - } -} -``` - -Example: https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header - -### Typescript support - -https://github.com/amzn/style-dictionary/pull/410 - -Style Dictionary has Typescript types now! We have added support both for generating typescript files with the typescript/es6-declarations and typescript/module-declarations formats, as well as type definitions for using the Style Dictionary module in a Typescript environment. The source code of Style Dictionary remains in plain Javascript for now, but many people have been wanting to use Style Dictionary in Typescript so as an interim solution we added just the type definitions. As an added bonus, the type definitions also help Javascript Intellisense in VSCode even if you aren't using Typescript in your project! - -Thanks [@AndrewLeedham](https://github.com/AndrewLeedham)! - -### More built-ins - -We added support for: Jetpack Compose, React Native, and Stylus with built-in transforms, transform groups, and formats. Style Dictionary is built to be customized and extended, so any language or platform can be supported with customization. We do want to offer a core set of generic transforms and formats to get you started so that you don't have to write custom code for everything. If you think we are missing something, please let us know! Here are the formats, transforms, and transformGroups we added in 3.0: - -#### Formats - -* [`javascript/module-flat`](https://github.com/amzn/style-dictionary/pull/457), thanks [@noslouch](https://github.com/noslouch)! -* [`android/resources`](https://github.com/amzn/style-dictionary/pull/509) -* [`stylus/variables`](https://github.com/amzn/style-dictionary/pull/527), thanks [@klausbayrhammer](https://github.com/klausbayrhammer) -* [`compose/object`](https://github.com/amzn/style-dictionary/pull/599), thanks [@bherbst](https://github.com/bherbst) -* [`typescript/es6-declarations`](https://github.com/amzn/style-dictionary/pull/557), thanks [@Tiamanti](https://github.com/Tiamanti) -* [`typescript/module-declarations`](https://github.com/amzn/style-dictionary/pull/557), thanks [@Tiamanti](https://github.com/Tiamanti) - -#### Transforms - -* [`size/pxToRem`](https://github.com/amzn/style-dictionary/pull/491), thanks [@jbarreiros](https://github.com/jbarreiros)! -* [`size/object`](https://github.com/amzn/style-dictionary/pull/512), thanks [@levi-pires](https://github.com/levi-pires) -* [`size/compose/remToSP`](https://github.com/amzn/style-dictionary/pull/599), thanks [@bherbst](https://github.com/bherbst) -* [`size/compose/remToDP`](https://github.com/amzn/style-dictionary/pull/599), thanks [@bherbst](https://github.com/bherbst) -* [`size/compose/em`](https://github.com/amzn/style-dictionary/pull/599), thanks [@bherbst](https://github.com/bherbst) -* [`color/composeColor`](https://github.com/amzn/style-dictionary/pull/599), thanks [@bherbst](https://github.com/bherbst) -* [Made base pixel size configurable](https://github.com/amzn/style-dictionary/pull/505), thanks [@jbarreiros](https://github.com/jbarreiros)! - -#### Transform Groups - -* [`react-native`](https://github.com/amzn/style-dictionary/pull/512), thanks [@levi-pires](https://github.com/levi-pires) -* [`compose`](https://github.com/amzn/style-dictionary/pull/599), thanks [@bherbst](https://github.com/bherbst) - -### Bug fixes - -* [Trailing slash check on windows](https://github.com/amzn/style-dictionary/pull/419), thanks [@JDansercoer](https://github.com/JDansercoer)! -* [Clean config path in CLI](https://github.com/amzn/style-dictionary/pull/454), thanks [@tehkaiyu](https://github.com/tehkaiyu)! -* [Fixing max call stack bug on json/nested format](https://github.com/amzn/style-dictionary/pull/465) -* [Fix transform options type](https://github.com/amzn/style-dictionary/pull/502), thanks [@amalik2](https://github.com/amalik2)! - -### Other features - -* [Don't generate files if there are no tokens](https://github.com/amzn/style-dictionary/pull/494) thanks [@davidyeiser](https://github.com/davidyeiser) - -### Better testing - -To have higher confidence in the end-to-end experience of Style Dictionary we have added integration tests that run Style Dictionary as real users would. Integration tests are in **__integration__** and use snapshot testing to ensure the output of Style Dictionary from input, transforms, and formats remains the same and valid output. - -We have also added more unit tests as well for some features we have added and bugs we have found. We added: - -* 28 test suites -* 174 tests -* 69 snapshots - -### Dropping support for older versions of node - -https://github.com/amzn/style-dictionary/pull/441 - -To be honest, we should have done this way sooner. Those versions of Node are no longer even in long-term support or maintenance. Hopefully this change should not affect anyone as you should all be on more recent versions of Node anyways. diff --git a/examples/README.md b/examples/README.md index 79eeee952..5a02820ba 100644 --- a/examples/README.md +++ b/examples/README.md @@ -13,42 +13,43 @@ $ style-dictionary init [example] Where `[example]` is one of: `basic`, `complete`. ## Basic + [View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/basic) This example code is bare-bones to show you what this framework can do. Use this if you want to play around with what the Style Dictionary can do. - ## Complete + [View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/complete) This is a more complete package and should have everything you need to get started. This package can be consumed as a Cocoapod on iOS, as a node module for web, and as a local library for Android. ## Advanced + [View the folder](https://github.com/amzn/style-dictionary/tree/main/examples/advanced) If you want to look at more advanced examples of possible applications and customizations of Style Dictionary, the [`examples/advanced`](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/) folder on GitHub contains these extra folders: -* [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. -* [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the tokens. -* [**component-cti**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. -* [**create-react-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-app) shows how to integrate Style Dictionary into a React application. -* [**create-react-native-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-native-app) shows how to integrate Style Dictionary into a React Native application. -* [**custom-file-header**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) shows how to define custom file headers and use them in output files. -* [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. -* [**custom-parser**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) shows how to use custom parsers for token files. -* [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. -* [**flutter**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/flutter) shows how to integrate with Flutter applications. -* [**matching-build-files**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/matching-build-files) shows how to output files 1-to-1 with source files. -* [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with token values depending on brand and platforms. -* [**node-modules-as-config-and-properties**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) shows how to use Javascript rather than JSON for configuration and token files. -* [**npm-module**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. -* [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. -* [**s3**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. -* [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. -* [**transitive-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms) shows how to use transitive transforms to transform references -* [**variables-in-outputs**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs) shows you how to use the `outputReferences` option to generate files variable references in them. -* [**yaml-tokens**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) shows how to use a custom parser to define your source files in YAML rather than JSON. - +- [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. +- [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the tokens. +- [**component-cti**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. +- [**create-react-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-app) shows how to integrate Style Dictionary into a React application. +- [**create-react-native-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-native-app) shows how to integrate Style Dictionary into a React Native application. +- [**custom-file-header**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) shows how to define custom file headers and use them in output files. +- [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. +- [**custom-parser**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) shows how to use custom parsers for token files. +- [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. +- [**flutter**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/flutter) shows how to integrate with Flutter applications. +- [**matching-build-files**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/matching-build-files) shows how to output files 1-to-1 with source files. +- [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with token values depending on brand and platforms. +- [**node-modules-as-config-and-properties**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) shows how to use Javascript rather than JSON for configuration and token files. +- [**npm-module**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. +- [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. +- [**s3**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. +- [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. +- [**transitive-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms) shows how to use transitive transforms to transform references +- [**variables-in-outputs**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs) shows you how to use the `outputReferences` option to generate files variable references in them. +- [**yaml-tokens**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) shows how to use a custom parser to define your source files in YAML rather than JSON. --- diff --git a/examples/advanced/assets-base64-embed/README.md b/examples/advanced/assets-base64-embed/README.md index ba6c63d07..7f1bea780 100644 --- a/examples/advanced/assets-base64-embed/README.md +++ b/examples/advanced/assets-base64-embed/README.md @@ -6,7 +6,7 @@ This means that you can centralize all your "core" design values in one single p #### Running the example -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). +First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use _yarn_, update the commands accordingly). At this point, run `npm run build`. This command will generate the files in the `build` folder. @@ -25,11 +25,13 @@ will be rendered as: ``` ``` + and in **Sass** this code: ``` background-image: url('data:image/png;base64,$asset-image-logo'); ``` + will be rendered as: ``` @@ -38,11 +40,11 @@ background-image: url('data:image/png;base64,PHN2ZyB4bWxucz0iaHR0...'); #### What to look at -Open the `config.json` file and see how all the "assets/embed/*" platform blocks are configured: +Open the `config.json` file and see how all the "assets/embed/\*" platform blocks are configured: ``` "assets/embed/json": { - "transforms": ["attribute/cti", "name/cti/kebab", "asset/base64"], + "transforms": ["attribute/cti", "name/kebab", "asset/base64"], "buildPath": "build/json/", "files": [{ "destination": "assets_icons.json", @@ -54,7 +56,7 @@ Open the `config.json` file and see how all the "assets/embed/*" platform blocks ... ``` -Here there are **three specific transforms**: *attribute/cti* to assign the Category/Type/Item attributes to the tokens, *name/cti/kebab* to assign them the correct name, and finally *asset/base64* to take the path declared in the "value" of the tokens, convert the file at that path in base64 format, and assign the output of the base64 conversion to the "value" of the token. +Here there are **three specific transforms**: _attribute/cti_ to assign the Category/Type/Item attributes to the tokens, _name/kebab_ to assign them the correct name, and finally _asset/base64_ to take the path declared in the "value" of the tokens, convert the file at that path in base64 format, and assign the output of the base64 conversion to the "value" of the token. If you take for example the file `assets/icons.json` you will see this declaration: @@ -64,6 +66,7 @@ If you take for example the file `assets/icons.json` you will see this declarati "alert-circle": { "value": "assets/icons/alert-circle.svg" } ``` + where the value of the `alert-circle` token is a path that points to the `alert-circle.svg` file in the `assets/icons/` folder. Now, `build` the dictionary and open the generated file `build/scss/assets_icons.scss`, and you will see this result: diff --git a/examples/advanced/assets-base64-embed/config.json b/examples/advanced/assets-base64-embed/config.json index 0bc364192..23266138f 100644 --- a/examples/advanced/assets-base64-embed/config.json +++ b/examples/advanced/assets-base64-embed/config.json @@ -4,95 +4,104 @@ "scss": { "transformGroup": "scss", "buildPath": "build/scss/", - "files": [{ - "destination": "colors.scss", - "format": "scss/variables", - "filter": { - "attributes": { - "category": "color" + "files": [ + { + "destination": "colors.scss", + "format": "scss/variables", + "filter": { + "type": "color" } - } - },{ - "destination": "sizes.scss", - "format": "scss/variables", - "filter": { - "attributes": { - "category": "size" + }, + { + "destination": "sizes.scss", + "format": "scss/variables", + "filter": { + "type": "fontSize" } } - }] + ] }, "json": { "transformGroup": "web", "buildPath": "build/json/", - "files": [{ - "destination": "variables.json", - "format": "json/flat" - }] + "files": [ + { + "destination": "variables.json", + "format": "json/flat" + } + ] }, "assets/embed/scss": { - "transforms": ["attribute/cti", "name/cti/kebab", "asset/base64"], + "transforms": ["attribute/cti", "name/kebab", "asset/base64"], "buildPath": "build/scss/", - "files": [{ - "destination": "assets_icons.scss", - "format": "scss/variables", - "filter": { - "attributes": { - "category": "asset", - "type": "icon" + "files": [ + { + "destination": "assets_icons.scss", + "format": "scss/variables", + "filter": { + "attributes": { + "category": "asset", + "type": "icon" + } } - } - },{ - "destination": "assets_images.scss", - "format": "scss/variables", - "filter": { - "attributes": { - "category": "asset", - "type": "image" + }, + { + "destination": "assets_images.scss", + "format": "scss/variables", + "filter": { + "attributes": { + "category": "asset", + "type": "image" + } } - } - },{ - "destination": "assets_fonts.scss", - "format": "scss/variables", - "filter": { - "attributes": { - "category": "asset", - "type": "font" + }, + { + "destination": "assets_fonts.scss", + "format": "scss/variables", + "filter": { + "attributes": { + "category": "asset", + "type": "font" + } } } - }] + ] }, "assets/embed/json": { - "transforms": ["attribute/cti", "name/cti/kebab", "asset/base64"], + "transforms": ["attribute/cti", "name/kebab", "asset/base64"], "buildPath": "build/json/", - "files": [{ - "destination": "assets_icons.json", - "format": "json/flat", - "filter": { - "attributes": { - "category": "asset", - "type": "icon" + "files": [ + { + "destination": "assets_icons.json", + "format": "json/flat", + "filter": { + "attributes": { + "category": "asset", + "type": "icon" + } } - } - },{ - "destination": "assets_images.json", - "format": "json/flat", - "filter": { - "attributes": { - "category": "asset", - "type": "image" + }, + { + "destination": "assets_images.json", + "format": "json/flat", + "filter": { + "attributes": { + "category": "asset", + "type": "image" + } } - } - },{ - "destination": "assets_fonts.json", - "format": "json/flat", - "filter": { - "attributes": { - "category": "asset", - "type": "font" + }, + { + "destination": "assets_fonts.json", + "format": "json/flat", + "filter": { + "attributes": { + "category": "asset", + "type": "font" + } } } - }] + ] } } } diff --git a/examples/advanced/assets-base64-embed/package.json b/examples/advanced/assets-base64-embed/package.json index 89e266384..70f51a59c 100644 --- a/examples/advanced/assets-base64-embed/package.json +++ b/examples/advanced/assets-base64-embed/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "description": "", "main": "build.js", + "type": "module", "scripts": { "build": "node_modules/.bin/style-dictionary build", "clean": "rm -rf build", @@ -11,6 +12,6 @@ "author": "", "license": "Apache-2.0", "devDependencies": { - "style-dictionary": "3.8.0" + "style-dictionary": "4.0.0-prerelease.30" } -} \ No newline at end of file +} diff --git a/examples/advanced/assets-base64-embed/tokens/assets/fonts.json b/examples/advanced/assets-base64-embed/tokens/assets/fonts.json index d992a28ef..f02db9e56 100644 --- a/examples/advanced/assets-base64-embed/tokens/assets/fonts.json +++ b/examples/advanced/assets-base64-embed/tokens/assets/fonts.json @@ -2,16 +2,16 @@ "asset": { "font": { "materialicons": { - "ttf" : { "value": "assets/fonts/MaterialIcons-Regular.ttf" }, - "eot" : { "value": "assets/fonts/MaterialIcons-Regular.eot" }, - "woff" : { "value": "assets/fonts/MaterialIcons-Regular.woff" }, - "woff2": { "value": "assets/fonts/MaterialIcons-Regular.woff2" } + "ttf": { "value": "assets/fonts/MaterialIcons-Regular.ttf", "type": "asset" }, + "eot": { "value": "assets/fonts/MaterialIcons-Regular.eot", "type": "asset" }, + "woff": { "value": "assets/fonts/MaterialIcons-Regular.woff", "type": "asset" }, + "woff2": { "value": "assets/fonts/MaterialIcons-Regular.woff2", "type": "asset" } }, "opensans": { - "ttf" : { "value": "assets/fonts/OpenSans-Regular.ttf" } + "ttf": { "value": "assets/fonts/OpenSans-Regular.ttf", "type": "asset" } }, "roboto": { - "ttf" : { "value": "assets/fonts/Roboto-Regular.ttf" } + "ttf": { "value": "assets/fonts/Roboto-Regular.ttf", "type": "asset" } } } } diff --git a/examples/advanced/assets-base64-embed/tokens/assets/icons.json b/examples/advanced/assets-base64-embed/tokens/assets/icons.json index 83ca09fb1..1c0421061 100644 --- a/examples/advanced/assets-base64-embed/tokens/assets/icons.json +++ b/examples/advanced/assets-base64-embed/tokens/assets/icons.json @@ -1,34 +1,34 @@ { "asset": { "icon": { - "alert-circle": { "value": "assets/icons/alert-circle.svg" }, - "alert-octagon": { "value": "assets/icons/alert-octagon.svg" }, - "alert-triangle": { "value": "assets/icons/alert-triangle.svg" }, - "archive": { "value": "assets/icons/archive.svg" }, - "book-open": { "value": "assets/icons/book-open.svg" }, - "book": { "value": "assets/icons/book.svg" }, - "bookmark": { "value": "assets/icons/bookmark.svg" }, - "briefcase": { "value": "assets/icons/briefcase.svg" }, - "calendar": { "value": "assets/icons/calendar.svg" }, - "camera": { "value": "assets/icons/camera.svg" }, - "check-circle": { "value": "assets/icons/check-circle.svg" }, - "check-square": { "value": "assets/icons/check-square.svg" }, - "database": { "value": "assets/icons/database.svg" }, - "delete": { "value": "assets/icons/delete.svg" }, - "dollar-sign": { "value": "assets/icons/dollar-sign.svg" }, - "download-cloud": { "value": "assets/icons/download-cloud.svg" }, - "edit-1": { "value": "assets/icons/edit-1.svg" }, - "edit-2": { "value": "assets/icons/edit-2.svg" }, - "edit-3": { "value": "assets/icons/edit-3.svg" }, - "external-link": { "value": "assets/icons/external-link.svg" }, - "file-text": { "value": "assets/icons/file-text.svg" }, - "file": { "value": "assets/icons/file.svg" }, - "film": { "value": "assets/icons/film.svg" }, - "folder": { "value": "assets/icons/folder.svg" }, - "gift": { "value": "assets/icons/gift.svg" }, - "github": { "value": "assets/icons/github.svg" }, - "globe": { "value": "assets/icons/globe.svg" }, - "grid": { "value": "assets/icons/grid.svg" } + "alert-circle": { "value": "assets/icons/alert-circle.svg", "type": "asset" }, + "alert-octagon": { "value": "assets/icons/alert-octagon.svg", "type": "asset" }, + "alert-triangle": { "value": "assets/icons/alert-triangle.svg", "type": "asset" }, + "archive": { "value": "assets/icons/archive.svg", "type": "asset" }, + "book-open": { "value": "assets/icons/book-open.svg", "type": "asset" }, + "book": { "value": "assets/icons/book.svg", "type": "asset" }, + "bookmark": { "value": "assets/icons/bookmark.svg", "type": "asset" }, + "briefcase": { "value": "assets/icons/briefcase.svg", "type": "asset" }, + "calendar": { "value": "assets/icons/calendar.svg", "type": "asset" }, + "camera": { "value": "assets/icons/camera.svg", "type": "asset" }, + "check-circle": { "value": "assets/icons/check-circle.svg", "type": "asset" }, + "check-square": { "value": "assets/icons/check-square.svg", "type": "asset" }, + "database": { "value": "assets/icons/database.svg", "type": "asset" }, + "delete": { "value": "assets/icons/delete.svg", "type": "asset" }, + "dollar-sign": { "value": "assets/icons/dollar-sign.svg", "type": "asset" }, + "download-cloud": { "value": "assets/icons/download-cloud.svg", "type": "asset" }, + "edit-1": { "value": "assets/icons/edit-1.svg", "type": "asset" }, + "edit-2": { "value": "assets/icons/edit-2.svg", "type": "asset" }, + "edit-3": { "value": "assets/icons/edit-3.svg", "type": "asset" }, + "external-link": { "value": "assets/icons/external-link.svg", "type": "asset" }, + "file-text": { "value": "assets/icons/file-text.svg", "type": "asset" }, + "file": { "value": "assets/icons/file.svg", "type": "asset" }, + "film": { "value": "assets/icons/film.svg", "type": "asset" }, + "folder": { "value": "assets/icons/folder.svg", "type": "asset" }, + "gift": { "value": "assets/icons/gift.svg", "type": "asset" }, + "github": { "value": "assets/icons/github.svg", "type": "asset" }, + "globe": { "value": "assets/icons/globe.svg", "type": "asset" }, + "grid": { "value": "assets/icons/grid.svg", "type": "asset" } } } } diff --git a/examples/advanced/assets-base64-embed/tokens/assets/images.json b/examples/advanced/assets-base64-embed/tokens/assets/images.json index 61b273e18..649e0f6f2 100644 --- a/examples/advanced/assets-base64-embed/tokens/assets/images.json +++ b/examples/advanced/assets-base64-embed/tokens/assets/images.json @@ -1,7 +1,7 @@ { "asset": { "image": { - "logo": { "value": "assets/images/logo.png" } + "logo": { "value": "assets/images/logo.png", "type": "asset" } } } } diff --git a/examples/advanced/assets-base64-embed/tokens/color/base.json b/examples/advanced/assets-base64-embed/tokens/color/base.json index 02a99d700..31642c256 100644 --- a/examples/advanced/assets-base64-embed/tokens/color/base.json +++ b/examples/advanced/assets-base64-embed/tokens/color/base.json @@ -2,12 +2,12 @@ "color": { "base": { "gray": { - "light" : { "value": "#CCCCCC" }, - "medium": { "value": "#999999" }, - "dark" : { "value": "#111111" } + "light": { "value": "#CCCCCC", "type": "color" }, + "medium": { "value": "#999999", "type": "color" }, + "dark": { "value": "#111111", "type": "color" } }, - "red": { "value": "#FF0000" }, - "green": { "value": "#00FF00" } + "red": { "value": "#FF0000", "type": "color" }, + "green": { "value": "#00FF00", "type": "color" } } } } diff --git a/examples/advanced/assets-base64-embed/tokens/color/font.json b/examples/advanced/assets-base64-embed/tokens/color/font.json index df0b84832..abb462c38 100644 --- a/examples/advanced/assets-base64-embed/tokens/color/font.json +++ b/examples/advanced/assets-base64-embed/tokens/color/font.json @@ -1,9 +1,9 @@ { "color": { "font": { - "base" : { "value": "{color.base.red.value}" }, - "secondary": { "value": "{color.base.green.value}" }, - "tertiary" : { "value": "{color.base.gray.light.value}" } + "base": { "value": "{color.base.red.value}", "type": "color" }, + "secondary": { "value": "{color.base.green.value}", "type": "color" }, + "tertiary": { "value": "{color.base.gray.light.value}", "type": "color" } } } } diff --git a/examples/advanced/assets-base64-embed/tokens/size/font.json b/examples/advanced/assets-base64-embed/tokens/size/font.json index 24e7b8034..5e487afc2 100644 --- a/examples/advanced/assets-base64-embed/tokens/size/font.json +++ b/examples/advanced/assets-base64-embed/tokens/size/font.json @@ -1,21 +1,25 @@ { "size": { "font": { - "small" : { + "small": { "value": "0.75", - "comment": "the small size of the font" + "comment": "the small size of the font", + "type": "fontSize" }, "medium": { "value": "1", - "comment": "the medium size of the font" + "comment": "the medium size of the font", + "type": "fontSize" }, - "large" : { + "large": { "value": "2", - "comment": "the large size of the font" + "comment": "the large size of the font", + "type": "fontSize" }, - "base" : { + "base": { "value": "{size.font.medium.value}", - "comment": "the base size of the font" + "comment": "the base size of the font", + "type": "fontSize" } } } diff --git a/examples/advanced/auto-rebuild-watcher/.gitignore b/examples/advanced/auto-rebuild-watcher/.gitignore deleted file mode 100644 index 3e2e84b08..000000000 --- a/examples/advanced/auto-rebuild-watcher/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -node_modules/ diff --git a/examples/advanced/auto-rebuild-watcher/README.md b/examples/advanced/auto-rebuild-watcher/README.md deleted file mode 100644 index 215484ba6..000000000 --- a/examples/advanced/auto-rebuild-watcher/README.md +++ /dev/null @@ -1,31 +0,0 @@ -## How to use a watcher to auto-rebuild - -This example shows how to use a "watcher" to rebuild automatically the files every time a token file is updated. - -This is quite handy when there are continuous changes to the token values (e.g. during development) and we want to avoid to run the "build" command at every update. - -#### Running the example - -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). - -At this point, if you want to build once the tokens you can run `npm run build`. This command will generate the files in the `build` folder. - -If instead you want to automatically build the tokens every time a token file is updated, run the command `npm run watch` in your CLI. - -This will start to watch the files in the "tokens" folder, and whenever a file is updated and saved, the files in `build` are re-generated with the new/updated values. - -If you want to see it in action, open one of the files generated in "build", open a token file and update one of the values: you will see immediately updated also the generated file. - -**Important**: when in "watch" mode, to interrupt and exit the process and get back to your command line, use the `ctrl-c` command in your terminal. - -#### How does it work - -The "watch" runner will start a process (using a special filesystem watcher called [Chokidar](https://github.com/paulmillr/chokidar)) that will listen to changes to a list of "watched" files. Whenever one of this file is changed/updated (more precisely, is saved to disk) the watch process will trigger a command specified by the user (as an argument passed to the watcher). - -In this example, we have selected all the JSON files in the `tokens` folder (using the glob pattern `tokens/**/*.json`) but you can specify your own path of watched files. - -The command that we automatically run at every update is the `npm run build` command, passed as parameter to the watcher via `-c 'npm run build'`. - -#### What to look at - -Open the `package.json` file and see how in the "scripts" block there is an additional entry for "watch". This is the way the "watch" mode is invoked and run. diff --git a/examples/advanced/auto-rebuild-watcher/config.json b/examples/advanced/auto-rebuild-watcher/config.json deleted file mode 100644 index 6710fad62..000000000 --- a/examples/advanced/auto-rebuild-watcher/config.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "source": ["tokens/**/*.json"], - "platforms": { - "scss": { - "transformGroup": "scss", - "buildPath": "build/scss/", - "files": [{ - "destination": "_variables.scss", - "format": "scss/variables" - }] - }, - "android": { - "transformGroup": "android", - "buildPath": "build/android/", - "files": [{ - "destination": "font_dimens.xml", - "format": "android/fontDimens" - },{ - "destination": "colors.xml", - "format": "android/colors" - }] - }, - "ios": { - "transformGroup": "ios", - "buildPath": "build/ios/", - "files": [{ - "destination": "StyleDictionaryColor.h", - "format": "ios/colors.h", - "className": "StyleDictionaryColor", - "type": "StyleDictionaryColorName", - "filter": { - "attributes": { - "category": "color" - } - } - },{ - "destination": "StyleDictionaryColor.m", - "format": "ios/colors.m", - "className": "StyleDictionaryColor", - "type": "StyleDictionaryColorName", - "filter": { - "attributes": { - "category": "color" - } - } - },{ - "destination": "StyleDictionarySize.h", - "format": "ios/static.h", - "className": "StyleDictionarySize", - "type": "float", - "filter": { - "attributes": { - "category": "size" - } - } - },{ - "destination": "StyleDictionarySize.m", - "format": "ios/static.m", - "className": "StyleDictionarySize", - "type": "float", - "filter": { - "attributes": { - "category": "size" - } - } - }] - } - } -} diff --git a/examples/advanced/auto-rebuild-watcher/package.json b/examples/advanced/auto-rebuild-watcher/package.json deleted file mode 100644 index 0b06472ab..000000000 --- a/examples/advanced/auto-rebuild-watcher/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "style-dictionary-auto-rebuild-watcher", - "version": "1.0.0", - "description": "", - "main": "build/index.js", - "files": [ - "build", - "properties" - ], - "scripts": { - "build": "node_modules/.bin/style-dictionary build", - "clean": "rm -rf build", - "watch": "npm run build && chokidar \"tokens/**/*.json\" -c \"npm run build\"", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "Apache-2.0", - "devDependencies": { - "chokidar-cli": "^1.2.0", - "style-dictionary": "3.8.0" - } -} \ No newline at end of file diff --git a/examples/advanced/auto-rebuild-watcher/tokens/color/base.json b/examples/advanced/auto-rebuild-watcher/tokens/color/base.json deleted file mode 100644 index 02a99d700..000000000 --- a/examples/advanced/auto-rebuild-watcher/tokens/color/base.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "color": { - "base": { - "gray": { - "light" : { "value": "#CCCCCC" }, - "medium": { "value": "#999999" }, - "dark" : { "value": "#111111" } - }, - "red": { "value": "#FF0000" }, - "green": { "value": "#00FF00" } - } - } -} diff --git a/examples/advanced/auto-rebuild-watcher/tokens/color/font.json b/examples/advanced/auto-rebuild-watcher/tokens/color/font.json deleted file mode 100644 index df0b84832..000000000 --- a/examples/advanced/auto-rebuild-watcher/tokens/color/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "font": { - "base" : { "value": "{color.base.red.value}" }, - "secondary": { "value": "{color.base.green.value}" }, - "tertiary" : { "value": "{color.base.gray.light.value}" } - } - } -} diff --git a/examples/advanced/auto-rebuild-watcher/tokens/size/font.json b/examples/advanced/auto-rebuild-watcher/tokens/size/font.json deleted file mode 100644 index 24e7b8034..000000000 --- a/examples/advanced/auto-rebuild-watcher/tokens/size/font.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "size": { - "font": { - "small" : { - "value": "0.75", - "comment": "the small size of the font" - }, - "medium": { - "value": "1", - "comment": "the medium size of the font" - }, - "large" : { - "value": "2", - "comment": "the large size of the font" - }, - "base" : { - "value": "{size.font.medium.value}", - "comment": "the base size of the font" - } - } - } -} diff --git a/examples/advanced/component-cti/.gitignore b/examples/advanced/component-cti/.gitignore deleted file mode 100644 index 3e2e84b08..000000000 --- a/examples/advanced/component-cti/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -node_modules/ diff --git a/examples/advanced/component-cti/README.md b/examples/advanced/component-cti/README.md deleted file mode 100644 index 940c33891..000000000 --- a/examples/advanced/component-cti/README.md +++ /dev/null @@ -1,89 +0,0 @@ -## Component CTI Structure - -This example will show you one way to define component tokens in a simple way while still using the CTI attributes for transforming the tokens. The CTI structure for Style Dictionary tokens makes defining component-level tokens cumbersome and not user-friendly. This is because the CTI of tokens is based on the object path of the token. Now, if you wanted to write tokens for a button component it would have to look something like this: - -```json -{ - "size": { - "padding" : { - "button": { "value": "{size.padding.base.value}" } - }, - "font": { - "button": { "value": 2 } - } - }, - - "color": { - "font": { - "button": { - "primary": { "value": "{color.font.inverse.value}" }, - "secondary": { "value": "{color.font.link.value}" } - } - }, - - "background": { - "button": { - "primary": { "value": "hsl(10, 80, 50)" }, - "secondary": { "value": "{color.background.primary.value}" } - } - } - } -} -``` - -Instead, when defining component tokens it makes more sense to structure them more like CSS. `component.button.background-color` makes more sense than `color.background.button`. Here is what the component tokens would look like in this new structure: - -```json -{ - "component": { - "button": { - "padding": { "value": "{size.padding.medium.value}" }, - "font-size": { "value": 2 }, - - "primary": { - "background-color": { "value": "hsl(10, 80, 50)" }, - "color": { "value": "{color.font.inverse.value}" } - }, - - "secondary": { - "background-color": { "value": "{color.background.primary.value}" }, - "color": { "value": "{color.font.link.value}" } - } - } - } -} -``` - -### Running the example - -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). - -At this point, if you want to build the tokens run `npm run build`. This command will generate the files in the `build` folder. - - -### How does it work - -All of the built-in transforms target tokens using the CTI attributes. The built-in [`attribute/cti`](https://amzn.github.io/style-dictionary/#/transforms?id=attributecti) transform adds the CTI attributes to each token based on the object path of the token. In this example we override the default behavior of the [`attribute/cti`](https://amzn.github.io/style-dictionary/#/transforms?id=attributecti) transform to apply CTI attributes based on token's key, or last part of the object path to generate the equivalent category and type. This way we can correctly map a token with an object path of `component.button.background-color` to a category of `color` and type of `background`. - -Style Dictionary allows for extensibility through [monkey patching](https://en.wikipedia.org/wiki/Monkey_patch). This allows you to override the default behavior of the Style Dictionary library, and any built-in transforms and formats. You can override built-in transforms and formats by adding ones with the same name. Also, all of the built-in transforms, transformGroups, and formats are available by accessing them in the Style Dictionary library under the attributes `transform`, `transformGroup`, and `format` respectively. For example: - -```javascript -const StyleDictionary = require('style-dictionary'); - -const cti = StyleDictionary.transform['attribute/cti']; -// { -// type: 'attribute', -// transformer: f () {} -// } -``` - -In this example we monkey patch the `attribute/cti` transform to look at the top-level namespace of the token and if it is 'component', instead of running the default `attribute/cti` transform, it instead looks at the last part of the object path to generate the equivalent category and type. - -For example, if the key of the token (the last part of the object path) is "background-color", the monkey patched `attribute/cti` transform will return a category of 'color' and type of 'background'. This example uses CSS property names, but you could also change it to use similar React/CSS-in-JS names like 'backgroundColor' instead of 'background-color'. - -### What to look at - -* `config.js`: - * `propertiesToCTI`: A plain object where we map the CSS property name to the proper category and type. - * `CTITransform`: A transform object that defines a transformer method, which will override the default `attribute/cti` transform. This is similar to creating a child class with some custom logic and then calling `super`. In the transformer function it first looks at the top-level namespace, the first item in the object path, and if it is 'component' we run our custom logic using the `propertiesToCTI` map. If it is not 'component', use the built-in `attribute/cti`. -* `tokens/component/button.json`: Take a look at how it defines the component tokens and uses the last part of the object path as the CSS property. Notice how we can define token values in here that are not references, but they still get transformed properly: font-size uses 'rem' and background-color uses hex in the output. diff --git a/examples/advanced/component-cti/config.js b/examples/advanced/component-cti/config.js deleted file mode 100644 index a8d1688a7..000000000 --- a/examples/advanced/component-cti/config.js +++ /dev/null @@ -1,71 +0,0 @@ -const StyleDictionary = require('style-dictionary'); -const transformer = StyleDictionary.transform['attribute/cti'].transformer; - -const propertiesToCTI = { - 'width': {category: 'size', type: 'dimension'}, - 'min-width': {category: 'size', type: 'dimension'}, - 'max-width': {category: 'size', type: 'dimension'}, - 'height': {category: 'size', type: 'dimension'}, - 'min-height': {category: 'size', type: 'dimension'}, - 'max-height': {category: 'size', type: 'dimension'}, - 'border-width': {category: 'size', type: 'border', item: 'width'}, - 'border-radius': { category: 'size', type: 'border', item: 'width' }, - 'border-color': {category: 'color', type: 'border'}, - 'background-color': {category: 'color', type: 'background'}, - 'color': {category: 'color', type: 'font'}, - 'text-color': { category: 'color', type: 'font' }, - 'padding': {category: 'size', type: 'padding'}, - 'padding-vertical': {category: 'size', type: 'padding'}, - 'padding-horizontal': {category: 'size', type: 'padding'}, - 'icon': {category: 'content', type: 'icon'}, - 'font-size': {category: 'size', type: 'font'}, - 'line-height': { category: 'size', type: 'line-height' }, - 'size': {category: 'size', type: 'icon'} -} - -const CTITransform = { - type: `attribute`, - transformer: (prop) => { - // Only do this custom functionality in the 'component' top-level namespace. - if (prop.path[0] === 'component') { - // When defining component tokens, the key of the token is the relevant CSS property - // The key of the token is the last element in the path array - return propertiesToCTI[prop.path[prop.path.length - 1]]; - } else { - // Fallback to the original 'attribute/cti' transformer - return transformer(prop); - } - } -} - -// We can call .registerTransform here -// or apply the custom transform directly in the configuration below -// -// StyleDictionary.registerTransform({ -// name: 'attribute/cti', -// type: 'attribute', -// transformer: CTITransform.transformer -// }); - -module.exports = { - // Rather than calling .registerTransform() we can apply the new transform - // directly in our configuration. Using .registerTransform() with the same - // transform name, 'attribute/cti', would work as well. - transform: { - // Override the attribute/cti transform - 'attribute/cti': CTITransform - }, - source: ['tokens/**/*.json'], - platforms: { - scss: { - // We can still use this transformGroup because we are overriding - // the underlying transform - transformGroup: "scss", - buildPath: 'build/', - files: [{ - destination: 'variables.scss', - format: 'scss/variables' - }] - } - } -} diff --git a/examples/advanced/component-cti/package.json b/examples/advanced/component-cti/package.json deleted file mode 100644 index 428c284a9..000000000 --- a/examples/advanced/component-cti/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "style-dictionary-component-cti", - "version": "1.0.0", - "description": "", - "main": "build/index.js", - "files": [ - "build", - "properties" - ], - "scripts": { - "build": "style-dictionary build --config ./config.js", - "clean": "rm -rf build", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "Apache-2.0", - "devDependencies": { - "style-dictionary": "3.8.0" - } -} \ No newline at end of file diff --git a/examples/advanced/component-cti/tokens/color/background.json b/examples/advanced/component-cti/tokens/color/background.json deleted file mode 100644 index e46810041..000000000 --- a/examples/advanced/component-cti/tokens/color/background.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "background": { - "primary": { "value": "#ffffff" }, - "link": { "value": "#0366d6" }, - "inverse": { "value": "#111111" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/component-cti/tokens/color/core.json b/examples/advanced/component-cti/tokens/color/core.json deleted file mode 100644 index b94ef6833..000000000 --- a/examples/advanced/component-cti/tokens/color/core.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "color": { - "core": { - "white": { "value": "#ffffff" }, - "black": { "value": "#111111" }, - "gray": { "value": "#dddddd" }, - "blue": { "value": "#0366d6" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/component-cti/tokens/color/font.json b/examples/advanced/component-cti/tokens/color/font.json deleted file mode 100644 index 296e619f0..000000000 --- a/examples/advanced/component-cti/tokens/color/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "font": { - "primary": { "value": "{color.core.black.value}" }, - "link": { "value": "{color.core.blue.value}" }, - "inverse": { "value": "{color.core.white.value}" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/component-cti/tokens/component/button.json b/examples/advanced/component-cti/tokens/component/button.json deleted file mode 100644 index bc5e45684..000000000 --- a/examples/advanced/component-cti/tokens/component/button.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "component": { - "button": { - "padding": { "value": "{size.padding.medium.value}" }, - "font-size": { "value": 2 }, - "text-align": { "value": "center" }, - - "primary": { - "background-color": { "value": "hsl(10, 80, 50)" }, - "color": { "value": "{color.font.inverse.value}" } - }, - - "secondary": { - "background-color": { "value": "{color.background.primary.value}" }, - "color": { "value": "{color.font.link.value}" } - } - } - } -} \ No newline at end of file diff --git a/examples/advanced/component-cti/tokens/size/font.json b/examples/advanced/component-cti/tokens/size/font.json deleted file mode 100644 index 650894ec9..000000000 --- a/examples/advanced/component-cti/tokens/size/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "size": { - "font": { - "small": { "value": 0.75 }, - "medium": { "value": 1 }, - "large": { "value": 1.5 } - } - } -} \ No newline at end of file diff --git a/examples/advanced/component-cti/tokens/size/padding.json b/examples/advanced/component-cti/tokens/size/padding.json deleted file mode 100644 index 47692fdb1..000000000 --- a/examples/advanced/component-cti/tokens/size/padding.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "size": { - "padding": { - "small": { "value": 0.5 }, - "medium": { "value": 1 }, - "large": { "value": 2 } - } - } -} \ No newline at end of file diff --git a/examples/advanced/create-react-app/README.md b/examples/advanced/create-react-app/README.md index f735ceda7..b87f9f49f 100644 --- a/examples/advanced/create-react-app/README.md +++ b/examples/advanced/create-react-app/README.md @@ -1,12 +1,12 @@ ## How to consume Style Dictionary properties in React -This example shows how to consume design tokens, generated via Style Dictionary, in a React application. +This example shows how to consume design tokens, generated via Style Dictionary, in a React application. To setup the app we have used [Create React App](https://facebook.github.io/create-react-app/) (CRA); we then have added to the default page three similar components, styled via [Sass](http://sass-lang.com/), [CSS Modules](https://github.com/css-modules/css-modules) and [Styled Components](https://www.styled-components.com). The CSS for these three different stylings is consuming the same set of tokens generated from design properties. #### Running the example -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). +First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use _yarn_, update the commands accordingly). At this point, if you want to build the tokens and launch the React application, you can run `npm run start`. This command will first generate the tokens files, then compile the React application, and finally launch the local web server and open the application in a browser window. @@ -18,7 +18,6 @@ If instead you want to build the tokens only, you can run `npm run build-diction **Important**: the file `.env` in this folder is to have CRA run inside another project; if want to use this example as standalone codebase please remove it. - #### What to look at In the **`style-dictionary`** folder you can find the properties files (`color/font/spacing.json`) and the configuration file (`config.json`) used by Style Dictionary to build the design tokens. @@ -39,18 +38,17 @@ The folder `components` contains the code for the three components used in the a - The **`components/with-sass`** folder contains the example React component, styled using CSS/Sass. Look at how the design tokens are consumed inside the Sass file as Sass variables. The Sass file is then imported in the component which will be compiled to CSS at build time and included in the resulting web app page. -- The **`components/with-css-modules`** folder contains the example React component, styled using CSS Modules. Look at how the styles are imported in the component, and the class names are applied to the HTML elements. The CSS styles are declared in Sass by which the design tokens can be consumed directly as Sass variables.
*If you want to know more about how CSS Modules works with React, and how it applies CSS styles to the JSX elements, [please refer to the documentation](https://github.com/css-modules/css-modules/blob/master/docs/css-modules-with-react.md).* +- The **`components/with-css-modules`** folder contains the example React component, styled using CSS Modules. Look at how the styles are imported in the component, and the class names are applied to the HTML elements. The CSS styles are declared in Sass by which the design tokens can be consumed directly as Sass variables.
_If you want to know more about how CSS Modules works with React, and how it applies CSS styles to the JSX elements, [please refer to the documentation](https://github.com/css-modules/css-modules/blob/master/docs/css-modules-with-react.md)._ -* The **`components/with-styled-components`** folder contains the example React component, styled using Styled Components. Look at how in this case the styles are declared directly in the component, as template literal "objects", and how the design tokens are consumed as JavaScript variables.
*If you want to know more about how Styled Components works, and how it applies CSS styles to the HTML elements, [please refer to the documentation](https://www.styled-components.com/docs/basics#getting-started).* +* The **`components/with-styled-components`** folder contains the example React component, styled using Styled Components. Look at how in this case the styles are declared directly in the component, as template literal "objects", and how the design tokens are consumed as JavaScript variables.
_If you want to know more about how Styled Components works, and how it applies CSS styles to the HTML elements, [please refer to the documentation](https://www.styled-components.com/docs/basics#getting-started)._ -- - ### Some useful links - [Official documentation for Create React App](https://github.com/facebook/create-react-app) - [How to use Sass and CSS Modules with create-react-app -](https://blog.bitsrc.io/how-to-use-sass-and-css-modules-with-create-react-app-83fa8b805e5e) + ](https://blog.bitsrc.io/how-to-use-sass-and-css-modules-with-create-react-app-83fa8b805e5e) - [CSS Modules and create-react-app](https://www.robinwieruch.de/create-react-app-css-modules/) - [Getting started with Styled Components and Create React App](https://medium.com/styled-components/styled-components-getting-started-c9818acbcbbd) - [How do I use styled-components with create-react-app?](https://www.styled-components.com/docs/faqs#how-do-i-use-styledcomponents-with-createreactapp) diff --git a/examples/advanced/create-react-app/package.json b/examples/advanced/create-react-app/package.json index 7f37c9d14..7aeae24b1 100644 --- a/examples/advanced/create-react-app/package.json +++ b/examples/advanced/create-react-app/package.json @@ -1,6 +1,7 @@ { "name": "style-dictionary-create-react-app", "description": "", + "type": "module", "version": "1.0.0", "dependencies": { "node-sass": "^7.0.0", @@ -10,7 +11,8 @@ "styled-components": "^5.3.0" }, "devDependencies": { - "style-dictionary": "3.8.0" + "eslint-config-react-app": "^7.0.1", + "style-dictionary": "4.0.0-prerelease.30" }, "resolutions": { "immer": "8.0.1", @@ -35,4 +37,4 @@ "not op_mini all" ], "license": "Apache-2.0" -} \ No newline at end of file +} diff --git a/examples/advanced/create-react-app/src/App.js b/examples/advanced/create-react-app/src/App.js index 9b562b7f1..7858f6c92 100644 --- a/examples/advanced/create-react-app/src/App.js +++ b/examples/advanced/create-react-app/src/App.js @@ -16,10 +16,17 @@ class App extends Component { React logo
-

- This app is built with Create React App (CRA) -

- More information about CRA: github.com/facebook/create-react-app +

This app is built with Create React App (CRA)

+ + More information about CRA:{' '} + + github.com/facebook/create-react-app + +
diff --git a/examples/advanced/create-react-app/src/components/with-css-modules/ComponentWithCssModules.js b/examples/advanced/create-react-app/src/components/with-css-modules/ComponentWithCssModules.js index 069382181..d81096f3c 100644 --- a/examples/advanced/create-react-app/src/components/with-css-modules/ComponentWithCssModules.js +++ b/examples/advanced/create-react-app/src/components/with-css-modules/ComponentWithCssModules.js @@ -8,13 +8,23 @@ class MyComponent extends Component { render() { return (
- CSS Modules logo -
-

- This component is styled with CSS Modules and Style Dictionary tokens -

-

More information about CSS Modules: github.com/css-modules/css-modules

-
+ CSS Modules logo +
+

+ This component is styled with CSS Modules and Style Dictionary tokens +

+

+ More information about CSS Modules:{' '} + + github.com/css-modules/css-modules + +

+
); } diff --git a/examples/advanced/create-react-app/src/components/with-sass/ComponentWithSass.js b/examples/advanced/create-react-app/src/components/with-sass/ComponentWithSass.js index 0a41d8cd1..2be63cfbd 100644 --- a/examples/advanced/create-react-app/src/components/with-sass/ComponentWithSass.js +++ b/examples/advanced/create-react-app/src/components/with-sass/ComponentWithSass.js @@ -6,13 +6,23 @@ class MyComponent extends Component { render() { return (
- Sass logo -
-

- This component is styled with Sass and Style Dictionary tokens -

-

More information about Sass: sass-lang.com

-
+ Sass logo +
+

+ This component is styled with Sass and Style Dictionary tokens +

+

+ More information about Sass:{' '} + + sass-lang.com + +

+
); } diff --git a/examples/advanced/create-react-app/src/components/with-styled-components/ComponentWithStyledComponents.js b/examples/advanced/create-react-app/src/components/with-styled-components/ComponentWithStyledComponents.js index 83534f683..46c68e4fa 100644 --- a/examples/advanced/create-react-app/src/components/with-styled-components/ComponentWithStyledComponents.js +++ b/examples/advanced/create-react-app/src/components/with-styled-components/ComponentWithStyledComponents.js @@ -48,13 +48,22 @@ class MyComponent extends Component { render() { return ( - - - - This component is styled with Styled Components and Style Dictionary tokens - - More information about Styled Components: styled-components.com - + + + + This component is styled with Styled Components and Style Dictionary tokens + + + More information about Styled Components:{' '} + + styled-components.com + + + ); } diff --git a/examples/advanced/create-react-app/src/serviceWorker.js b/examples/advanced/create-react-app/src/serviceWorker.js index f384f9b0f..452926a69 100644 --- a/examples/advanced/create-react-app/src/serviceWorker.js +++ b/examples/advanced/create-react-app/src/serviceWorker.js @@ -15,9 +15,7 @@ const isLocalhost = Boolean( // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) + window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/), ); export function register(config) { @@ -43,7 +41,7 @@ export function register(config) { navigator.serviceWorker.ready.then(() => { console.log( 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit http://bit.ly/CRA-PWA' + 'worker. To learn more, visit http://bit.ly/CRA-PWA', ); }); } else { @@ -57,7 +55,7 @@ export function register(config) { function registerValidSW(swUrl, config) { navigator.serviceWorker .register(swUrl) - .then(registration => { + .then((registration) => { registration.onupdatefound = () => { const installingWorker = registration.installing; if (installingWorker == null) { @@ -71,7 +69,7 @@ function registerValidSW(swUrl, config) { // content until all client tabs are closed. console.log( 'New content is available and will be used when all ' + - 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' + 'tabs for this page are closed. See http://bit.ly/CRA-PWA.', ); // Execute callback @@ -93,7 +91,7 @@ function registerValidSW(swUrl, config) { }; }; }) - .catch(error => { + .catch((error) => { console.error('Error during service worker registration:', error); }); } @@ -101,7 +99,7 @@ function registerValidSW(swUrl, config) { function checkValidServiceWorker(swUrl, config) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl) - .then(response => { + .then((response) => { // Ensure service worker exists, and that we really are getting a JS file. const contentType = response.headers.get('content-type'); if ( @@ -109,7 +107,7 @@ function checkValidServiceWorker(swUrl, config) { (contentType != null && contentType.indexOf('javascript') === -1) ) { // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { + navigator.serviceWorker.ready.then((registration) => { registration.unregister().then(() => { window.location.reload(); }); @@ -120,15 +118,13 @@ function checkValidServiceWorker(swUrl, config) { } }) .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); + console.log('No internet connection found. App is running in offline mode.'); }); } export function unregister() { if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { + navigator.serviceWorker.ready.then((registration) => { registration.unregister(); }); } diff --git a/examples/advanced/create-react-app/style-dictionary/config.json b/examples/advanced/create-react-app/style-dictionary/config.json index 9cb9b3e4f..55979341b 100644 --- a/examples/advanced/create-react-app/style-dictionary/config.json +++ b/examples/advanced/create-react-app/style-dictionary/config.json @@ -1,22 +1,26 @@ { - "source": ["./style-dictionary/properties/**/*.json"], + "source": ["./style-dictionary/tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", "buildPath": "./src/style-dictionary-dist/", "prefix": "token", - "files": [{ - "destination": "variables.scss", - "format": "scss/variables" - }] + "files": [ + { + "destination": "variables.scss", + "format": "scss/variables" + } + ] }, "js": { "transformGroup": "js", "buildPath": "./src/style-dictionary-dist/", - "files": [{ - "destination": "variables.js", - "format": "javascript/es6" - }] + "files": [ + { + "destination": "variables.js", + "format": "javascript/es6" + } + ] } } } diff --git a/examples/advanced/create-react-app/style-dictionary/properties/color.json b/examples/advanced/create-react-app/style-dictionary/properties/color.json deleted file mode 100644 index e5bcb28f0..000000000 --- a/examples/advanced/create-react-app/style-dictionary/properties/color.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "color": { - "base": { - "primary": { - "value": "#61dafb" - }, - "secondary": { - "value": "#fc7aa5" - } - }, - "text": { - "value": "#666666" - }, - "background": { - "value": "#EEEEEE" - } - } -} diff --git a/examples/advanced/create-react-app/style-dictionary/properties/font.json b/examples/advanced/create-react-app/style-dictionary/properties/font.json deleted file mode 100644 index 6eaccdd1b..000000000 --- a/examples/advanced/create-react-app/style-dictionary/properties/font.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "font": { - "family": { - "base" : { - "value": "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif" - }, - "code" : { - "value": "source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace" - } - } - }, - "size": { - "text": { - "base" : { - "value": "{size.text.medium.value}" - }, - "small" : { - "value": "0.75" - }, - "medium": { - "value": "1" - }, - "large" : { - "value": "1.5" - } - } - } -} diff --git a/examples/advanced/create-react-app/style-dictionary/properties/spacing.json b/examples/advanced/create-react-app/style-dictionary/properties/spacing.json deleted file mode 100644 index 31164e7ab..000000000 --- a/examples/advanced/create-react-app/style-dictionary/properties/spacing.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "spacing": { - "small": { - "value": "10px" - }, - "medium": { - "value": "20px" - }, - "large": { - "value": "30px" - } - } -} diff --git a/examples/advanced/create-react-app/style-dictionary/tokens/color.json b/examples/advanced/create-react-app/style-dictionary/tokens/color.json new file mode 100644 index 000000000..500702645 --- /dev/null +++ b/examples/advanced/create-react-app/style-dictionary/tokens/color.json @@ -0,0 +1,22 @@ +{ + "color": { + "base": { + "primary": { + "value": "#61dafb", + "type": "color" + }, + "secondary": { + "value": "#fc7aa5", + "type": "color" + } + }, + "text": { + "value": "#666666", + "type": "color" + }, + "background": { + "value": "#EEEEEE", + "type": "color" + } + } +} diff --git a/examples/advanced/create-react-app/style-dictionary/tokens/font.json b/examples/advanced/create-react-app/style-dictionary/tokens/font.json new file mode 100644 index 000000000..76fd2f048 --- /dev/null +++ b/examples/advanced/create-react-app/style-dictionary/tokens/font.json @@ -0,0 +1,34 @@ +{ + "font": { + "family": { + "base": { + "value": "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", + "type": "fontFamily" + }, + "code": { + "value": "source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace", + "type": "fontFamily" + } + } + }, + "size": { + "text": { + "base": { + "value": "{size.text.medium.value}", + "type": "fontSize" + }, + "small": { + "value": "0.75", + "type": "fontSize" + }, + "medium": { + "value": "1", + "type": "fontSize" + }, + "large": { + "value": "1.5", + "type": "fontSize" + } + } + } +} diff --git a/examples/advanced/create-react-app/style-dictionary/tokens/spacing.json b/examples/advanced/create-react-app/style-dictionary/tokens/spacing.json new file mode 100644 index 000000000..d948f29b8 --- /dev/null +++ b/examples/advanced/create-react-app/style-dictionary/tokens/spacing.json @@ -0,0 +1,16 @@ +{ + "spacing": { + "small": { + "value": "10px", + "type": "dimension" + }, + "medium": { + "value": "20px", + "type": "dimension" + }, + "large": { + "value": "30px", + "type": "dimension" + } + } +} diff --git a/examples/advanced/create-react-native-app/__tests__/App.js b/examples/advanced/create-react-native-app/__tests__/App.js index e1f2e0594..176ee3c5d 100644 --- a/examples/advanced/create-react-native-app/__tests__/App.js +++ b/examples/advanced/create-react-native-app/__tests__/App.js @@ -1,10 +1,10 @@ -import "react-native"; -import React from "react"; -import App from "../src/App"; +import 'react-native'; +import React from 'react'; +import App from '../src/App'; // Note: test renderer must be required after react-native. -import renderer from "react-test-renderer"; +import renderer from 'react-test-renderer'; -it("renders correctly", () => { +it('renders correctly', () => { renderer.create(); }); diff --git a/examples/advanced/create-react-native-app/babel.config.js b/examples/advanced/create-react-native-app/babel.config.js index 2900afe9d..9d89e1311 100644 --- a/examples/advanced/create-react-native-app/babel.config.js +++ b/examples/advanced/create-react-native-app/babel.config.js @@ -1,4 +1,4 @@ -module.exports = function(api) { +module.exports = function (api) { api.cache(true); return { presets: ['babel-preset-expo'], diff --git a/examples/advanced/create-react-native-app/config.json b/examples/advanced/create-react-native-app/config.json index d7441a0ca..01d2a5be9 100644 --- a/examples/advanced/create-react-native-app/config.json +++ b/examples/advanced/create-react-native-app/config.json @@ -1,5 +1,5 @@ { - "source": ["./style-dictionary/properties/**/*.json"], + "source": ["./style-dictionary/tokens/**/*.json"], "platforms": { "rn": { "transformGroup": "react-native", diff --git a/examples/advanced/create-react-native-app/index.js b/examples/advanced/create-react-native-app/index.js index 4e11800cc..be6bdb8d7 100644 --- a/examples/advanced/create-react-native-app/index.js +++ b/examples/advanced/create-react-native-app/index.js @@ -1,6 +1,6 @@ -import { registerRootComponent } from "expo"; +import { registerRootComponent } from 'expo'; -import App from "./src/App"; +import App from './src/App'; // registerRootComponent calls AppRegistry.registerComponent('main', () => App); // It also ensures that whether you load the app in the Expo client or in a native build, diff --git a/examples/advanced/create-react-native-app/metro.config.js b/examples/advanced/create-react-native-app/metro.config.js index ba9728366..84f5f08f7 100644 --- a/examples/advanced/create-react-native-app/metro.config.js +++ b/examples/advanced/create-react-native-app/metro.config.js @@ -1,5 +1,6 @@ -module.exports = { +const cfg = { transformer: { assetPlugins: ['expo-asset/tools/hashAssetFiles'], }, }; +export default cfg; diff --git a/examples/advanced/create-react-native-app/package.json b/examples/advanced/create-react-native-app/package.json index 3e2fe4ee6..3ea237d00 100644 --- a/examples/advanced/create-react-native-app/package.json +++ b/examples/advanced/create-react-native-app/package.json @@ -1,5 +1,6 @@ { "main": "index.js", + "type": "module", "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", @@ -25,12 +26,16 @@ "devDependencies": { "@babel/core": "~7.9.0", "babel-jest": "~25.2.6", + "eslint-config-react-app": "^7.0.1", "jest": "~25.2.6", "react-test-renderer": "~16.13.1", - "style-dictionary": "3.8.0" + "style-dictionary": "4.0.0-prerelease.30" }, "jest": { "preset": "react-native" }, + "eslintConfig": { + "extends": "react-app" + }, "private": true -} \ No newline at end of file +} diff --git a/examples/advanced/create-react-native-app/src/App.js b/examples/advanced/create-react-native-app/src/App.js index 05b4b3da7..a95e034df 100644 --- a/examples/advanced/create-react-native-app/src/App.js +++ b/examples/advanced/create-react-native-app/src/App.js @@ -1,13 +1,14 @@ -import { StatusBar } from "expo-status-bar"; -import React from "react"; -import { StyleSheet, Text, View, PixelRatio } from "react-native"; -import * as variables from "./style-dictionary-dist/variables"; +import { StatusBar } from 'expo-status-bar'; +import React from 'react'; +import { StyleSheet, Text, View, PixelRatio } from 'react-native'; +import * as variables from './style-dictionary-dist/variables'; export default function App() { return ( Testing! Testing! All done! + {/* eslint-disable-next-line react/style-prop-object */} ); @@ -17,8 +18,8 @@ const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: variables.colorBrand01, - alignItems: "center", - justifyContent: "center", + alignItems: 'center', + justifyContent: 'center', }, title: { fontSize: PixelRatio.getFontScale() * variables.sizeFontMd.scale, diff --git a/examples/advanced/create-react-native-app/src/style-dictionary-dist/variables.js b/examples/advanced/create-react-native-app/src/style-dictionary-dist/variables.js index 888a75bca..dc8976470 100644 --- a/examples/advanced/create-react-native-app/src/style-dictionary-dist/variables.js +++ b/examples/advanced/create-react-native-app/src/style-dictionary-dist/variables.js @@ -3,7 +3,17 @@ * Generated on Fri, 18 Dec 2020 00:08:57 GMT */ -export const colorBrand01 = "#eeeeff"; -export const colorBrand02 = "#ddaa33"; -export const sizeFontSm = {"original":"16px","number":16,"decimal":0.16,"scale":256}; -export const sizeFontMd = {"original":"2rem","number":2,"decimal":0.02,"scale":32}; \ No newline at end of file +export const colorBrand01 = '#eeeeff'; +export const colorBrand02 = '#ddaa33'; +export const sizeFontSm = { + original: '16px', + number: 16, + decimal: 0.16, + scale: 256, +}; +export const sizeFontMd = { + original: '2rem', + number: 2, + decimal: 0.02, + scale: 32, +}; diff --git a/examples/advanced/create-react-native-app/style-dictionary/properties/color/brand.json b/examples/advanced/create-react-native-app/style-dictionary/tokens/color/brand.json similarity index 51% rename from examples/advanced/create-react-native-app/style-dictionary/properties/color/brand.json rename to examples/advanced/create-react-native-app/style-dictionary/tokens/color/brand.json index aa9b7ef30..bae1d56a4 100644 --- a/examples/advanced/create-react-native-app/style-dictionary/properties/color/brand.json +++ b/examples/advanced/create-react-native-app/style-dictionary/tokens/color/brand.json @@ -3,15 +3,11 @@ "brand": { "01": { "value": "#eef", - "attributes": { - "category": "color" - } + "type": "color" }, "02": { "value": "#da3", - "attributes": { - "category": "color" - } + "type": "color" } } } diff --git a/examples/advanced/create-react-native-app/style-dictionary/properties/size/size.json b/examples/advanced/create-react-native-app/style-dictionary/tokens/size/size.json similarity index 51% rename from examples/advanced/create-react-native-app/style-dictionary/properties/size/size.json rename to examples/advanced/create-react-native-app/style-dictionary/tokens/size/size.json index 06b26333b..a054dd509 100644 --- a/examples/advanced/create-react-native-app/style-dictionary/properties/size/size.json +++ b/examples/advanced/create-react-native-app/style-dictionary/tokens/size/size.json @@ -3,15 +3,11 @@ "font": { "sm": { "value": "16px", - "attributes": { - "category": "size" - } + "type": "fontSize" }, "md": { "value": "2rem", - "attributes": { - "category": "size" - } + "type": "fontSize" } } } diff --git a/examples/advanced/custom-file-header/README.md b/examples/advanced/custom-file-header/README.md deleted file mode 100644 index 7fb21736f..000000000 --- a/examples/advanced/custom-file-header/README.md +++ /dev/null @@ -1,44 +0,0 @@ -## Custom File Header - -Style Dictionary 3.0 added the ability to define custom file headers for files generated from formats. A file header is a comment at the beginning of the generated file that has some information about how it was generated. This is fairly common in build tools that output source code. Before 3.0 you could only show or hide this header in the built-in formats. Now you can write your own custom file header messages that can be used in built-in formats as well as custom formats. - -Use cases include: - -- Using a version number or hash in the file header comment -- Using your own custom message - - -#### Running the example - -First of all, set up the required dependencies running the command `npm ci` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). - -At this point, you can run `npm run build`. This command will generate output files in the `build` folder. Just to show how file headers work, this example outputs a bunch of files with the same code, but different file header comments. - - -#### How does it work - -There are 3 ways to add a custom file header: - -1. Using the `registerFileHeader` method, and then referencing the name in the file configuration. -1. Adding a `fileHeader` object to the Style Dictionary configuration, and then referencing the key in the file configuration -1. Writing the `fileHeader` as a function in the platform or file configuration - -This example codebase has all 3 methods for you to see which works best for you. All 3 methods are in the [**build.js**](/build.js) file. - -A file header is a function that returns an array of strings. This array of strings will get mapped to lines in a comment at the beginning of a file generated by a formatter. The formatter will take care of how to format the lines in the proper comment style (`//`, `/* */`). - -You can reference the file header in a custom format as well by using the `fileHeader` function in `StyleDictionary.formatHelpers`, as shown below: - -```javascript -const {fileHeader} = StyleDictionary.formatHelpers; - -const myCustomFormat = ({ dictionary, file }) => { - return `${fileHeader({file, commentStyle: 'short'})}${dictionary.allTokens.map(token => { - return `--${token.name}: ${token.value};` - }).join(`\n`)}` -} -``` - -#### What to look at - -* **build.js** Has everything you need diff --git a/examples/advanced/custom-file-header/build.js b/examples/advanced/custom-file-header/build.js deleted file mode 100644 index 70c4f2518..000000000 --- a/examples/advanced/custom-file-header/build.js +++ /dev/null @@ -1,120 +0,0 @@ -const crypto = require('crypto'); -const StyleDictionary = require('style-dictionary'); -const version = require('./package.json').version; - -// You can use the `fileHeader` format helper function -// This function will use any custom file headers or the default -// file header -const {fileHeader} = StyleDictionary.formatHelpers; - -const myCustomFormat = ({ dictionary, file }) => { - return `${fileHeader({file, commentStyle: 'short'})}${dictionary.allTokens.map(token => { - return `--${token.name}: ${token.value};` - }).join(`\n`)}` -} - -const styleDictionary = StyleDictionary.extend({ - // You can add custom file headers directly on the configuration by - // adding a `fileHeader` object. The keys inside are the names of - // the file headers - fileHeader: { - // defaultMessage is the built-in file header message: - // Do not edit directly - // Generated on Sat, 01 Jan 2000 00:00:00 GMT - myFileHeader: (defaultMessage) => { - // A file header function is expected to return an array of strings. - // This array will be mapped to the proper comment style for a given format. - // For example, Android XML formats use XML comments: , - // whereas other languages have short and long style comments, // and /* */ - return [ - ...defaultMessage, - 'hello, world!' - ]; - } - }, - - format: { - myCustomFormat - }, - - source: [`tokens/**/*.json`], - - platforms: { - css: { - transformGroup: `css`, - buildPath: `build/`, - files: [{ - destination: `variables.css`, - format: `css/variables`, - options: { - // You can now reference a custom file header in a file's options. - fileHeader: `myFileHeader` - } - },{ - destination: `variables1.css`, - format: `myCustomFormat`, - options: { - fileHeader: `myFileHeader` - } - },{ - destination: `variables2.css`, - format: `css/variables`, - options: { - // You can also directly pass a function to the `fileHeader` option: - fileHeader: () => { - return [ - `build version ${version}` - ] - } - } - }] - }, - js: { - transformGroup: `js`, - buildPath: `build/`, - // You can also add a header at the platform level. - // Platform-level options cascade down to files. - options: { - fileHeader: `customFileHeader` - }, - files: [{ - destination: `colors.js`, - format: `javascript/es6` - },{ - destination: `colors2.js`, - format: `javascript/es6`, - // This file won't get the custom header because it defines the - // showFileHeader option to false - options: { - showFileHeader: false - } - },{ - destination: `colors3.js`, - format: `javascript/es6`, - // This file will use the custom header defined here because the file's - // options take precedence over the platform's options. - options: { - fileHeader: () => [`Header overridden`] - } - }] - } - } -}); - -// Create a hash of style dictionary tokens object to use in a file header -const hash = crypto.createHash('md5') - .update(JSON.stringify(styleDictionary.tokens)) - .digest('hex'); - -// Adding a custom file header with the `.registerFileHeader` -styleDictionary.registerFileHeader({ - name: `customFileHeader`, - fileHeader: () => { - return [ - `Do not edit directly`, - `build hash ${hash}` - ] - } -}); - -styleDictionary.buildAllPlatforms(); \ No newline at end of file diff --git a/examples/advanced/custom-file-header/package.json b/examples/advanced/custom-file-header/package.json deleted file mode 100644 index 3cd7a01d0..000000000 --- a/examples/advanced/custom-file-header/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "custom-file-header", - "version": "1.0.0", - "description": "", - "main": "sd.config.js", - "scripts": { - "build": "node build.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "style-dictionary": "3.8.0" - } -} \ No newline at end of file diff --git a/examples/advanced/custom-file-header/tokens/color.json b/examples/advanced/custom-file-header/tokens/color.json deleted file mode 100644 index 02bedfcc6..000000000 --- a/examples/advanced/custom-file-header/tokens/color.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "core": { - "red": { "value": "#ff0000" }, - "blue": { "value": "#00ff00" }, - "green": { "value": "#0000ff" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/custom-filters/.gitignore b/examples/advanced/custom-filters/.gitignore deleted file mode 100644 index 3e2e84b08..000000000 --- a/examples/advanced/custom-filters/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -node_modules/ diff --git a/examples/advanced/custom-filters/README.md b/examples/advanced/custom-filters/README.md deleted file mode 100644 index 8978bb102..000000000 --- a/examples/advanced/custom-filters/README.md +++ /dev/null @@ -1,99 +0,0 @@ -## Filters - -This example shows how to use built-in and custom filters to the design tokens. - -Filters are functions that might remove according to some conditions a design token from the output distribution. - -#### Running the example - -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn* update the commands accordingly). - -At this point, if you want to build the tokens you can run `npm run build`. This command will generate the files in the `build` folder. - -#### How does it work a built-in filter? - -Currently StyleDictionary supports just the following built-in filters: - -- removePrivate - -You have to apply it in the `config.json` file: - -``` -"scss": { - "buildPath": "build/web/", - "files": [{ - "destination": "colors.scss", - "filter": "removePrivate", - "format": "scss/variables" - }] -} -``` - -The StyleDictionary will take care of filtering out proper design tokens from the source of truth: - -``` -{ - "color": { - "gray": { - "light" : { - "value": "#CCCCCC", - "group": "color", - "private": true - }, - "medium": { - "value": "#999999", - "group": "color" - }, - "dark" : { - "value": "#111111", - "group": "color" - } - }, - } -} -``` - -#### How does it work a custom filter? - -To declare a custom **filter**, you have to call the `registerFilter` method: - -``` -StyleDictionary.registerFilter({ - name: 'isTextTransform', - matcher: function(token) { - return token.attributes.category === 'font' && token.value.includes['lowercase', 'uppercase] - } -}); -``` - -You have to apply it in the `config.json` file: - -``` -"scss": { - "buildPath": "build/web/", - "files": [{ - "destination": "fonts.scss", - "filter": "isTextTransform", - "format": "scss/variables" - }] -} -``` - -The StyleDictionary will take care of filtering out proper design tokens from the source of truth: - -``` -{ - "fonts": { - "title-transform": { - "value": "uppercase", // included - "group": "font" - }, - "title-size": { - "value": "36px", // excluded - "group": "font" - } - } -} -``` - -More information can be found on the [documentation](https://amzn.github.io/style-dictionary/#/api?id=registerfilter). diff --git a/examples/advanced/custom-filters/build.js b/examples/advanced/custom-filters/build.js deleted file mode 100644 index a060de86f..000000000 --- a/examples/advanced/custom-filters/build.js +++ /dev/null @@ -1,27 +0,0 @@ -const StyleDictionary = require('../../../index'); - -console.log('Build started...'); -console.log('\n=============================================='); - - -// REGISTER THE CUSTOM FILTERS - -StyleDictionary.registerFilter({ - name: 'removeBigSpacing', - matcher: function(token) { - return token.group === 'spacing' && token.value < 0.5 - } -}); - -// APPLY THE CONFIGURATION -// IMPORTANT: the registration of custom transforms -// needs to be done _before_ applying the configuration -const StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/config.json'); - - -// FINALLY, BUILD ALL THE PLATFORMS -StyleDictionaryExtended.buildAllPlatforms(); - - -console.log('\n=============================================='); -console.log('\nBuild completed!'); diff --git a/examples/advanced/custom-filters/config.json b/examples/advanced/custom-filters/config.json deleted file mode 100644 index a6d7f396a..000000000 --- a/examples/advanced/custom-filters/config.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "source": ["tokens/**/*.json"], - "platforms": { - "web": { - "buildPath": "build/web/", - "files": [{ - "destination": "tokens.js", - "filter": "removeBigSpacing", - "format": "javascript/es6" - }] - }, - "scss": { - "buildPath": "build/web/", - "files": [{ - "destination": "tokens.scss", - "filter": "removeBigSpacing", - "format": "scss/variables" - }] - } - } -} diff --git a/examples/advanced/custom-filters/package.json b/examples/advanced/custom-filters/package.json deleted file mode 100644 index 28a191c6e..000000000 --- a/examples/advanced/custom-filters/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "style-dictionary-filters", - "version": "1.0.0", - "description": "", - "main": "build/index.js", - "files": [ - "build", - "properties" - ], - "scripts": { - "build": "node ./build.js", - "clean": "rm -rf build", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "Apache-2.0", - "devDependencies": { - "style-dictionary": "3.8.0" - } -} \ No newline at end of file diff --git a/examples/advanced/custom-filters/tokens/spacing.json b/examples/advanced/custom-filters/tokens/spacing.json deleted file mode 100644 index 1876a7ad7..000000000 --- a/examples/advanced/custom-filters/tokens/spacing.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "margin": { - "small" : { - "value": "0.15", - "group": "spacing" - }, - "medium": { - "value": "0.25", - "group": "spacing" - }, - "large" : { - "value": "0.6", - "group": "spacing" - }, - "extralarge" : { - "value": "1", - "group": "spacing" - } - } -} diff --git a/examples/advanced/custom-formats-with-templates/.gitignore b/examples/advanced/custom-formats-with-templates/.gitignore deleted file mode 100644 index 3e2e84b08..000000000 --- a/examples/advanced/custom-formats-with-templates/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -node_modules/ diff --git a/examples/advanced/custom-formats-with-templates/README.md b/examples/advanced/custom-formats-with-templates/README.md deleted file mode 100644 index 1ff963280..000000000 --- a/examples/advanced/custom-formats-with-templates/README.md +++ /dev/null @@ -1,56 +0,0 @@ -## Custom formats using templates - -This example shows how to generate design tokens files with custom formats using "custom" template files/engines. This is useful when you need to distribute your design tokens and integrate them with custom pipelines or scripts, that expect specific formats, or if you have any specific needs that are not covered out-of-the-box by Style Dictionary. - -**Notice**: before starting to dig into all the possible customisations that you can have, try the default settings offered by the library, look at the output files, and see if they can suit your needs. Probably they will do. If they don't, think how you want the output files generated, and see which one of the API methods you can use for that specific scope. - -#### Running the example - -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn* update the commands accordingly). - -At this point, if you want to build the tokens you can run `npm run build`. This command will generate the files in the `build` folder. - -#### How does it work - -The "build" command will run the custom script `build.js`, that contains three different custom templates, one for every platform declared in the `config.js` file. For example, this is the custom template declaration for the "android" platform: - -``` -StyleDictionary.registerFormat({ - name: 'custom/format/android-xml', - formatter: _.template(fs.readFileSync(__dirname + '/templates/android-xml.template')) -}); -``` - -As you can see, the `registerFormat` [API method](https://amzn.github.io/style-dictionary/#/api?id=registerformat) is invoked, passing a custom name for the format (you can choose whatever string you like) and a formatting function that returns the content to be saved to file. - -The format is then used in the `config.js` file and passed to a `file` declaration for a platform (look at the `config.js` file in the example to see how it is used). - -For the formatting function, it's possible to use any templating language (Lodash, Mustache, PUG, anything that can return a string). In the example, we have used three different languages to show the differences. - -#### What to look at - -Open the `config.js` file and see how for each platform the `files` declarations use custom formats: - -``` -"android": { - "transformGroup": "android", - "buildPath": "build/android/", - "files": [{ - "destination": "tokens.xml", - "format": "custom/format/android-xml" - },{ - "destination": "tokens_alt.xml", - "format": "custom/format/android-xml-alt" - }] -} -``` - -Now open the `build.js` script and look at how these custom formats are declared, using **different templating files/engines**. - -Finally, look at the different template files in the `templates` folder and see how they are built to generate custom file formats in output: - -* **web-scss.template**: this is a template that uses [Lodash](https://lodash.com/docs/4.17.10#template), and shows how you can create a custom format for Sass ".scss" files. The same approach can be used if you need other custom formats for the web (or other platforms too). -* **android-xml.template**: this template uses Lodash as well, and shows how to create a custom XML format for Android, that can be read as "resource file". This is one of the many possible formats for Android that you could create. -* **android-xml_alt.hbs**: this is an alternative example of custom XML format for Android, that uses [Handlebar](https://handlebarsjs.com) as templating language. -* **ios-plist.template**: this template uses Lodash as well, and shows how to create a custom PLIST format for iOS, that can be read as "resource file". This is one of the many possible formats for iOS that you could create. -* **ios-plist_alt.pug**: this is an alternative example of custom XML format for Android, that uses [Pug](https://pugjs.org/api/getting-started.html) as templating language. diff --git a/examples/advanced/custom-formats-with-templates/build.js b/examples/advanced/custom-formats-with-templates/build.js deleted file mode 100644 index 2a5d541e8..000000000 --- a/examples/advanced/custom-formats-with-templates/build.js +++ /dev/null @@ -1,69 +0,0 @@ -const StyleDictionary = require('style-dictionary').extend(__dirname + '/config.json'); -const fs = require('fs'); -const _ = require('lodash'); -const handlebars = require('handlebars'); -const pug = require('pug'); - - -console.log('Build started...'); -console.log('\n=============================================='); - - -// DECLARE CUSTOM FORMATS VIA CUSTOM TEMPLATE FILES (AND ENGINES) - - -// These formatting functions are using the Lodash "template" syntax - -StyleDictionary.registerFormat({ - name: 'custom/format/scss', - formatter: _.template(fs.readFileSync(__dirname + '/templates/web-scss.template')) -}); - -StyleDictionary.registerFormat({ - name: 'custom/format/ios-plist', - formatter: _.template(fs.readFileSync(__dirname + '/templates/ios-plist.template')) -}); - -StyleDictionary.registerFormat({ - name: 'custom/format/android-xml', - formatter: _.template(fs.readFileSync(__dirname + '/templates/android-xml.template')) -}); - - -// In this case we are using an alternative templating engine (Handlebars) -const templateCustomXml = handlebars.compile(fs.readFileSync(__dirname + '/templates/android-xml_alt.hbs', 'utf8')); - -StyleDictionary.registerFormat({ - name: 'custom/format/android-xml-alt', - formatter: function({dictionary, platform}) { - return templateCustomXml({ - // this is to show that the formatter function only takes a "dictionary" and "platform" parameters - // (and dictionary has "tokens" and "allTokens" attributes) - // and returns a string. for more details about the "formatter" function refer to the documentation - allTokens: dictionary.allTokens, - tokens: dictionary.tokens, - options: platform - }); - } -}); - - -// ... and here another templating engine (Pug) -const templateCustomPlist = pug.compileFile(__dirname + '/templates/ios-plist_alt.pug', { pretty: true }); - -StyleDictionary.registerFormat({ - name: 'custom/format/ios-plist-alt', - formatter: function({dictionary}) { - return templateCustomPlist({ - allTokens: dictionary.allTokens - }); - } -}); - - -// FINALLY, BUILD ALL THE PLATFORMS -StyleDictionary.buildAllPlatforms(); - - -console.log('\n=============================================='); -console.log('\nBuild completed!'); diff --git a/examples/advanced/custom-formats-with-templates/config.json b/examples/advanced/custom-formats-with-templates/config.json deleted file mode 100644 index b7e7c0698..000000000 --- a/examples/advanced/custom-formats-with-templates/config.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "source": ["properties/**/*.json"], - "platforms": { - "scss": { - "transformGroup": "web", - "buildPath": "build/web/", - "files": [{ - "destination": "tokens.scss", - "format": "custom/format/scss" - }] - }, - "android": { - "transformGroup": "android", - "buildPath": "build/android/", - "files": [{ - "destination": "tokens.xml", - "format": "custom/format/android-xml" - },{ - "destination": "tokens_alt.xml", - "format": "custom/format/android-xml-alt" - }] - }, - "ios": { - "transformGroup": "ios", - "buildPath": "build/ios/", - "files": [{ - "destination": "tokens.plist", - "format": "custom/format/ios-plist" - },{ - "destination": "tokens_alt.plist", - "format": "custom/format/ios-plist-alt" - }] - } - } -} diff --git a/examples/advanced/custom-formats-with-templates/package.json b/examples/advanced/custom-formats-with-templates/package.json deleted file mode 100644 index 202553fa6..000000000 --- a/examples/advanced/custom-formats-with-templates/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "style-dictionary-custom-formats-with-templates", - "version": "1.0.0", - "description": "", - "main": "build/index.js", - "files": [ - "build", - "properties" - ], - "scripts": { - "build": "node ./build.js", - "clean": "rm -rf build", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "Apache-2.0", - "devDependencies": { - "handlebars": "^4.7.7", - "lodash": "^4.17.21", - "pug": "^3.0.2", - "style-dictionary": "3.8.0" - } -} \ No newline at end of file diff --git a/examples/advanced/custom-formats-with-templates/properties/color/base.json b/examples/advanced/custom-formats-with-templates/properties/color/base.json deleted file mode 100644 index 02a99d700..000000000 --- a/examples/advanced/custom-formats-with-templates/properties/color/base.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "color": { - "base": { - "gray": { - "light" : { "value": "#CCCCCC" }, - "medium": { "value": "#999999" }, - "dark" : { "value": "#111111" } - }, - "red": { "value": "#FF0000" }, - "green": { "value": "#00FF00" } - } - } -} diff --git a/examples/advanced/custom-formats-with-templates/properties/color/font.json b/examples/advanced/custom-formats-with-templates/properties/color/font.json deleted file mode 100644 index df0b84832..000000000 --- a/examples/advanced/custom-formats-with-templates/properties/color/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "font": { - "base" : { "value": "{color.base.red.value}" }, - "secondary": { "value": "{color.base.green.value}" }, - "tertiary" : { "value": "{color.base.gray.light.value}" } - } - } -} diff --git a/examples/advanced/custom-formats-with-templates/properties/size/font.json b/examples/advanced/custom-formats-with-templates/properties/size/font.json deleted file mode 100644 index 24e7b8034..000000000 --- a/examples/advanced/custom-formats-with-templates/properties/size/font.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "size": { - "font": { - "small" : { - "value": "0.75", - "comment": "the small size of the font" - }, - "medium": { - "value": "1", - "comment": "the medium size of the font" - }, - "large" : { - "value": "2", - "comment": "the large size of the font" - }, - "base" : { - "value": "{size.font.medium.value}", - "comment": "the base size of the font" - } - } - } -} diff --git a/examples/advanced/custom-formats-with-templates/templates/android-xml.template b/examples/advanced/custom-formats-with-templates/templates/android-xml.template deleted file mode 100644 index f00a17f73..000000000 --- a/examples/advanced/custom-formats-with-templates/templates/android-xml.template +++ /dev/null @@ -1,30 +0,0 @@ -<% -var allTokens = _.each(allTokens, function(prop) { - if(prop.attributes.category === 'color') { - prop.tag = 'color'; - } else if(prop.attributes.category === 'size') { - prop.tag = 'dimen'; - } else if(prop.attributes.category === 'time' || prop.attributes.category === 'opacity' || prop.attributes.category === 'multiplier') { - prop.tag = 'double'; - } else if(prop.attributes.category === 'content') { - prop.tag = 'string'; - } else { - prop.tag = 'item'; - } -}); %> - -<% _.each(allTokens, function(prop) { - // Notice: this is an alternative way to use Lodash templating syntax, - // that uses string concatenation and the print() function to have - // more control over the indentation, whitespace, newlines, etc. - var output = ""; - output += "\t<" + prop.tag + " name=\"" + prop.name + "\">"; - output += prop.value; - output += ""; - if(prop.comment) { - output += ""; - } - output += "\n"; - print(output); -}); -%> diff --git a/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs b/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs deleted file mode 100644 index c2ebf22b9..000000000 --- a/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs +++ /dev/null @@ -1,4 +0,0 @@ - -{{#each allTokens}} -{{value}} -{{/each}} diff --git a/examples/advanced/custom-formats-with-templates/templates/ios-plist.template b/examples/advanced/custom-formats-with-templates/templates/ios-plist.template deleted file mode 100644 index e62f75ae6..000000000 --- a/examples/advanced/custom-formats-with-templates/templates/ios-plist.template +++ /dev/null @@ -1,24 +0,0 @@ - - - -<% -var allTokens = _.each(allTokens, function(prop) { - if(prop.type === 'color') { - prop.tag = 'string'; - } else if(prop.type === 'size') { - prop.tag = 'integer'; - } else if(prop.type === 'time' || prop.type === 'opacity') { - prop.tag = 'real'; - } else if(prop.type === 'content') { - prop.tag = 'string'; - } else { - prop.tag = 'string'; - } -}); -%> - - <% _.each(allTokens, function(prop) { - %><%= prop.name %><<%= prop.tag %>><%= prop.value %>><% if (prop.comment) { %><% } %> - <% }); %> - - \ No newline at end of file diff --git a/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug b/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug deleted file mode 100644 index f6cc4cf8a..000000000 --- a/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug +++ /dev/null @@ -1,24 +0,0 @@ - -each token in allTokens - case token.attributes.category - when 'color' - - var tag = 'string' - when 'size' - - var tag = 'integer' - when 'time' - - var tag = 'real' - when 'opacity' - - var tag = 'real' - when 'content' - - var tag = 'string' - default - - var tag = 'string' - key #{token.name} - dict - if token.comment - // #{token.comment} - if token.type - key type - string #{token.type} - key value - #{tag}(name=token.name) #{token.value} diff --git a/examples/advanced/custom-formats-with-templates/templates/web-scss.template b/examples/advanced/custom-formats-with-templates/templates/web-scss.template deleted file mode 100644 index 546acdb42..000000000 --- a/examples/advanced/custom-formats-with-templates/templates/web-scss.template +++ /dev/null @@ -1,3 +0,0 @@ -<% _.each(allTokens, function(prop) { -%>$<%= prop.name %>: <%= prop.value %>;<% if (prop.comment) { %> // <%= prop.comment %><% } %> -<% }); %> \ No newline at end of file diff --git a/examples/advanced/custom-parser/README.md b/examples/advanced/custom-parser/README.md index 150ab1032..79f952e7c 100644 --- a/examples/advanced/custom-parser/README.md +++ b/examples/advanced/custom-parser/README.md @@ -1,29 +1,30 @@ ## Custom Parsers -Style Dictionary 3.0 added the ability to define custom parsers for source files. Before 3.0, the source files for Style Dictionary had to be JSON, JSON5, or Node modules (unless you wanted to read and merge the data yourself outside of Style Dictionary). Now you can define custom parsers that run on certain files based on a file path pattern regular expression (similar to how Webpack loaders work). +Style Dictionary 3.0 added the ability to define custom parsers for source files. Before 3.0, the source files for Style Dictionary had to be JSON, JSON5, or Node modules (unless you wanted to read and merge the data yourself outside of Style Dictionary). Now you can define custom parsers that run on certain files based on a file path pattern regular expression (similar to how Webpack loaders work). Use cases include: - Using YAML instead of JSON, JSON5, or Node modules as the source language for Style Dictionary files - Adding custom metadata when source files are parsed - #### Running the example -First of all, set up the required dependencies running the command `npm ci` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). +First of all, set up the required dependencies running the command `npm ci` in your local CLI environment (if you prefer to use _yarn_, update the commands accordingly). -At this point, you can run `npm run build`. This command will generate output files in the `build` folder. Just to show how custom parsers work, this example only has 2 design tokens and outputs a single CSS variables file. +At this point, you can run `npm run build`. This command will generate output files in the `build` folder. Just to show how custom parsers work, this example only has 2 design tokens and outputs a single CSS variables file. #### How does it work You can define custom parsers in 2 ways: + 1. With the `.registerParser` method -1. Adding a `parsers` array to the Style Dictionary configuration +2. Adding a `hooks.parsers` array to the Style Dictionary configuration A parser is an object with a `pattern` attribute that is a regular expression, and a `parse` attribute that is a function. The `parse` function accepts `contents` and `filePath` as named arguments and should return a plain Javascript object. ```javascript { + name: 'json-parser', pattern: /\.json$/, parse: ({contents, filePath}) => { return JSON.parse(contents); @@ -31,26 +32,28 @@ A parser is an object with a `pattern` attribute that is a regular expression, a } ``` -Because parsers work on the source files for Style Dictionary, they need to be defined at or before the configuration is passed to Style Dictionary through the `.extend` method. +Because parsers work on the source files for Style Dictionary, they need to be defined at or before the configuration is passed to Style Dictionary through the `.extend` method. ```javascript -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; -const styleDictionary = StyleDictionary.extend({ +const sd = new StyleDictionary({ + parsers: ['json-parser'], source: [`tokens/**/*.json`], //.. }); // This won't work because Style Dictionary has already parsed the source files // in the .extend method -styleDictionary.registerParser({ +sd.registerParser({ + name: 'json-parser', pattern: /\.json$/, - parse: ({contents, filePath}) => { + parse: ({ contents, filePath }) => { return JSON.parse(contents); - } -}) + }, +}); ``` #### What to look at -* **sd.config.js** Has everything you need \ No newline at end of file +- **sd.config.js** Has everything you need diff --git a/examples/advanced/custom-parser/package.json b/examples/advanced/custom-parser/package.json index 4475aaba4..5623e3a7c 100644 --- a/examples/advanced/custom-parser/package.json +++ b/examples/advanced/custom-parser/package.json @@ -3,12 +3,13 @@ "version": "1.0.0", "description": "", "main": "index.js", + "type": "module", "scripts": { "build": "style-dictionary build --config ./sd.config.js" }, "author": "", "license": "Apache-2.0", "devDependencies": { - "style-dictionary": "3.8.0" + "style-dictionary": "4.0.0-prerelease.30" } -} \ No newline at end of file +} diff --git a/examples/advanced/custom-parser/sd.config.js b/examples/advanced/custom-parser/sd.config.js index afcd3dc99..0b102a608 100644 --- a/examples/advanced/custom-parser/sd.config.js +++ b/examples/advanced/custom-parser/sd.config.js @@ -1,9 +1,10 @@ -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; // You can use the .registerParser() method like this StyleDictionary.registerParser({ + name: 'json-parser', pattern: /\.json$/, - parse: ({contents, filePath}) => { + parser: ({ contents, filePath }) => { // Probably a good idea to wrap this in a try/catch block try { const object = JSON.parse(contents); @@ -13,15 +14,16 @@ StyleDictionary.registerParser({ // Here we are going to grab the filepath and turn it into a prefix. // tokens/color/core.json will become 'color-core'. We will append this // to all token names. - const pathParts = filePath.replace(__dirname + '/tokens/', '') - .replace('.json','') + const pathParts = filePath + .replace(import.meta.dirname + '/tokens/', '') + .replace('.json', '') .split('/') .join('-'); const output = {}; for (const key in object) { - if (object.hasOwnProperty(key)) { + if (Object.hasOwn(object, key)) { const element = object[key]; output[`${pathParts}-${key}`] = element; } @@ -31,43 +33,31 @@ StyleDictionary.registerParser({ } catch (error) { console.log(error); } - } + }, }); -// Or you can add parsers directly on the configuration object here like this: -// StyleDictionary.extend({ -// parsers: [{ -// pattern: /\.json$/, -// parse: ({contents, filePath}) => {} -// }], -// source: [`tokens/**/*.json`], -// platforms: { -// css: { -// transformGroup: 'css', -// buildPath: 'build/', -// files: [{ -// destination: 'variables.css', -// format: 'css/variables' -// }] -// } -// } -// }).buildAllPlatforms(); - -module.exports = { +export default { // Or you can add parsers directly on the configuration object here like this: - // parsers: [{ - // pattern: /\.json$/, - // parse: ({contents, filePath}) => {} - // }], + // hooks: { + // parsers: { + // 'json-parser': { + // pattern: /\.json$/, + // parse: ({contents, filePath}) => {} + // } + // } + // }, + parsers: ['json-parser'], source: [`tokens/**/*.json`], platforms: { css: { transformGroup: 'css', buildPath: 'build/', - files: [{ - destination: 'variables.css', - format: 'css/variables' - }] - } - } -} + files: [ + { + destination: 'variables.css', + format: 'css/variables', + }, + ], + }, + }, +}; diff --git a/examples/advanced/custom-parser/tokens/color/core.json b/examples/advanced/custom-parser/tokens/color/core.json index ec0599de5..c5c4d9717 100644 --- a/examples/advanced/custom-parser/tokens/color/core.json +++ b/examples/advanced/custom-parser/tokens/color/core.json @@ -1,4 +1,4 @@ { - "blue": { "value": "#0000ff" }, - "red": { "value": "#ff0000" } + "blue": { "value": "#0000ff", "type": "color" }, + "red": { "value": "#ff0000", "type": "color" } } diff --git a/examples/advanced/custom-transforms/README.md b/examples/advanced/custom-transforms/README.md index b766b8503..7d4a167e9 100644 --- a/examples/advanced/custom-transforms/README.md +++ b/examples/advanced/custom-transforms/README.md @@ -2,18 +2,18 @@ This example shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. -Transforms are functions that modify a design token (in a non-destructive way). The reason for *transforms* is that in this way each platform can consume the token in different ways (eg. changing *pixel* values to *pt* values for iOS, and *dp* or *sp* for Android). +Transforms are functions that modify a design token (in a non-destructive way). The reason for _transforms_ is that in this way each platform can consume the token in different ways (eg. changing _pixel_ values to _pt_ values for iOS, and _dp_ or _sp_ for Android). **Remember**: transforms are performed sequentially, hence the order you use transforms matters. -The need for custom transforms is that Style Dictionary expects the tokens to be declared according to certain criteria, to use the pre-defined transforms and formats/templates. For example, the *web* transformGroup consists of the *attribute/cti*, *name/cti/kebab*, *size/px* and *color/css* transforms. -The *size/px* adds 'px' to the end of the number, and is applied only if `token.attributes.category === 'size'`. This means that your token needs to be expressed without units, and be under the *'size'* "category. If you need a different logic or you want to organize your tokens differently, probably you can't use the out-of-the-box transformation groups, but you have to declare your custom ones. +The need for custom transforms is that Style Dictionary expects the tokens to be declared according to certain criteria, to use the pre-defined transforms and formats/templates. For example, the _web_ transformGroup consists of the _attribute/cti_, _name/kebab_, _size/px_ and _color/css_ transforms. +The _size/px_ adds 'px' to the end of the number, and is applied only if `token.attributes.category === 'size'`. This means that your token needs to be expressed without units, and be under the _'size'_ "category. If you need a different logic or you want to organize your tokens differently, probably you can't use the out-of-the-box transformation groups, but you have to declare your custom ones. -If [custom formats](../custom-formats-with-templates/) are the way to allow users to customize the format of the *output* of Style Dictionary, custom transforms are the way to allow them to customize both the *input* (the token names/values/attributes) and the *output* (the actual values expressed in the design tokens). For this reasons, custom transforms are probably one of the **most powerful features** of Style Dictionary: they make it extremely versatile, allowing limitless possibilities of extension and customization of the entire design token pipeline. +If [custom formats](../custom-formats-with-templates/) are the way to allow users to customize the format of the _output_ of Style Dictionary, custom transforms are the way to allow them to customize both the _input_ (the token names/values/attributes) and the _output_ (the actual values expressed in the design tokens). For this reasons, custom transforms are probably one of the **most powerful features** of Style Dictionary: they make it extremely versatile, allowing limitless possibilities of extension and customization of the entire design token pipeline. #### Running the example -First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn* update the commands accordingly). +First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use _yarn_ update the commands accordingly). At this point, if you want to build the tokens you can run `npm run build`. This command will generate the files in the `build` folder. @@ -21,16 +21,16 @@ At this point, if you want to build the tokens you can run `npm run build`. This To declare a custom **transform**, you have to call the `registerTransform` method: -``` +```js StyleDictionary.registerTransform({ name: 'ratio/%', type: 'value', - matcher: function(token) { - return token.group === 'ratio'; + filter: function (token) { + return token.group === 'ratio'; + }, + transform: function (token) { + return `${Math.floor(100 * token.value)}%`; }, - transformer: function(token) { - return `${Math.floor(100 * token.value)}%`; - } }); ``` @@ -75,16 +75,15 @@ in your code and look the array of transforms associated with the it, directly i Open the `config.json` file and see how for each platform there is a `transformGroup` declaration. In this specific example, all the transformGroups applied to the platforms are custom. -Now open a token file (eg. `tokens/colors|font|spacing.json`) to see how we have associated custom attributes to the tokens, to be used later in the matchers functions. See also how the values are unit-less, where the units are applied at build time accordingly to the destination platform. Compare the values in the input JSON files, and the values that appear in the files generated in `build`, and you will see where and how the transformations have been applied. +Now open a token file (eg. `tokens/colors|font|spacing.json`) to see how we have associated custom attributes to the tokens, to be used later in the filter functions. See also how the values are unit-less, where the units are applied at build time accordingly to the destination platform. Compare the values in the input JSON files, and the values that appear in the files generated in `build`, and you will see where and how the transformations have been applied. Now open the `build.js` script and look at how these custom transforms/transformGroups are declared and registered via the `registerTransform` and `registerTransform` API methods. We have added as many comments as possible to make the code clear and show the interesting parts of it. A few things to notice in the file: - the name of a custom "transform" can be the same as an existing pre-defined method; in that case, the pre-defined method is overwritten -- beyond the existing attributes, you can use custom attributes to create **matcher** functions, used to filter the tokens and apply the transform only to those that match the filter condition. -- if you don't specify a **matcher**, the transformation will be applied to all the tokens +- beyond the existing attributes, you can use custom attributes to create **filter** functions, used to filter the tokens and apply the transform only to those that match the filter condition. +- if you don't specify a **filter**, the transformation will be applied to all the tokens - the transformation can be applied not only to the **value** of a token, but also to its **name** (and also to its attributes) - **IMPORTANT**: the registration of custom transforms needs to be done _before_ applying the configuration (the methods needs to be already declared and registered in Style Dictionary to be used when extending it with the configuration). See the code in the `build.js` for more details. diff --git a/examples/advanced/custom-transforms/build.js b/examples/advanced/custom-transforms/build.js index 3801162ad..3009318af 100644 --- a/examples/advanced/custom-transforms/build.js +++ b/examples/advanced/custom-transforms/build.js @@ -1,70 +1,72 @@ -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); console.log('Build started...'); console.log('\n=============================================='); - // REGISTER THE CUSTOM TRANSFORMS StyleDictionary.registerTransform({ name: 'size/px', // notice: the name is an override of an existing predefined method (yes, you can do it) type: 'value', - matcher: function(token) { - // this is an example of a possible filter (based on the "cti" values) to show how a "matcher" works - return token.attributes.category === 'font' || token.attributes.category === 'margin'; + filter: function (token) { + // this is an example of a possible filter (based on the "cti" values) to show how a "filter" works + return token.type === 'fontSize' || token.type === 'dimension'; + }, + transform: function (token) { + return `${token.value}px`; }, - transformer: function(token) { - return `${token.value}px`; - } }); StyleDictionary.registerTransform({ name: 'ratio/%', type: 'value', - matcher: function(token) { - // here we are using a custom attribute, declared in the token, to match the values where apply the transform - return token.group === 'ratio'; + filter: function (token) { + // here we are using a custom attribute, declared in the token, to match the values where apply the transform + return token.type === 'ratio'; + }, + transform: function (token) { + return `${Math.floor(100 * token.value)}%`; }, - transformer: function(token) { - return `${Math.floor(100 * token.value)}%`; - } }); StyleDictionary.registerTransform({ name: 'hexRGB/hexARGB', type: 'value', - matcher: function(token) { - return token.group === 'color'; + filter: function (token) { + return token.type === 'color'; + }, + transform: function (token) { + // for sake of simplicity, in this example we assume colors are always in the format #xxxxxx + return token.value.replace(/^#/, '#FF'); }, - transformer: function(token) { - // for sake of simplicity, in this example we assume colors are always in the format #xxxxxx - return token.value.replace(/^#/,'#FF'); - } }); StyleDictionary.registerTransform({ - name: 'unitless/dp-sp', + name: 'unitless/sp', type: 'value', - matcher: function(token) { - return token.group === 'typography' || token.group === 'spacing'; + filter: function (token) { + return token.type === 'fontSize'; + }, + transform: function (token) { + // in Android font sizes are expressed in "sp" units + return `${token.value}sp`; }, - transformer: function(token) { - // in Android font sizes are expressed in "sp" units - let unit = (token.group === 'typography') ? 'sp' : 'dp'; - return `${token.value}${unit}`; - } }); -StyleDictionary.registerTransform({ // this is a silly example, to show how you can apply transform to names +StyleDictionary.registerTransform({ + // this is a silly example, to show how you can apply transform to names name: 'name/squiggle', type: 'name', - // notice: if you don't specify a matcher, the transformation will be applied to all the tokens - transformer: function(token) { - return token.path.join('~'); - } + // notice: if you don't specify a filter, the transformation will be applied to all the tokens + transform: function (token) { + return token.path.join('~'); + }, }); - // REGISTER THE CUSTOM TRANSFORM GROUPS // if you want to see what a pre-defined group contains, uncomment the next line: @@ -73,45 +75,43 @@ StyleDictionary.registerTransform({ // this is a silly example, to show how you StyleDictionary.registerTransformGroup({ name: 'custom/web', // notice: here the "size/px" transform is not the pre-defined one, but the custom one we have declared above - transforms: ['attribute/cti', 'name/cti/constant', 'size/px', 'color/css', 'time/seconds', 'ratio/%'] + transforms: ['attribute/cti', 'name/constant', 'size/px', 'color/css', 'time/seconds', 'ratio/%'], }); StyleDictionary.registerTransformGroup({ name: 'custom/scss', // this is to show one possibility for adding a few transforms to a pre-defined group // (however, we suggest to use the previous approach, which is more explicit and clear) - transforms: StyleDictionary.transformGroup['scss'].concat(['size/px', 'ratio/%']) + transforms: StyleDictionary.transformGroup['scss'].concat(['size/px', 'ratio/%']), }); StyleDictionary.registerTransformGroup({ name: 'custom/android', // as you can see, here we are completely ignoring the "attribute/cti" transform (it's totally possible), - // because we are relying on custom attributes for the matchers and the custom format for the output - transforms: ['name/squiggle', 'hexRGB/hexARGB', 'unitless/dp-sp'] + // because we are relying on custom attributes for the filters and the custom format for the output + transforms: ['name/squiggle', 'hexRGB/hexARGB', 'unitless/dp-sp'], }); - // REGISTER A CUSTOM FORMAT (to be used for this specific example) StyleDictionary.registerFormat({ name: 'custom/android/xml', - formatter: function({ dictionary }) { - return dictionary.allTokens.map(function(token) { - return `${token.value}`; - }).join('\n'); - } + format: function ({ dictionary }) { + return dictionary.allTokens + .map(function (token) { + return `${token.value}`; + }) + .join('\n'); + }, }); - // APPLY THE CONFIGURATION // IMPORTANT: the registration of custom transforms // needs to be done _before_ applying the configuration -const StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/config.json'); - +const sd = new StyleDictionary(__dirname + '/config.json'); // FINALLY, BUILD ALL THE PLATFORMS -StyleDictionaryExtended.buildAllPlatforms(); - +await sd.buildAllPlatforms(); console.log('\n=============================================='); console.log('\nBuild completed!'); diff --git a/examples/advanced/custom-transforms/package.json b/examples/advanced/custom-transforms/package.json index 1a282fd17..a62721147 100644 --- a/examples/advanced/custom-transforms/package.json +++ b/examples/advanced/custom-transforms/package.json @@ -2,6 +2,7 @@ "name": "style-dictionary-custom-transforms", "version": "1.0.0", "description": "", + "type": "module", "main": "build/index.js", "files": [ "build", @@ -15,6 +16,6 @@ "author": "", "license": "Apache-2.0", "devDependencies": { - "style-dictionary": "3.8.0" + "style-dictionary": "4.0.0-prerelease.30" } -} \ No newline at end of file +} diff --git a/examples/advanced/custom-transforms/tokens/button.json b/examples/advanced/custom-transforms/tokens/button.json index 76dbcdd4d..4e5d02f5c 100644 --- a/examples/advanced/custom-transforms/tokens/button.json +++ b/examples/advanced/custom-transforms/tokens/button.json @@ -1,12 +1,13 @@ { "button": { - "border" : { + "border": { "width": { - "value": "1" + "value": "1", + "type": "dimension" }, "radius": { "value": "0.01", - "group": "ratio" + "type": "ratio" } } } diff --git a/examples/advanced/custom-transforms/tokens/colors.json b/examples/advanced/custom-transforms/tokens/colors.json index 5610b0a0a..bdfea0220 100644 --- a/examples/advanced/custom-transforms/tokens/colors.json +++ b/examples/advanced/custom-transforms/tokens/colors.json @@ -2,26 +2,26 @@ "color": { "base": { "gray": { - "light" : { + "light": { "value": "#CCCCCC", - "group": "color" + "type": "color" }, "medium": { "value": "#999999", - "group": "color" + "type": "color" }, - "dark" : { + "dark": { "value": "#111111", - "group": "color" + "type": "color" } }, "red": { "value": "#FF0000", - "group": "color" + "type": "color" }, "green": { "value": "#00FF00", - "group": "color" + "type": "color" } } } diff --git a/examples/advanced/custom-transforms/tokens/font.json b/examples/advanced/custom-transforms/tokens/font.json index 34a084cde..86a15f1d1 100644 --- a/examples/advanced/custom-transforms/tokens/font.json +++ b/examples/advanced/custom-transforms/tokens/font.json @@ -1,20 +1,20 @@ { "font": { - "small" : { + "small": { "value": "0.75", - "group": "typography" + "type": "fontSize" }, "medium": { "value": "1.5", - "group": "typography" + "type": "fontSize" }, - "large" : { + "large": { "value": "2", - "group": "typography" + "type": "fontSize" }, - "base" : { + "base": { "value": "1", - "group": "typography" + "type": "fontSize" } } } diff --git a/examples/advanced/custom-transforms/tokens/spacing.json b/examples/advanced/custom-transforms/tokens/spacing.json index 652434111..f168e3798 100644 --- a/examples/advanced/custom-transforms/tokens/spacing.json +++ b/examples/advanced/custom-transforms/tokens/spacing.json @@ -1,16 +1,16 @@ { "margin": { - "small" : { + "small": { "value": "0.15", - "group": "spacing" + "group": "dimension" }, "medium": { "value": "0.25", - "group": "spacing" + "group": "dimension" }, - "large" : { + "large": { "value": "0.4", - "group": "spacing" + "group": "dimension" } } } diff --git a/examples/advanced/flutter/README.md b/examples/advanced/flutter/README.md index 0015fabb5..67801b912 100644 --- a/examples/advanced/flutter/README.md +++ b/examples/advanced/flutter/README.md @@ -1,3 +1,3 @@ # style_dictionary -A Flutter package project to show the usage of styled-dictionary's flutter support. \ No newline at end of file +A Flutter package project to show the usage of styled-dictionary's flutter support. diff --git a/examples/advanced/flutter/style_dictionary/config.json b/examples/advanced/flutter/style_dictionary/config.json index ab112957c..b1f53c61f 100644 --- a/examples/advanced/flutter/style_dictionary/config.json +++ b/examples/advanced/flutter/style_dictionary/config.json @@ -1,46 +1,46 @@ { - "source": [ - "properties/**/*.json" - ], - "platforms": { - "flutter": { - "transformGroup": "flutter", - "buildPath": "../lib/unique_file/", - "files": [ - { - "destination": "style_dictionary.dart", - "format": "flutter/class.dart", - "className": "StyleDictionary" - } - ] + "source": ["tokens/**/*.json"], + "platforms": { + "flutter": { + "transformGroup": "flutter", + "buildPath": "../lib/unique_file/", + "files": [ + { + "destination": "style_dictionary.dart", + "format": "flutter/class.dart", + "options": { + "className": "StyleDictionary" + } + } + ] + }, + "flutter-separate": { + "transformGroup": "flutter-separate", + "buildPath": "../lib/", + "files": [ + { + "destination": "style_dictionary_color.dart", + "format": "flutter/class.dart", + "options": { + "className": "StyleDictionaryColor", + "type": "color" + }, + "filter": { + "type": "color" + } }, - "flutter-separate": { - "transformGroup": "flutter-separate", - "buildPath": "../lib/", - "files": [ - { - "destination": "style_dictionary_color.dart", - "format": "flutter/class.dart", - "className": "StyleDictionaryColor", - "type": "color", - "filter": { - "attributes": { - "category": "color" - } - } - }, - { - "destination": "style_dictionary_sizes.dart", - "format": "flutter/class.dart", - "className": "StyleDictionarySize", - "type": "float", - "filter": { - "attributes": { - "category": "size" - } - } - } - ] + { + "destination": "style_dictionary_sizes.dart", + "format": "flutter/class.dart", + "options": { + "className": "StyleDictionarySize", + "type": "float" + }, + "filter": { + "type": "color" + } } + ] } -} \ No newline at end of file + } +} diff --git a/examples/advanced/flutter/style_dictionary/properties/color/background.json b/examples/advanced/flutter/style_dictionary/properties/color/background.json deleted file mode 100644 index e46810041..000000000 --- a/examples/advanced/flutter/style_dictionary/properties/color/background.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "background": { - "primary": { "value": "#ffffff" }, - "link": { "value": "#0366d6" }, - "inverse": { "value": "#111111" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/flutter/style_dictionary/properties/color/core.json b/examples/advanced/flutter/style_dictionary/properties/color/core.json deleted file mode 100644 index b94ef6833..000000000 --- a/examples/advanced/flutter/style_dictionary/properties/color/core.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "color": { - "core": { - "white": { "value": "#ffffff" }, - "black": { "value": "#111111" }, - "gray": { "value": "#dddddd" }, - "blue": { "value": "#0366d6" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/flutter/style_dictionary/properties/color/font.json b/examples/advanced/flutter/style_dictionary/properties/color/font.json deleted file mode 100644 index 296e619f0..000000000 --- a/examples/advanced/flutter/style_dictionary/properties/color/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "color": { - "font": { - "primary": { "value": "{color.core.black.value}" }, - "link": { "value": "{color.core.blue.value}" }, - "inverse": { "value": "{color.core.white.value}" } - } - } -} \ No newline at end of file diff --git a/examples/advanced/flutter/style_dictionary/properties/size/font.json b/examples/advanced/flutter/style_dictionary/properties/size/font.json deleted file mode 100644 index 650894ec9..000000000 --- a/examples/advanced/flutter/style_dictionary/properties/size/font.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "size": { - "font": { - "small": { "value": 0.75 }, - "medium": { "value": 1 }, - "large": { "value": 1.5 } - } - } -} \ No newline at end of file diff --git a/examples/advanced/flutter/style_dictionary/properties/size/padding.json b/examples/advanced/flutter/style_dictionary/properties/size/padding.json deleted file mode 100644 index 47692fdb1..000000000 --- a/examples/advanced/flutter/style_dictionary/properties/size/padding.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "size": { - "padding": { - "small": { "value": 0.5 }, - "medium": { "value": 1 }, - "large": { "value": 2 } - } - } -} \ No newline at end of file diff --git a/examples/advanced/flutter/style_dictionary/tokens/color/background.json b/examples/advanced/flutter/style_dictionary/tokens/color/background.json new file mode 100644 index 000000000..5fba977c4 --- /dev/null +++ b/examples/advanced/flutter/style_dictionary/tokens/color/background.json @@ -0,0 +1,9 @@ +{ + "color": { + "background": { + "primary": { "value": "#ffffff", "type": "color" }, + "link": { "value": "#0366d6", "type": "color" }, + "inverse": { "value": "#111111", "type": "color" } + } + } +} diff --git a/examples/advanced/flutter/style_dictionary/tokens/color/core.json b/examples/advanced/flutter/style_dictionary/tokens/color/core.json new file mode 100644 index 000000000..258aff469 --- /dev/null +++ b/examples/advanced/flutter/style_dictionary/tokens/color/core.json @@ -0,0 +1,10 @@ +{ + "color": { + "core": { + "white": { "value": "#ffffff", "type": "color" }, + "black": { "value": "#111111", "type": "color" }, + "gray": { "value": "#dddddd", "type": "color" }, + "blue": { "value": "#0366d6", "type": "color" } + } + } +} diff --git a/examples/advanced/flutter/style_dictionary/tokens/color/font.json b/examples/advanced/flutter/style_dictionary/tokens/color/font.json new file mode 100644 index 000000000..3ef4d379a --- /dev/null +++ b/examples/advanced/flutter/style_dictionary/tokens/color/font.json @@ -0,0 +1,9 @@ +{ + "color": { + "font": { + "primary": { "value": "{color.core.black.value}", "type": "color" }, + "link": { "value": "{color.core.blue.value}", "type": "color" }, + "inverse": { "value": "{color.core.white.value}", "type": "color" } + } + } +} diff --git a/examples/advanced/flutter/style_dictionary/tokens/size/font.json b/examples/advanced/flutter/style_dictionary/tokens/size/font.json new file mode 100644 index 000000000..3a7cd494c --- /dev/null +++ b/examples/advanced/flutter/style_dictionary/tokens/size/font.json @@ -0,0 +1,9 @@ +{ + "size": { + "font": { + "small": { "value": 0.75, "type": "dimension" }, + "medium": { "value": 1, "type": "dimension" }, + "large": { "value": 1.5, "type": "dimension" } + } + } +} diff --git a/examples/advanced/flutter/style_dictionary/tokens/size/padding.json b/examples/advanced/flutter/style_dictionary/tokens/size/padding.json new file mode 100644 index 000000000..49a4a17ea --- /dev/null +++ b/examples/advanced/flutter/style_dictionary/tokens/size/padding.json @@ -0,0 +1,9 @@ +{ + "size": { + "padding": { + "small": { "value": 0.5, "type": "dimension" }, + "medium": { "value": 1, "type": "dimension" }, + "large": { "value": 2, "type": "dimension" } + } + } +} diff --git a/examples/advanced/font-face-rules/README.md b/examples/advanced/font-face-rules/README.md index 6d2aad527..76233ea6f 100644 --- a/examples/advanced/font-face-rules/README.md +++ b/examples/advanced/font-face-rules/README.md @@ -5,11 +5,12 @@ To generate `@font-face` rules, we will need a few moving parts (described below ```css /** build/css/fonts.css */ @font-face { - font-family: "Roboto"; + font-family: 'Roboto'; font-style: normal; font-weight: 400; - src: url("../fonts/Roboto.woff2") format("woff2"), - url("../fonts/Roboto.woff") format("woff"); + src: + url('../fonts/Roboto.woff2') format('woff2'), + url('../fonts/Roboto.woff') format('woff'); font-display: fallback; } ``` @@ -17,11 +18,12 @@ To generate `@font-face` rules, we will need a few moving parts (described below ```scss // build/scss/_fonts.scss @font-face { - font-family: "Roboto"; + font-family: 'Roboto'; font-style: normal; font-weight: 400; - src: url("#{$font-path}/fonts/Roboto.woff2") format("woff2"), - url("#{$font-path}/fonts/Roboto.woff") format("woff"); + src: + url('#{$font-path}/fonts/Roboto.woff2') format('woff2'), + url('#{$font-path}/fonts/Roboto.woff') format('woff'); font-display: fallback; } ``` @@ -32,7 +34,7 @@ Set up the required dependencies by running the command `npm install` in your lo At this point, if you want to build the tokens you can run `npm run build`. This command will generate the files in the `build` folder. -Note, running this example will generate a "While building fonts.css, token collisions were found; output may be unexpected." warning. The warning is expected and can be ignored. +Note, running this example will generate a "While building fonts.css, token collisions were found; output may be unexpected. Ignore this warning if intentional." warning. The warning is expected and can be ignored. #### How does it work @@ -45,7 +47,8 @@ Note, running this example will generate a "While building fonts.css, token coll "": { "