From fbd0eb272a8182eb5a4f4bb2229da92f71ceb95a Mon Sep 17 00:00:00 2001 From: Dario Soller Date: Thu, 24 Oct 2024 23:32:31 +0200 Subject: [PATCH] feat: introduce and provide enum-like JS objects for most hardcoded config strings (#1367) --- .changeset/five-vans-whisper.md | 5 + README.md | 11 +- __integration__/android.test.js | 14 +- __integration__/async.test.js | 23 +- __integration__/compose.test.js | 7 +- __integration__/css.test.js | 15 +- __integration__/customFileHeader.test.js | 20 +- __integration__/customFormats.test.js | 7 +- __integration__/flutter.test.js | 16 +- __integration__/iOSObjectiveC.test.js | 20 +- __integration__/logging/config.test.js | 9 +- __integration__/logging/file.test.js | 122 +- __integration__/nameCollisions.test.js | 11 +- __integration__/objectValues.test.js | 32 +- __integration__/outputReferences.test.js | 34 +- __integration__/scss.test.js | 21 +- __integration__/showFileHeader.test.js | 16 +- __integration__/swift.test.js | 9 +- __integration__/w3c-forward-compat.test.js | 11 +- __perf_tests__/basic.test.js | 12 +- __tests__/StyleDictionary.test.js | 33 +- __tests__/__configs/test.js | 51 +- __tests__/buildAllPlatforms.test.js | 12 +- __tests__/buildPlatform.test.js | 18 +- .../createPropertyFormatter.test.js | 45 +- .../common/formatHelpers/fileHeader.test.js | 3 +- __tests__/common/transforms.test.js | 377 ++-- __tests__/exportPlatform.test.js | 72 +- .../formats/__snapshots__/all.test.snap.js | 1550 ++++++++--------- ...est.snap.js => javascriptEsm.test.snap.js} | 0 ...ap.js => javascriptEsmMinify.test.snap.js} | 0 __tests__/formats/all.test.js | 3 +- __tests__/formats/androidResources.test.js | 7 +- __tests__/formats/es6Constants.test.js | 9 +- ...s6Module.test.js => javascriptEsm.test.js} | 9 +- ...fy.test.js => javascriptEsmMinify.test.js} | 9 +- __tests__/formats/javascriptModule.test.js | 9 +- .../formats/javascriptModuleFlat.test.js | 9 +- __tests__/formats/javascriptObject.test.js | 9 +- __tests__/formats/javascriptUmd.test.js | 9 +- __tests__/formats/json.test.js | 9 +- __tests__/formats/jsonFlat.test.js | 7 +- __tests__/formats/jsonNested.test.js | 9 +- __tests__/formats/lessIcons.test.js | 9 +- __tests__/formats/lessVariables.test.js | 9 +- __tests__/formats/scssIcons.test.js | 9 +- __tests__/formats/scssMaps.test.js | 7 +- __tests__/formats/scssVariables.test.js | 9 +- __tests__/formats/stylusVariable.test.js | 9 +- __tests__/formats/swiftFile.test.js | 9 +- .../formats/typeScriptEs6Declarations.test.js | 9 +- .../typeScriptModuleDeclarations.test.js | 9 +- __tests__/register/overwrite.test.js | 26 +- __tests__/register/preprocessor.test.js | 3 +- __tests__/register/transform.test.js | 21 +- __tests__/register/transformGroup.test.js | 12 +- __tests__/transform/config.test.js | 15 +- __tests__/transform/object.test.js | 11 +- __tests__/transform/tokenSetup.test.js | 2 +- __tests__/transform/transformToken.test.js | 11 +- bin/style-dictionary.js | 7 +- docs/src/components/sd-playground.ts | 5 +- .../docs/examples/splitting-output-files.md | 10 +- .../docs/getting-started/installation.mdx | 5 +- .../docs/reference/Hooks/Formats/helpers.md | 7 +- .../docs/reference/Hooks/Formats/index.md | 6 +- .../reference/Hooks/Formats/predefined.md | 10 +- .../docs/reference/Hooks/Transforms/index.md | 2 +- .../docs/reference/Hooks/file-headers.md | 6 +- .../content/docs/reference/Hooks/filters.md | 6 +- .../docs/reference/Utils/format-helpers.md | 33 +- .../docs/reference/Utils/references.md | 28 +- docs/src/content/docs/reference/api.mdx | 77 +- docs/src/content/docs/reference/config.md | 2 +- docs/src/content/docs/reference/enums.md | 305 ++++ docs/src/content/docs/reference/logging.md | 26 +- docs/src/utils/rollup-bundle.ts | 70 +- docs/starlight-config.ts | 4 + examples/advanced/custom-parser/sd.config.js | 5 +- examples/advanced/custom-transforms/README.md | 2 +- examples/advanced/custom-transforms/build.js | 19 +- .../advanced/font-face-rules/sd.config.js | 3 +- examples/advanced/format-helpers/sd.config.js | 5 +- .../advanced/matching-build-files/config.js | 25 +- .../multi-brand-multi-platform/build.js | 17 +- .../config.js | 29 +- examples/advanced/tokens-deprecation/build.js | 3 +- .../transitive-transforms/sd.config.js | 21 +- .../variables-in-outputs/sd.config.js | 15 +- examples/advanced/yaml-tokens/sd.config.js | 5 +- lib/Register.js | 9 +- lib/StyleDictionary.js | 54 +- lib/cleanDir.js | 3 +- lib/cleanFile.js | 7 +- lib/common/actions.js | 12 +- .../formatHelpers/createPropertyFormatter.js | 45 +- lib/common/formatHelpers/fileHeader.js | 6 +- .../formatHelpers/formattedVariables.js | 4 +- lib/common/formats.js | 330 ++-- .../templates/scss/map-flat.template.js | 7 +- lib/common/transformGroups.js | 232 ++- lib/common/transforms.js | 222 +-- lib/enums/actions.js | 4 + lib/enums/commentPositions.js | 4 + lib/enums/commentStyles.js | 5 + lib/enums/fileHeaderCommentStyles.js | 5 + lib/enums/formats.js | 50 + lib/enums/index.js | 12 + lib/enums/logBrokenReferenceLevels.js | 4 + lib/enums/logVerbosityLevels.js | 5 + lib/enums/logWarningLevels.js | 5 + lib/enums/propertyFormatNames.js | 6 + lib/enums/transformGroups.js | 17 + lib/enums/transformTypes.js | 5 + lib/enums/transforms.js | 57 + lib/transform/config.js | 5 +- lib/transform/token.js | 13 +- package.json | 1 + types/Config.ts | 15 +- types/File.ts | 8 +- types/Format.ts | 4 +- types/Transform.ts | 10 +- 122 files changed, 2851 insertions(+), 1927 deletions(-) create mode 100644 .changeset/five-vans-whisper.md rename __tests__/formats/__snapshots__/{es6Module.test.snap.js => javascriptEsm.test.snap.js} (100%) rename __tests__/formats/__snapshots__/{es6ModuleMinify.test.snap.js => javascriptEsmMinify.test.snap.js} (100%) rename __tests__/formats/{es6Module.test.js => javascriptEsm.test.js} (95%) rename __tests__/formats/{es6ModuleMinify.test.js => javascriptEsmMinify.test.js} (87%) create mode 100644 docs/src/content/docs/reference/enums.md create mode 100644 lib/enums/actions.js create mode 100644 lib/enums/commentPositions.js create mode 100644 lib/enums/commentStyles.js create mode 100644 lib/enums/fileHeaderCommentStyles.js create mode 100644 lib/enums/formats.js create mode 100644 lib/enums/index.js create mode 100644 lib/enums/logBrokenReferenceLevels.js create mode 100644 lib/enums/logVerbosityLevels.js create mode 100644 lib/enums/logWarningLevels.js create mode 100644 lib/enums/propertyFormatNames.js create mode 100644 lib/enums/transformGroups.js create mode 100644 lib/enums/transformTypes.js create mode 100644 lib/enums/transforms.js diff --git a/.changeset/five-vans-whisper.md b/.changeset/five-vans-whisper.md new file mode 100644 index 000000000..aff460bb9 --- /dev/null +++ b/.changeset/five-vans-whisper.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Introduce a new entrypoint: `style-dictionary/enums` for most of the library's hard-coded string values. Most of these are built-in hooks names. This provides better type-safety for consumers as well as various maintainability related benefits for this library. [See documentation for more info](https://styledictionary.com/reference/enums). diff --git a/README.md b/README.md index 34ddc1b91..4a90df2be 100644 --- a/README.md +++ b/README.md @@ -91,16 +91,18 @@ 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 +import { formats, transformGroups } from 'style-dictionary/enums'; + const StyleDictionary = require('style-dictionary').extend({ source: ['tokens/**/*.json'], platforms: { scss: { - transformGroup: 'scss', + transformGroup: transformGroups.scss, buildPath: 'build/', files: [ { destination: 'variables.scss', - format: 'scss/variables', + format: formats.scssVariables, }, ], }, @@ -294,10 +296,11 @@ The style dictionary build system is made to be extended. We don't know exactly ```javascript const StyleDictionary = require('style-dictionary').extend('config.json'); +import { transforms, transformTypes } from 'style-dictionary/enums'; StyleDictionary.registerTransform({ - name: 'time/seconds', - type: 'value', + name: transforms.timeSeconds, + type: transformTypes.value, filter: function (token) { return token.type === 'time'; }, diff --git a/__integration__/android.test.js b/__integration__/android.test.js index 8c7154808..0d5c7ef70 100644 --- a/__integration__/android.test.js +++ b/__integration__/android.test.js @@ -16,6 +16,10 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from 'style-dictionary/enums'; + +const { androidResources } = formats; +const { android } = transformGroups; describe('integration', async () => { before(async () => { @@ -23,23 +27,23 @@ describe('integration', async () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { android: { - transformGroup: `android`, + transformGroup: android, buildPath, files: [ { destination: `resources.xml`, - format: `android/resources`, + format: androidResources, }, { destination: `resourcesWithReferences.xml`, - format: `android/resources`, + format: androidResources, options: { outputReferences: true, }, }, { destination: `colors.xml`, - format: `android/resources`, + format: androidResources, filter: { type: `color`, }, @@ -56,7 +60,7 @@ describe('integration', async () => { }); describe('android', async () => { - describe(`android/resources`, async () => { + describe(androidResources, async () => { it(`should match snapshot`, async () => { const output = fs.readFileSync(resolve(`${buildPath}resources.xml`), { encoding: 'UTF-8', diff --git a/__integration__/async.test.js b/__integration__/async.test.js index a21495931..cd5401048 100644 --- a/__integration__/async.test.js +++ b/__integration__/async.test.js @@ -17,11 +17,12 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { transforms, propertyFormatNames, transformTypes } from '../lib/enums/index.js'; const sleep = async (time) => { await new Promise((resolve) => setTimeout(resolve, time)); }; - +const { attributeCti, nameKebab, timeSeconds, htmlIcon, sizeRem, colorCss } = transforms; const textFile = resolve(`${buildPath}text.txt`); // Tests all hooks async, into a single config @@ -58,7 +59,7 @@ describe('integration', async function () { SDExtension.registerTransform({ name: 'foo-value-transform', - type: 'value', + type: transformTypes.value, filter: (token) => token.value === 'foo', transform: async () => { await sleep(10); @@ -74,7 +75,11 @@ describe('integration', async function () { return ( (await fileHeader({ file })) + ':root {\n' + - formattedVariables({ format: 'css', dictionary, outputReferences }) + + formattedVariables({ + format: propertyFormatNames.css, + dictionary, + outputReferences, + }) + '\n}\n' ); }, @@ -96,12 +101,12 @@ describe('integration', async function () { platforms: { css: { transforms: [ - 'attribute/cti', - 'name/kebab', - 'time/seconds', - 'html/icon', - 'size/rem', - 'color/css', + attributeCti, + nameKebab, + timeSeconds, + htmlIcon, + sizeRem, + colorCss, 'foo-value-transform', ], buildPath, diff --git a/__integration__/compose.test.js b/__integration__/compose.test.js index a5ccc55e6..b74d6af67 100644 --- a/__integration__/compose.test.js +++ b/__integration__/compose.test.js @@ -16,6 +16,9 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats } from '../lib/enums/index.js'; + +const { composeObject } = formats; describe('integration', async () => { before(async () => { @@ -28,7 +31,7 @@ describe('integration', async () => { files: [ { destination: 'StyleDictionary.kt', - format: 'compose/object', + format: composeObject, options: { className: 'StyleDictionary', packageName: 'com.example.tokens', @@ -36,7 +39,7 @@ describe('integration', async () => { }, { destination: 'StyleDictionaryWithReferences.kt', - format: 'compose/object', + format: composeObject, options: { outputReferences: true, className: 'StyleDictionary', diff --git a/__integration__/css.test.js b/__integration__/css.test.js index 0baeecc88..5ce757a2a 100644 --- a/__integration__/css.test.js +++ b/__integration__/css.test.js @@ -16,6 +16,9 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { cssVariables } = formats; describe('integration', async () => { before(async () => { @@ -33,19 +36,19 @@ describe('integration', async () => { }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, buildPath, files: [ { destination: 'variables.css', - format: 'css/variables', + format: cssVariables, options: { formatting: { indentation: ' ' }, }, }, { destination: 'variablesWithReferences.css', - format: 'css/variables', + format: cssVariables, options: { outputReferences: true, outputReferenceFallbacks: false, @@ -53,7 +56,7 @@ describe('integration', async () => { }, { destination: 'variablesWithReferenceFallbacks.css', - format: 'css/variables', + format: cssVariables, options: { outputReferences: true, outputReferenceFallbacks: true, @@ -61,7 +64,7 @@ describe('integration', async () => { }, { destination: 'variablesWithSelector.css', - format: 'css/variables', + format: cssVariables, options: { selector: '.test', }, @@ -78,7 +81,7 @@ describe('integration', async () => { }); describe('css', async () => { - describe('css/variables', async () => { + describe(cssVariables, async () => { it(`should match snapshot`, async () => { const output = fs.readFileSync(resolve(`${buildPath}variables.css`), { encoding: 'UTF-8', diff --git a/__integration__/customFileHeader.test.js b/__integration__/customFileHeader.test.js index 49a5df987..6bbd9b9d2 100644 --- a/__integration__/customFileHeader.test.js +++ b/__integration__/customFileHeader.test.js @@ -16,6 +16,10 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { cssVariables, javascriptModule } = formats; +const { css, js } = transformGroups; describe(`integration`, async () => { before(async () => { @@ -46,26 +50,26 @@ describe(`integration`, async () => { platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `registeredFileHeader.css`, - format: `css/variables`, + format: cssVariables, options: { fileHeader: `valid custom file headers test fileHeader`, }, }, { destination: `configFileHeader.css`, - format: `css/variables`, + format: cssVariables, options: { fileHeader: `configFileHeader`, }, }, { destination: `inlineFileHeader.css`, - format: `css/variables`, + format: cssVariables, options: { fileHeader: () => { return [`build version 1.0.0`]; @@ -75,7 +79,7 @@ describe(`integration`, async () => { ], }, js: { - transformGroup: `js`, + transformGroup: js, buildPath, options: { fileHeader: `configFileHeader`, @@ -83,18 +87,18 @@ describe(`integration`, async () => { files: [ { destination: `noOptions.js`, - format: `javascript/module`, + format: javascriptModule, }, { destination: `showFileHeader.js`, - format: `javascript/module`, + format: javascriptModule, options: { showFileHeader: false, }, }, { destination: `fileHeaderOverride.js`, - format: `javascript/module`, + format: javascriptModule, options: { fileHeader: () => [`Header overridden`], }, diff --git a/__integration__/customFormats.test.js b/__integration__/customFormats.test.js index b548e25c6..a86a2abc4 100644 --- a/__integration__/customFormats.test.js +++ b/__integration__/customFormats.test.js @@ -16,6 +16,9 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { transformGroups } from '../lib/enums/index.js'; + +const { js } = transformGroups; describe('integration', async () => { before(async () => { @@ -34,7 +37,7 @@ describe('integration', async () => { }, platforms: { inlineCustomFormats: { - transformGroup: 'js', + transformGroup: js, buildPath, options: { otherOption: `platform option`, @@ -59,7 +62,7 @@ describe('integration', async () => { ], }, customFormats: { - transformGroup: 'js', + transformGroup: js, buildPath, options: { otherOption: `platform option`, diff --git a/__integration__/flutter.test.js b/__integration__/flutter.test.js index 3394182f8..4e6c5a040 100644 --- a/__integration__/flutter.test.js +++ b/__integration__/flutter.test.js @@ -16,6 +16,10 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { flutterClassDart } = formats; +const { flutter, flutterSeparate } = transformGroups; describe('integration', async () => { before(async () => { @@ -23,19 +27,19 @@ describe('integration', async () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { flutter: { - transformGroup: `flutter`, + transformGroup: flutter, buildPath, files: [ { destination: 'style_dictionary.dart', - format: 'flutter/class.dart', + format: flutterClassDart, options: { className: 'StyleDictionary', }, }, { destination: 'style_dictionary_with_references.dart', - format: 'flutter/class.dart', + format: flutterClassDart, options: { outputReferences: true, className: 'StyleDictionary', @@ -44,12 +48,12 @@ describe('integration', async () => { ], }, flutter_separate: { - transformGroup: `flutter-separate`, + transformGroup: flutterSeparate, buildPath, files: [ { destination: 'style_dictionary_color.dart', - format: 'flutter/class.dart', + format: flutterClassDart, options: { className: 'StyleDictionaryColor', type: 'color', @@ -60,7 +64,7 @@ describe('integration', async () => { }, { destination: 'style_dictionary_sizes.dart', - format: 'flutter/class.dart', + format: flutterClassDart, options: { className: 'StyleDictionarySize', type: 'float', diff --git a/__integration__/iOSObjectiveC.test.js b/__integration__/iOSObjectiveC.test.js index 78e1c9fe8..13bb5cb4a 100644 --- a/__integration__/iOSObjectiveC.test.js +++ b/__integration__/iOSObjectiveC.test.js @@ -16,6 +16,10 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { iosColorsH, iosColorsM, iosMacros, iosSingletonH, iosSingletonM, iosStaticH, iosStaticM } = + formats; describe('integration', async () => { before(async () => { @@ -23,26 +27,26 @@ describe('integration', async () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { flutter: { - transformGroup: `ios`, + transformGroup: transformGroups.ios, buildPath, files: [ { destination: 'singleton.m', - format: 'ios/singleton.m', + format: iosSingletonM, options: { className: 'StyleDictionary', }, }, { destination: 'singleton.h', - format: 'ios/singleton.h', + format: iosSingletonH, options: { className: 'StyleDictionary', }, }, { destination: 'color.h', - format: 'ios/colors.h', + format: iosColorsH, options: { className: 'StyleDictionaryColor', type: 'StyleDictionaryColorName', @@ -51,7 +55,7 @@ describe('integration', async () => { }, { destination: 'color.m', - format: 'ios/colors.m', + format: iosColorsM, options: { className: 'StyleDictionaryColor', type: 'StyleDictionaryColorName', @@ -60,11 +64,11 @@ describe('integration', async () => { }, { destination: 'macros.h', - format: 'ios/macros', + format: iosMacros, }, { destination: 'static.h', - format: 'ios/static.h', + format: iosStaticH, options: { className: 'StyleDictionaryStatic', type: 'CGFloat', @@ -73,7 +77,7 @@ describe('integration', async () => { }, { destination: 'static.m', - format: 'ios/static.m', + format: iosStaticM, options: { className: 'StyleDictionaryStatic', type: 'CGFloat', diff --git a/__integration__/logging/config.test.js b/__integration__/logging/config.test.js index cbe8ca040..2556bb3f7 100644 --- a/__integration__/logging/config.test.js +++ b/__integration__/logging/config.test.js @@ -15,6 +15,9 @@ import { restore, stubMethod } from 'hanbi'; import StyleDictionary from 'style-dictionary'; import { buildPath, cleanConsoleOutput } from '../_constants.js'; import { clearOutput } from '../../__tests__/__helpers.js'; +import { logWarningLevels, logVerbosityLevels } from '../../lib/enums/index.js'; + +const { error: errorLog, disabled } = logWarningLevels; /** * These integration tests will verify the behavior and logging at the *config* @@ -54,7 +57,7 @@ describe(`integration >`, () => { it(`should not log anything if the log verbosity is set to silent`, async () => { const sd = new StyleDictionary({ log: { - verbosity: 'silent', + verbosity: logVerbosityLevels.silent, }, source: [ // including a specific file twice will throw value collision warnings @@ -70,7 +73,7 @@ describe(`integration >`, () => { it(`should not log anything if the log warnings is set to disabled`, async () => { const sd = new StyleDictionary({ log: { - warnings: 'disabled', + warnings: disabled, }, source: [ // including a specific file twice will throw value collision warnings @@ -86,7 +89,7 @@ describe(`integration >`, () => { it(`should not show warnings if given higher log level`, async () => { const sd = new StyleDictionary( { - log: { warnings: `error` }, + log: { warnings: errorLog }, source: [ // including a specific file twice will throw value collision warnings `__integration__/tokens/size/padding.json`, diff --git a/__integration__/logging/file.test.js b/__integration__/logging/file.test.js index 99a47bd2c..59f3a21fb 100644 --- a/__integration__/logging/file.test.js +++ b/__integration__/logging/file.test.js @@ -15,6 +15,20 @@ import { restore, stubMethod } from 'hanbi'; import StyleDictionary from 'style-dictionary'; import { buildPath, cleanConsoleOutput } from '../_constants.js'; import { clearOutput } from '../../__tests__/__helpers.js'; +import { + formats, + logWarningLevels, + logVerbosityLevels, + transforms, + transformGroups, +} from '../../lib/enums/index.js'; + +const { silent, verbose } = logVerbosityLevels; +const { error: errorLog, disabled } = logWarningLevels; +const { attributeCti } = transforms; +const { cssVariables } = formats; +const { css } = transformGroups; + /** * The last and final level of logging: file. * These logs happen when a file is being built and will notify the user @@ -40,11 +54,11 @@ describe(`integration`, () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, files: [ { destination: `empty.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `foo`, }, ], @@ -60,15 +74,15 @@ describe(`integration`, () => { it(`should not warn user about empty tokens with silent log verbosity`, async () => { const sd = new StyleDictionary({ - log: { verbosity: 'silent' }, + log: { verbosity: silent }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, files: [ { destination: `empty.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `foo`, }, ], @@ -82,15 +96,15 @@ describe(`integration`, () => { it(`should not warn user about empty tokens with silent log verbosity`, async () => { const sd = new StyleDictionary({ - log: { warnings: 'disabled' }, + log: { warnings: disabled }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, files: [ { destination: `empty.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `foo`, }, ], @@ -105,15 +119,15 @@ describe(`integration`, () => { it(`should not warn user about empty tokens with log level set to error`, async () => { const sd = new StyleDictionary({ - log: { warnings: 'error' }, + log: { warnings: errorLog }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, files: [ { destination: `empty.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `foo`, }, ], @@ -131,12 +145,12 @@ describe(`integration`, () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - log: { warnings: 'error' }, - transformGroup: `css`, + log: { warnings: errorLog }, + transformGroup: css, files: [ { destination: `empty.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `foo`, }, ], @@ -157,12 +171,12 @@ describe(`integration`, () => { platforms: { css: { // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -177,17 +191,17 @@ describe(`integration`, () => { it(`should not warn user of name collisions with log verbosity silent`, async () => { const sd = new StyleDictionary({ - log: { verbosity: 'silent' }, + log: { verbosity: silent }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -200,17 +214,17 @@ describe(`integration`, () => { it(`should not warn user of name collisions with log verbosity silent`, async () => { const sd = new StyleDictionary({ - log: { warnings: 'disabled' }, + log: { warnings: disabled }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -224,17 +238,17 @@ describe(`integration`, () => { it(`should throw a brief error of name collisions with log level set to error`, async () => { const sd = new StyleDictionary({ - log: { warnings: `error` }, + log: { warnings: errorLog }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -255,14 +269,14 @@ describe(`integration`, () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - log: { warnings: `error` }, + log: { warnings: errorLog }, // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -281,17 +295,17 @@ describe(`integration`, () => { it(`should warn user of name collisions with a detailed message through "verbose" verbosity`, async () => { const sd = new StyleDictionary({ - log: { verbosity: 'verbose' }, + log: { verbosity: verbose }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -306,17 +320,17 @@ describe(`integration`, () => { 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' }, + log: { warnings: errorLog, verbosity: verbose }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { // no name transform means there will be name collisions - transforms: [`attribute/cti`], + transforms: [attributeCti], buildPath, files: [ { destination: `nameCollisions.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, ], @@ -339,12 +353,12 @@ describe(`integration`, () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, @@ -364,16 +378,16 @@ describe(`integration`, () => { it(`should not warn user of filtered references with log verbosity silent`, async () => { const sd = new StyleDictionary({ - log: { verbosity: 'silent' }, + log: { verbosity: silent }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, @@ -391,16 +405,16 @@ describe(`integration`, () => { it(`should not warn user of filtered references with log verbosity silent`, async () => { const sd = new StyleDictionary({ - log: { warnings: 'disabled' }, + log: { warnings: disabled }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, @@ -419,16 +433,16 @@ describe(`integration`, () => { it(`should throw a brief error of filtered references with log level set to error`, async () => { const sd = new StyleDictionary({ - log: { warnings: `error` }, + log: { warnings: errorLog }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, @@ -455,13 +469,13 @@ describe(`integration`, () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - log: { warnings: `error` }, - transformGroup: `css`, + log: { warnings: errorLog }, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, @@ -485,16 +499,16 @@ describe(`integration`, () => { it(`should warn user of filtered references with a detailed message through "verbose" verbosity`, async () => { const sd = new StyleDictionary({ - log: { verbosity: 'verbose' }, + log: { verbosity: verbose }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, @@ -514,16 +528,16 @@ describe(`integration`, () => { 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' }, + log: { warnings: errorLog, verbosity: verbose }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `css`, + transformGroup: css, buildPath, files: [ { destination: `filteredReferences.css`, - format: `css/variables`, + format: cssVariables, options: { outputReferences: true, }, diff --git a/__integration__/nameCollisions.test.js b/__integration__/nameCollisions.test.js index 428686d9f..fec1fda7b 100644 --- a/__integration__/nameCollisions.test.js +++ b/__integration__/nameCollisions.test.js @@ -15,6 +15,9 @@ import StyleDictionary from 'style-dictionary'; import { stubMethod, restore } from 'hanbi'; import { buildPath, cleanConsoleOutput } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, logVerbosityLevels } from '../lib/enums/index.js'; + +const { cssVariables, jsonNested } = formats; const tokens = { color: { @@ -48,7 +51,7 @@ describe('integration', async () => { files: [ { destination: 'variables.css', - format: 'css/variables', + format: cssVariables, }, ], }, @@ -63,14 +66,14 @@ describe('integration', async () => { // we are only testing name collision warnings options so we don't need // the full source. tokens, - log: { verbosity: 'verbose' }, + log: { verbosity: logVerbosityLevels.verbose }, platforms: { web: { buildPath, files: [ { destination: 'variables.css', - format: 'css/variables', + format: cssVariables, }, ], }, @@ -91,7 +94,7 @@ describe('integration', async () => { files: [ { destination: 'tokens.json', - format: 'json/nested', + format: jsonNested, }, ], }, diff --git a/__integration__/objectValues.test.js b/__integration__/objectValues.test.js index 6005b9989..05b60d123 100644 --- a/__integration__/objectValues.test.js +++ b/__integration__/objectValues.test.js @@ -17,6 +17,10 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformTypes } from '../lib/enums/index.js'; + +const { cssVariables, scssVariables } = formats; +const { value: transformTypeValue } = transformTypes; describe('integration', async () => { before(async () => { @@ -81,7 +85,7 @@ describe('integration', async () => { hooks: { transforms: { hsl: { - type: 'value', + type: transformTypeValue, transitive: true, filter: (token) => token.original.value.h, transform: (token) => { @@ -89,7 +93,7 @@ describe('integration', async () => { }, }, hslToHex: { - type: 'value', + type: transformTypeValue, transitive: true, filter: (token) => token.original.value.h, transform: (token) => { @@ -109,12 +113,12 @@ describe('integration', async () => { files: [ { destination: `hsl.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, }, { destination: `hslWithReferences.css`, - format: `css/variables`, + format: cssVariables, filter: (token) => token.type === `color`, options, }, @@ -129,12 +133,12 @@ describe('integration', async () => { files: [ { destination: 'hex.css', - format: 'css/variables', + format: cssVariables, filter: (token) => token.type === `color`, }, { destination: 'hexWithReferences.css', - format: 'css/variables', + format: cssVariables, filter: (token) => token.type === `color`, options, }, @@ -149,12 +153,12 @@ describe('integration', async () => { files: [ { destination: 'border.css', - format: 'css/variables', + format: cssVariables, filter: (token) => token.type === `border`, }, { destination: 'borderWithReferences.css', - format: 'css/variables', + format: cssVariables, filter: (token) => token.type === `border`, options, }, @@ -166,12 +170,12 @@ describe('integration', async () => { files: [ { destination: 'shadow.css', - format: 'css/variables', + format: cssVariables, filter: (token) => token.type === `shadow`, }, { destination: 'shadowWithReferences.css', - format: 'css/variables', + format: cssVariables, filter: (token) => token.type === `shadow`, options, }, @@ -184,12 +188,12 @@ describe('integration', async () => { files: [ { destination: 'border.scss', - format: 'scss/variables', + format: scssVariables, filter: (token) => token.type === `border`, }, { destination: 'borderWithReferences.scss', - format: 'scss/variables', + format: scssVariables, filter: (token) => token.type === `border`, options, }, @@ -205,7 +209,7 @@ describe('integration', async () => { }); describe('object values', async () => { - describe('css/variables', async () => { + describe(cssVariables, async () => { describe(`hsl syntax`, async () => { it(`should match snapshot`, async () => { const output = fs.readFileSync(resolve(`${buildPath}hsl.css`), { @@ -277,7 +281,7 @@ describe('integration', async () => { }); }); - describe('scss/variables', async () => { + describe(scssVariables, async () => { it(`should match snapshot`, async () => { const output = fs.readFileSync(resolve(`${buildPath}border.scss`), { encoding: 'UTF-8', diff --git a/__integration__/outputReferences.test.js b/__integration__/outputReferences.test.js index b6c53f43e..6345a2ad0 100644 --- a/__integration__/outputReferences.test.js +++ b/__integration__/outputReferences.test.js @@ -19,6 +19,16 @@ import { resolve } from '../lib/resolve.js'; import { clearOutput } from '../__tests__/__helpers.js'; import { outputReferencesFilter } from '../lib/utils/references/outputReferencesFilter.js'; import { outputReferencesTransformed } from '../lib/utils/index.js'; +import { + logVerbosityLevels, + formats, + transformGroups, + transformTypes, +} from '../lib/enums/index.js'; + +const { cssVariables } = formats; +const { css } = transformGroups; +const { verbose } = logVerbosityLevels; describe('integration', async () => { let stub; @@ -48,7 +58,7 @@ describe('integration', async () => { hooks: { transforms: { 'rgb-in-rgba': { - type: 'value', + type: transformTypes.value, transitive: true, filter: (token) => token.type === 'color', // quite naive transform to support rgb inside rgba @@ -70,7 +80,7 @@ describe('integration', async () => { files: [ { destination: 'transformedFilteredVariables.css', - format: 'css/variables', + format: cssVariables, options: { outputReferences: outputReferencesTransformed, }, @@ -138,12 +148,12 @@ describe('integration', async () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: 'css', + transformGroup: css, buildPath, files: [ { destination: 'filteredVariables.css', - format: 'css/variables', + format: cssVariables, // filter tokens and use outputReferences // Style Dictionary should build this file ok // but warn the user @@ -164,16 +174,16 @@ describe('integration', async () => { const sd = new StyleDictionary({ // we are only testing showFileHeader options so we don't need // the full source. - log: { verbosity: 'verbose' }, + log: { verbosity: verbose }, source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: 'css', + transformGroup: css, buildPath, files: [ { destination: 'filteredVariables.css', - format: 'css/variables', + format: cssVariables, // filter tokens and use outputReferences // Style Dictionary should build this file ok // but warn the user @@ -194,18 +204,18 @@ describe('integration', async () => { 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' }, + 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', + transformGroup: css, buildPath, files: [ { destination: 'filteredVariables.css', - format: 'css/variables', + format: cssVariables, // filter tokens and use outputReferences // Style Dictionary should build this file ok // but warn the user @@ -236,12 +246,12 @@ describe('integration', async () => { }, platforms: { css: { - transformGroup: 'css', + transformGroup: css, buildPath, files: [ { destination: 'dtcgOutputRef.css', - format: 'css/variables', + format: cssVariables, options: { outputReferences: true, usesDtcg: true, diff --git a/__integration__/scss.test.js b/__integration__/scss.test.js index 90924704b..5dd87ec4a 100644 --- a/__integration__/scss.test.js +++ b/__integration__/scss.test.js @@ -17,6 +17,9 @@ import { compileString } from 'sass'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { scssVariables, scssMapFlat, scssMapDeep } = formats; describe(`integration`, async () => { before(async () => { @@ -24,30 +27,30 @@ describe(`integration`, async () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { css: { - transformGroup: `scss`, + transformGroup: transformGroups.scss, buildPath, files: [ { destination: `variables.scss`, - format: `scss/variables`, + format: scssVariables, }, { destination: `variables-themeable.scss`, - format: `scss/variables`, + format: scssVariables, options: { themeable: true, }, }, { destination: `variables-with-references.scss`, - format: `scss/variables`, + format: scssVariables, options: { outputReferences: true, }, }, { destination: `filtered-variables-with-references.scss`, - format: `scss/variables`, + format: scssVariables, filter: (token) => token.path[1] === 'background', options: { outputReferences: true, @@ -55,21 +58,21 @@ describe(`integration`, async () => { }, { destination: `map-flat.scss`, - format: `scss/map-flat`, + format: scssMapFlat, options: { mapName: 'design-system-tokens', }, }, { destination: `map-deep.scss`, - format: `scss/map-deep`, + format: scssMapDeep, options: { mapName: 'design-system-tokens', }, }, { destination: `map-deep-with-references.scss`, - format: `scss/map-deep`, + format: scssMapDeep, options: { mapName: 'design-system-tokens', outputReferences: true, @@ -77,7 +80,7 @@ describe(`integration`, async () => { }, { destination: `map-deep-not-themeable.scss`, - format: `scss/map-deep`, + format: scssMapDeep, options: { mapName: 'design-system-tokens', themeable: false, diff --git a/__integration__/showFileHeader.test.js b/__integration__/showFileHeader.test.js index a571c363b..ac3fd58fd 100644 --- a/__integration__/showFileHeader.test.js +++ b/__integration__/showFileHeader.test.js @@ -16,6 +16,10 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { cssVariables } = formats; +const { css } = transformGroups; describe('integration', async () => { before(async () => { @@ -25,16 +29,16 @@ describe('integration', async () => { source: [`__integration__/tokens/size/padding.json`], platforms: { css: { - transformGroup: 'css', + transformGroup: css, buildPath, files: [ { destination: 'platform-none-file-none.css', - format: 'css/variables', + format: cssVariables, }, { destination: 'platform-none-file-false.css', - format: 'css/variables', + format: cssVariables, options: { showFileHeader: false, }, @@ -42,7 +46,7 @@ describe('integration', async () => { ], }, fileHeader: { - transformGroup: 'css', + transformGroup: css, buildPath, options: { showFileHeader: false, @@ -50,11 +54,11 @@ describe('integration', async () => { files: [ { destination: 'platform-false-file-none.css', - format: 'css/variables', + format: cssVariables, }, { destination: 'platform-false-file-true.css', - format: 'css/variables', + format: cssVariables, options: { showFileHeader: true, }, diff --git a/__integration__/swift.test.js b/__integration__/swift.test.js index 7095002f6..decc1c77b 100644 --- a/__integration__/swift.test.js +++ b/__integration__/swift.test.js @@ -16,6 +16,9 @@ import { fs } from 'style-dictionary/fs'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { iosSwiftClassSwift } = formats; describe('integration', async () => { before(async () => { @@ -23,19 +26,19 @@ describe('integration', async () => { source: [`__integration__/tokens/**/[!_]*.json?(c)`], platforms: { flutter: { - transformGroup: `ios-swift`, + transformGroup: transformGroups.iosSwift, buildPath, files: [ { destination: 'style_dictionary.swift', - format: 'ios-swift/class.swift', + format: iosSwiftClassSwift, options: { className: 'StyleDictionary', }, }, { destination: 'style_dictionary_with_references.swift', - format: 'ios-swift/class.swift', + format: iosSwiftClassSwift, options: { className: 'StyleDictionary', outputReferences: true, diff --git a/__integration__/w3c-forward-compat.test.js b/__integration__/w3c-forward-compat.test.js index 802d657b4..e5b53ad38 100644 --- a/__integration__/w3c-forward-compat.test.js +++ b/__integration__/w3c-forward-compat.test.js @@ -17,6 +17,9 @@ import Color from 'tinycolor2'; import { resolve } from '../lib/resolve.js'; import { buildPath } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transforms, transformTypes } from '../lib/enums/index.js'; + +const { value } = transformTypes; describe('integration', async () => { before(async () => { @@ -46,14 +49,14 @@ describe('integration', async () => { hooks: { transforms: { 'custom/css/color': { - type: 'value', + type: value, filter: (token) => token.$type === 'color', transform: (token) => { return Color(sd.usesDtcg ? token.$value : token.value).toRgbString(); }, }, 'custom/add/px': { - type: 'value', + type: value, filter: (token) => token.$type === 'dimension', transform: (token) => { return `${sd.usesDtcg ? token.$value : token.value}px`; @@ -63,12 +66,12 @@ describe('integration', async () => { }, platforms: { css: { - transforms: ['name/kebab', 'custom/css/color', 'custom/add/px'], + transforms: [transforms.nameKebab, 'custom/css/color', 'custom/add/px'], buildPath, files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, }, ], }, diff --git a/__perf_tests__/basic.test.js b/__perf_tests__/basic.test.js index 644c753df..decf746da 100644 --- a/__perf_tests__/basic.test.js +++ b/__perf_tests__/basic.test.js @@ -14,6 +14,10 @@ import { expect } from 'chai'; import StyleDictionary from 'style-dictionary'; import { buildPath } from '../__integration__/_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { cssVariables } = formats; +const { css } = transformGroups; /** * Utility to programmatically generate large sets of tokens @@ -92,12 +96,12 @@ describe('cliBuildWithJsConfig', () => { }, platforms: { css: { - transformGroup: 'css', + transformGroup: css, buildPath, files: [ { destination: 'variables.css', - format: 'css/variables', + format: cssVariables, }, ], }, @@ -128,12 +132,12 @@ describe('cliBuildWithJsConfig', () => { }, platforms: { css: { - transformGroup: 'css', + transformGroup: css, buildPath, files: [ { destination: 'variables.css', - format: 'css/variables', + format: cssVariables, }, ], }, diff --git a/__tests__/StyleDictionary.test.js b/__tests__/StyleDictionary.test.js index f5c6033a7..8da843b22 100644 --- a/__tests__/StyleDictionary.test.js +++ b/__tests__/StyleDictionary.test.js @@ -21,6 +21,17 @@ import { convertTokenData } from '../lib/utils/convertTokenData.js'; import { stripMeta } from '../lib/utils/stripMeta.js'; import formats from '../lib/common/formats.js'; import { restore, stubMethod } from 'hanbi'; +import { + logWarningLevels, + logVerbosityLevels, + logBrokenReferenceLevels, + formats as fileFormats, + transformGroups, +} from '../lib/enums/index.js'; + +const { console: logToConsole } = logBrokenReferenceLevels; +const { silent, verbose } = logVerbosityLevels; +const { error: errorLog, warn } = logWarningLevels; function traverseObj(obj, fn) { for (let key in obj) { @@ -276,7 +287,7 @@ describe('StyleDictionary class', () => { const StyleDictionaryExtended = new StyleDictionary({ include: ['__tests__/__tokens/paddings.json'], source: ['__tests__/__tokens/paddings.json'], - log: 'error', + log: errorLog, }); const output = fileToJSON('__tests__/__tokens/paddings.json'); traverseObj(output, (obj) => { @@ -293,7 +304,7 @@ describe('StyleDictionary class', () => { const sd = new StyleDictionary( { source: ['__tests__/__tokens/paddings.json', '__tests__/__tokens/_paddings.json'], - log: { warnings: 'error', verbosity: 'verbose' }, + log: { warnings: errorLog, verbosity: verbose }, }, { init: false }, ); @@ -310,7 +321,7 @@ describe('StyleDictionary class', () => { const sd = new StyleDictionary( { source: ['__tests__/__tokens/paddings.json', '__tests__/__tokens/_paddings.json'], - log: { warnings: 'error' }, + log: { warnings: errorLog }, }, { init: false }, ); @@ -327,7 +338,7 @@ describe('StyleDictionary class', () => { const sd = new StyleDictionary( { source: ['__tests__/__tokens/paddings.json', '__tests__/__tokens/paddings.json'], - log: 'warn', + log: warn, }, { init: false }, ); @@ -387,7 +398,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. const sd = new StyleDictionary({ log: { errors: { - brokenReferences: 'console', + brokenReferences: logToConsole, }, }, tokens: { @@ -413,9 +424,9 @@ Refer to: https://styledictionary.com/reference/logging/ const stub = stubMethod(console, 'error'); const sd = new StyleDictionary({ log: { - verbosity: 'silent', + verbosity: silent, errors: { - brokenReferences: 'console', + brokenReferences: logToConsole, }, }, tokens: { @@ -437,7 +448,7 @@ Refer to: https://styledictionary.com/reference/logging/ const sd = new StyleDictionary({ log: { errors: { - brokenReferences: 'console', + brokenReferences: logToConsole, }, }, tokens: { @@ -694,7 +705,7 @@ Refer to: https://styledictionary.com/reference/logging/ }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, }, }, }); @@ -985,7 +996,7 @@ Refer to: https://styledictionary.com/reference/logging/ const sd = new StyleDictionary(); const { logs } = await sd.formatFile( { destination, format }, - { log: { verbosity: 'verbose' } }, + { log: { verbosity: verbose } }, dictionary, ); @@ -1168,7 +1179,7 @@ ${dictionary.allTokens.map((tok) => ` ${tok.name}: "${tok.value}";`).join('\n') const { output } = await sd.formatFile( { destination: 'test.css', - format: formats['css/variables'], + format: formats[fileFormats.cssVariables], options: { fileHeader: async () => { await new Promise((resolve) => setTimeout(resolve, 100)); diff --git a/__tests__/__configs/test.js b/__tests__/__configs/test.js index a2f1a357f..e2972b1fa 100644 --- a/__tests__/__configs/test.js +++ b/__tests__/__configs/test.js @@ -1,52 +1,69 @@ +import { formats, actions, transformGroups } from '../../lib/enums/index.js'; + +const { + scssIcons, + scssVariables, + javascriptModule, + lessIcons, + lessVariables, + androidColors, + androidFontDimens, + androidDimens, + iosPlist, + iosMacros, + javascriptEs6, +} = formats; +const { web, scss, less } = transformGroups; + export default { source: ['__tests__/__tokens/**/*.json'], platforms: { web: { - transformGroup: 'web', + transformGroup: web, prefix: 'smop', buildPath: '__tests__/__output/web/', files: [ { destination: '_icons.css', - format: 'scss/icons', + format: scssIcons, }, { destination: '_variables.css', - format: 'scss/variables', + format: scssVariables, }, { destination: '_styles.js', - format: 'javascript/module', + format: javascriptModule, }, ], }, scss: { - transformGroup: 'scss', + transformGroup: scss, prefix: 'smop', buildPath: '__tests__/__output/scss/', files: [ { destination: '_icons.scss', - format: 'scss/icons', + format: scssIcons, }, { destination: '_variables.scss', - format: 'scss/variables', + format: scssVariables, }, ], }, less: { - transformGroup: 'less', + transformGroup: less, prefix: 'smop', buildPath: '__tests__/__output/less/', files: [ { destination: '_icons.less', - format: 'less/icons', + format: lessIcons, }, { destination: '_variables.less', - format: 'less/variables', + format: lessVariables, }, ], }, @@ -56,18 +73,18 @@ export default { files: [ { destination: 'android/colors.xml', - format: 'android/colors', + format: androidColors, }, { destination: 'android/font_dimen.xml', - format: 'android/fontDimens', + format: androidFontDimens, }, { destination: 'android/dimens.xml', - format: 'android/dimens', + format: androidDimens, }, ], - actions: ['android/copyImages'], + actions: [actions.androidCopyImages], }, ios: { transformGroup: 'ios', @@ -75,11 +92,11 @@ export default { files: [ { destination: 'style_dictionary.plist', - format: 'ios/plist', + format: iosPlist, }, { destination: 'style_dictionary.h', - format: 'ios/macros', + format: iosMacros, }, ], }, @@ -89,7 +106,7 @@ export default { files: [ { destination: 'style_dictionary.js', - format: 'javascript/es6', + format: javascriptEs6, }, ], }, diff --git a/__tests__/buildAllPlatforms.test.js b/__tests__/buildAllPlatforms.test.js index c2b2e3f73..62adce901 100644 --- a/__tests__/buildAllPlatforms.test.js +++ b/__tests__/buildAllPlatforms.test.js @@ -15,6 +15,10 @@ import StyleDictionary from 'style-dictionary'; import { fs } from 'style-dictionary/fs'; import { clearOutput, fileExists } from './__helpers.js'; import memfs from '@bundled-es-modules/memfs'; +import { formats, transformGroups } from '../lib/enums/index.js'; + +const { cssVariables } = formats; +const { css } = transformGroups; describe('buildAllPlatforms', () => { beforeEach(() => { @@ -52,12 +56,12 @@ describe('buildAllPlatforms', () => { source: ['__tests__/__tokens/colors.json'], platforms: { web: { - transformGroup: 'css', + transformGroup: css, buildPath: '__tests__/__output/css/', files: [ { destination: 'vars1.css', - format: 'css/variables', + format: cssVariables, }, ], }, @@ -79,12 +83,12 @@ describe('buildAllPlatforms', () => { source: ['__tests__/__tokens/colors.json'], platforms: { web: { - transformGroup: 'css', + transformGroup: css, buildPath: '__tests__/__output/css/', files: [ { destination: 'vars2.css', - format: 'css/variables', + format: cssVariables, }, ], }, diff --git a/__tests__/buildPlatform.test.js b/__tests__/buildPlatform.test.js index c36a6d686..5cbbc21fb 100644 --- a/__tests__/buildPlatform.test.js +++ b/__tests__/buildPlatform.test.js @@ -13,9 +13,13 @@ import { expect } from 'chai'; import StyleDictionary from 'style-dictionary'; import { fileToJSON, clearOutput, fileExists } from './__helpers.js'; +import { formats, transforms, transformGroups } from '../lib/enums/index.js'; const config = fileToJSON('__tests__/__configs/test.json'); const StyleDictionaryExtended = new StyleDictionary(config); +const { cssVariables, json } = formats; +const { scss } = transformGroups; +const { attributeCti, sizePx, colorHex } = transforms; describe('buildPlatform', () => { beforeEach(() => { @@ -70,11 +74,11 @@ describe('buildPlatform', () => { platforms: { test: { buildPath: '__tests__/__output/', - transforms: ['attribute/cti', 'size/px', 'color/hex'], + transforms: [attributeCti, sizePx, colorHex], files: [ { destination: 'output.json', - format: 'json', + format: json, }, ], }, @@ -104,11 +108,11 @@ describe('buildPlatform', () => { platforms: { test: { buildPath: '__tests__/__output/', - transformGroup: 'scss', + transformGroup: scss, files: [ { destination: 'output.json', - format: 'json', + format: json, }, ], }, @@ -129,11 +133,11 @@ describe('buildPlatform', () => { platforms: { test: { buildPath: '__tests__/__output/', - transformGroup: 'scss', + transformGroup: scss, files: [ { destination: 'output.json', - format: 'json', + format: json, }, ], }, @@ -155,7 +159,7 @@ describe('buildPlatform', () => { files: [ { destination: '__tests__/__output/test.css', - format: 'css/variables', + format: cssVariables, }, ], }, diff --git a/__tests__/common/formatHelpers/createPropertyFormatter.test.js b/__tests__/common/formatHelpers/createPropertyFormatter.test.js index 057bf443b..f51aa1dd7 100644 --- a/__tests__/common/formatHelpers/createPropertyFormatter.test.js +++ b/__tests__/common/formatHelpers/createPropertyFormatter.test.js @@ -14,6 +14,11 @@ import { expect } from 'chai'; import createPropertyFormatter from '../../../lib/common/formatHelpers/createPropertyFormatter.js'; import { convertTokenData } from '../../../lib/utils/convertTokenData.js'; import { outputReferencesFilter } from '../../../lib/utils/references/outputReferencesFilter.js'; +import { commentStyles, commentPositions, propertyFormatNames } from '../../../lib/enums/index.js'; + +const { short, long } = commentStyles; +const { above } = commentPositions; +const { css, sass } = propertyFormatNames; const dictionary = { foo: { @@ -172,7 +177,7 @@ describe('common', () => { const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary: { tokens: dictionary }, - format: 'css', + format: css, }); expect(propFormatter(dictionary.foo)).to.equal(' --foo: 5px;'); expect(propFormatter(dictionary.ref)).to.equal(' --ref: var(--foo);'); @@ -182,7 +187,7 @@ describe('common', () => { const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary: { tokens: transformedDictionary }, - format: 'css', + format: css, }); expect(propFormatter(transformedDictionary.foo)).to.equal(' --foo: 5px;'); expect(propFormatter(transformedDictionary.ref)).to.equal(' --ref: var(--foo);'); @@ -192,7 +197,7 @@ describe('common', () => { const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary: { tokens: numberDictionary }, - format: 'css', + format: css, }); expect(propFormatter(numberDictionary.foo)).to.equal(' --foo: 10;'); expect(propFormatter(numberDictionary.ref)).to.equal(' --ref: var(--foo);'); @@ -202,7 +207,7 @@ describe('common', () => { const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary: { tokens: numberDictionary }, - format: 'css', + format: css, }); expect(propFormatter(numberDictionary.zero)).to.equal(' --zero: 0;'); expect(propFormatter(numberDictionary['ref-zero'])).to.equal( @@ -214,7 +219,7 @@ describe('common', () => { const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary: { tokens: multiDictionary }, - format: 'css', + format: css, }); expect(propFormatter(multiDictionary.foo)).to.equal(' --foo: 10px;'); expect(propFormatter(multiDictionary.bar)).to.equal(' --bar: 15px;'); @@ -264,7 +269,7 @@ describe('common', () => { unfilteredTokens, allTokens, }, - format: 'css', + format: css, // outputReferences function that only outputs the refs if the token name is "bar" outputReferences: (token) => token.name === 'bar', }); @@ -324,7 +329,7 @@ describe('common', () => { unfilteredTokens, allTokens, }, - format: 'css', + format: css, // outputReferences function that only outputs the refs if the referred tokens are not filtered out outputReferences: outputReferencesFilter, }); @@ -385,7 +390,7 @@ describe('common', () => { unfilteredTokens, allTokens, }, - format: 'css', + format: css, usesDtcg: true, // outputReferences function that only outputs the refs if the referred tokens are not filtered out outputReferences: outputReferencesFilter, @@ -402,7 +407,7 @@ describe('common', () => { const propFormatter = createPropertyFormatter({ outputReferences: true, dictionary: { tokens: objectDictionary }, - format: 'css', + format: css, }); // expect(propFormatter(objectDictionary.tokens.foo)).to.equal(' --foo: 5px;'); @@ -448,12 +453,12 @@ describe('common', () => { it('should default to putting comment next to the output value', async () => { // long commentStyle const cssFormatter = createPropertyFormatter({ - format: 'css', + format: css, dictionary: { tokens: commentDictionary }, }); // short commentStyle const sassFormatter = createPropertyFormatter({ - format: 'sass', + format: sass, dictionary: { tokens: commentDictionary }, }); @@ -473,15 +478,21 @@ describe('common', () => { it('allows overriding formatting commentStyle', async () => { // long commentStyle const cssFormatter = createPropertyFormatter({ - format: 'css', + format: css, dictionary: { tokens: commentDictionary }, - formatting: { commentStyle: 'long', commentPosition: 'above' }, + formatting: { + commentStyle: long, + commentPosition: above, + }, }); // short commentStyle const sassFormatter = createPropertyFormatter({ - format: 'sass', + format: sass, dictionary: { tokens: commentDictionary }, - formatting: { commentStyle: 'short', commentPosition: 'above' }, + formatting: { + commentStyle: short, + commentPosition: above, + }, }); const cssRed = cssFormatter(commentDictionary.color.green); @@ -536,7 +547,7 @@ describe('common', () => { it('supports DTCG spec $description property for comments', async () => { // long commentStyle const cssFormatter = createPropertyFormatter({ - format: 'css', + format: css, dictionary: { tokens: dtcgDictionary }, usesDtcg: true, }); @@ -553,7 +564,7 @@ describe('common', () => { it('supports DTCG spec $value for outputReferences', async () => { // long commentStyle const cssFormatter = createPropertyFormatter({ - format: 'css', + format: css, outputReferences: true, dictionary: { tokens: dtcgDictionary }, usesDtcg: true, diff --git a/__tests__/common/formatHelpers/fileHeader.test.js b/__tests__/common/formatHelpers/fileHeader.test.js index af7f01e34..3b6c42e34 100644 --- a/__tests__/common/formatHelpers/fileHeader.test.js +++ b/__tests__/common/formatHelpers/fileHeader.test.js @@ -13,6 +13,7 @@ import { expect } from 'chai'; import { fixDate } from '../../__helpers.js'; import fileHeader from '../../../lib/common/formatHelpers/fileHeader.js'; +import { commentStyles } from '../../../lib/enums/index.js'; const defaultLine1 = `Do not edit directly, this file was auto-generated.`; const defaultLine2 = `Generated on Sat, 01 Jan 2000 00:00:00 GMT`; @@ -49,7 +50,7 @@ describe('common', () => { }); it(`should handle commentStyle short`, async () => { - const comment = await fileHeader({ commentStyle: 'short' }); + const comment = await fileHeader({ commentStyle: commentStyles.short }); expect(comment).to.equal( ` // ${defaultLine1} diff --git a/__tests__/common/transforms.test.js b/__tests__/common/transforms.test.js index c699cc6f7..88fe69ea9 100644 --- a/__tests__/common/transforms.test.js +++ b/__tests__/common/transforms.test.js @@ -13,13 +13,65 @@ import { expect } from 'chai'; import Color from 'tinycolor2'; import transforms, { isColor } from '../../lib/common/transforms.js'; +import { transforms as transformNames } from '../../lib/enums/index.js'; + +const { + nameCamel, + nameKebab, + nameSnake, + nameConstant, + attributeColor, + attributeCti, + colorHex, + colorHex8, + colorHex8android, + colorRgb, + colorHsl4, + colorHsl, + colorComposeColor, + colorUIColor, + colorUIColorSwift, + colorColorSwiftUI, + colorHex8flutter, + colorCss, + colorSketch, + sizeSp, + sizeDp, + sizeObject, + sizeRemToSp, + sizeRemToDp, + sizePx, + sizeRemToPt, + sizeComposeRemToSp, + sizeComposeEm, + sizeComposeRemToDp, + sizeSwiftRemToCGFloat, + sizeRemToPx, + sizePxToRem, + sizeRem, + sizeFlutterRemToDouble, + contentQuote, + htmlIcon, + contentObjCLiteral, + assetUrl, + assetObjCLiteral, + timeSeconds, + fontFamilyCss, + cubicBezierCss, + typographyCssShorthand, + borderCssShorthand, + strokeStyleCssShorthand, + transitionCssShorthand, + shadowCssShorthand, + assetPath, +} = transformNames; describe('common', () => { describe('transforms', () => { - describe('name/camel', () => { + describe(nameCamel, () => { it('should handle prefix', () => { expect( - transforms['name/camel'].transform( + transforms[nameCamel].transform( { path: ['one', 'two', 'three'], }, @@ -32,7 +84,7 @@ describe('common', () => { it('should handle no prefix', () => { expect( - transforms['name/camel'].transform( + transforms[nameCamel].transform( { path: ['one', 'two', 'three'], }, @@ -42,10 +94,10 @@ describe('common', () => { }); }); - describe('name/kebab', () => { + describe(nameKebab, () => { it('should handle prefix', () => { expect( - transforms['name/kebab'].transform( + transforms[nameKebab].transform( { path: ['one', 'two', 'three'], }, @@ -58,7 +110,7 @@ describe('common', () => { it('should handle no prefix', () => { expect( - transforms['name/kebab'].transform( + transforms[nameKebab].transform( { path: ['one', 'two', 'three'], }, @@ -68,10 +120,10 @@ describe('common', () => { }); }); - describe('name/snake', () => { + describe(nameSnake, () => { it('should handle prefix', () => { expect( - transforms['name/snake'].transform( + transforms[nameSnake].transform( { path: ['one', 'two', 'three'], }, @@ -84,7 +136,7 @@ describe('common', () => { it('should handle no prefix', () => { expect( - transforms['name/snake'].transform( + transforms[nameSnake].transform( { path: ['one', 'two', 'three'], }, @@ -94,10 +146,10 @@ describe('common', () => { }); }); - describe('name/constant', () => { + describe(nameConstant, () => { it('should handle prefix', () => { expect( - transforms['name/constant'].transform( + transforms[nameConstant].transform( { path: ['one', 'two', 'three'], }, @@ -110,7 +162,7 @@ describe('common', () => { it('should handle no prefix', () => { expect( - transforms['name/constant'].transform( + transforms[nameConstant].transform( { path: ['one', 'two', 'three'], }, @@ -120,9 +172,9 @@ describe('common', () => { }); }); - describe('attribute/color', () => { + describe(attributeColor, () => { it('should handle normal colors', () => { - const attributes = transforms['attribute/color'].transform( + const attributes = transforms[attributeColor].transform( { value: '#aaaaaa', }, @@ -134,14 +186,14 @@ describe('common', () => { expect(attributes).to.have.nested.property('hsl.s', 0); }); it('should handle colors with transparency', () => { - const attributes = transforms['attribute/color'].transform( + const attributes = transforms[attributeColor].transform( { value: '#aaaaaa99', }, {}, {}, ); - const attributes2 = transforms['attribute/color'].transform( + const attributes2 = transforms[attributeColor].transform( { value: 'rgba(170,170,170,0.6)', }, @@ -158,7 +210,7 @@ describe('common', () => { }); describe('transform', () => { - describe('attribute/cti', () => { + describe(attributeCti, () => { const prop = { path: ['color', 'background', 'button', 'primary', 'active', 'extra'], }; @@ -168,9 +220,9 @@ describe('common', () => { attributes: { category: 'size', component: 'button' }, }; - const attrs = transforms['attribute/cti'].transform(prop, {}, {}); - const attrsShort = transforms['attribute/cti'].transform(propShort, {}, {}); - const attrsOverride = transforms['attribute/cti'].transform(propOverride, {}, {}); + const attrs = transforms[attributeCti].transform(prop, {}, {}); + const attrsShort = transforms[attributeCti].transform(propShort, {}, {}); + const attrsOverride = transforms[attributeCti].transform(propOverride, {}, {}); it('should assign attributes correctly', () => { expect(attrs).eql({ @@ -199,9 +251,9 @@ describe('common', () => { }); }); - describe('color/hex', () => { + describe(colorHex, () => { it('should handle hex colors', () => { - const value = transforms['color/hex'].transform( + const value = transforms[colorHex].transform( { value: '#aaaaaa', }, @@ -212,7 +264,7 @@ describe('common', () => { }); it('should handle hex8 colors', () => { - const value = transforms['color/hex'].transform( + const value = transforms[colorHex].transform( { value: '#aaaaaaaa', }, @@ -223,7 +275,7 @@ describe('common', () => { }); it('should handle rgb colors', () => { - const value = transforms['color/hex'].transform( + const value = transforms[colorHex].transform( { value: 'rgb(170,170,170)', }, @@ -234,7 +286,7 @@ describe('common', () => { }); it('should handle rgb (object) colors', () => { - const value = transforms['color/hex'].transform( + const value = transforms[colorHex].transform( { value: { r: '170', @@ -245,7 +297,7 @@ describe('common', () => { {}, {}, ); - const value2 = transforms['color/hex'].transform( + const value2 = transforms[colorHex].transform( { value: 'rgb(170,170,170)', }, @@ -257,7 +309,7 @@ describe('common', () => { }); it('should handle hsl colors', () => { - const value = transforms['color/hex'].transform( + const value = transforms[colorHex].transform( { value: { h: '0', @@ -268,7 +320,7 @@ describe('common', () => { {}, {}, ); - const value2 = transforms['color/hex'].transform( + const value2 = transforms[colorHex].transform( { value: 'hsl(0,0,0.5)', }, @@ -280,9 +332,9 @@ describe('common', () => { }); }); - describe('color/hex8', () => { + describe(colorHex8, () => { it('should handle hex colors', () => { - const value = transforms['color/hex8'].transform( + const value = transforms[colorHex8].transform( { value: '#aaaaaa', }, @@ -293,7 +345,7 @@ describe('common', () => { }); it('should handle rgb colors', () => { - const value = transforms['color/hex8'].transform( + const value = transforms[colorHex8].transform( { value: 'rgb(170,170,170)', }, @@ -304,7 +356,7 @@ describe('common', () => { }); it('should handle rgba colors', () => { - const value = transforms['color/hex8'].transform( + const value = transforms[colorHex8].transform( { value: 'rgba(170,170,170,0.6)', }, @@ -315,9 +367,9 @@ describe('common', () => { }); }); - describe('color/hex8android', () => { + describe(colorHex8android, () => { it('should handle colors without alpha', () => { - const value = transforms['color/hex8android'].transform( + const value = transforms[colorHex8android].transform( { value: '#aaaaaa', }, @@ -328,7 +380,7 @@ describe('common', () => { }); it('should handle colors with alpha', () => { - const value = transforms['color/hex8android'].transform( + const value = transforms[colorHex8android].transform( { value: '#aaaaaa99', }, @@ -339,9 +391,9 @@ describe('common', () => { }); }); - describe('color/rgb', () => { + describe(colorRgb, () => { it('should handle normal colors', () => { - const value = transforms['color/rgb'].transform( + const value = transforms[colorRgb].transform( { value: '#aaaaaa', }, @@ -352,7 +404,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/rgb'].transform( + const value = transforms[colorRgb].transform( { value: '#aaaaaa99', }, @@ -363,9 +415,9 @@ describe('common', () => { }); }); - describe('color/hsl-4', () => { + describe(colorHsl4, () => { it('should handle normal colors', () => { - const value = transforms['color/hsl-4'].transform( + const value = transforms[colorHsl4].transform( { value: '#009688', }, @@ -376,7 +428,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/hsl-4'].transform( + const value = transforms[colorHsl4].transform( { value: '#00968899', }, @@ -387,9 +439,9 @@ describe('common', () => { }); }); - describe('color/hsl', () => { + describe(colorHsl, () => { it('should handle normal colors', () => { - const value = transforms['color/hsl'].transform( + const value = transforms[colorHsl].transform( { value: '#009688', }, @@ -400,7 +452,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/hsl'].transform( + const value = transforms[colorHsl].transform( { value: '#00968899', }, @@ -411,9 +463,9 @@ describe('common', () => { }); }); - describe('color/composeColor', () => { + describe(colorComposeColor, () => { it('should handle color without alpha', () => { - const value = transforms['color/composeColor'].transform( + const value = transforms[colorComposeColor].transform( { value: '#aaaaaa', }, @@ -424,7 +476,7 @@ describe('common', () => { }); it('should handle color with alpha', () => { - const value = transforms['color/composeColor'].transform( + const value = transforms[colorComposeColor].transform( { value: '#aaaaaaff', }, @@ -435,9 +487,9 @@ describe('common', () => { }); }); - describe('color/UIColor', () => { + describe(colorUIColor, () => { it('should handle normal colors', () => { - const value = transforms['color/UIColor'].transform( + const value = transforms[colorUIColor].transform( { value: '#aaaaaa', }, @@ -450,7 +502,7 @@ describe('common', () => { }); it('should retain enough precision when converting to decimal', () => { - const value = transforms['color/UIColor'].transform( + const value = transforms[colorUIColor].transform( { value: '#1d1d1d', }, @@ -463,7 +515,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/UIColor'].transform( + const value = transforms[colorUIColor].transform( { value: '#aaaaaa99', }, @@ -476,9 +528,9 @@ describe('common', () => { }); }); - describe('color/UIColorSwift', () => { + describe(colorUIColorSwift, () => { it('should handle normal colors', () => { - const value = transforms['color/UIColorSwift'].transform( + const value = transforms[colorUIColorSwift].transform( { value: '#aaaaaa', }, @@ -489,7 +541,7 @@ describe('common', () => { }); it('should retain enough precision when converting to decimal', () => { - const value = transforms['color/UIColorSwift'].transform( + const value = transforms[colorUIColorSwift].transform( { value: '#1d1d1d', }, @@ -500,7 +552,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/UIColorSwift'].transform( + const value = transforms[colorUIColorSwift].transform( { value: '#aaaaaa99', }, @@ -511,9 +563,9 @@ describe('common', () => { }); }); - describe('color/ColorSwiftUI', () => { + describe(colorColorSwiftUI, () => { it('should handle normal colors', () => { - const value = transforms['color/ColorSwiftUI'].transform( + const value = transforms[colorColorSwiftUI].transform( { value: '#aaaaaa', }, @@ -524,7 +576,7 @@ describe('common', () => { }); it('should retain enough precision when converting to decimal', () => { - const value = transforms['color/ColorSwiftUI'].transform( + const value = transforms[colorColorSwiftUI].transform( { value: '#1d1d1d', }, @@ -535,7 +587,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/ColorSwiftUI'].transform( + const value = transforms[colorColorSwiftUI].transform( { value: '#aaaaaa99', }, @@ -546,9 +598,9 @@ describe('common', () => { }); }); - describe('color/hex8flutter', () => { + describe(colorHex8flutter, () => { it('should handle colors without alpha', () => { - const value = transforms['color/hex8flutter'].transform( + const value = transforms[colorHex8flutter].transform( { value: '#aaaaaa', }, @@ -559,7 +611,7 @@ describe('common', () => { }); it('should handle colors with alpha', () => { - const value = transforms['color/hex8flutter'].transform( + const value = transforms[colorHex8flutter].transform( { value: '#aaaaaa99', }, @@ -570,9 +622,9 @@ describe('common', () => { }); }); - describe('color/css', () => { + describe(colorCss, () => { it('should handle normal colors', () => { - const value = transforms['color/css'].transform( + const value = transforms[colorCss].transform( { value: 'rgb(170, 170, 170)', }, @@ -583,7 +635,7 @@ describe('common', () => { }); it('should handle colors with transparency', () => { - const value = transforms['color/css'].transform( + const value = transforms[colorCss].transform( { value: '#aaaaaa99', }, @@ -594,10 +646,10 @@ describe('common', () => { }); }); - describe('color/sketch', () => { + describe(colorSketch, () => { it('should retain hex specificity', () => { const originalHex = '#0b7dbb'; - const value = transforms['color/sketch'].transform( + const value = transforms[colorSketch].transform( { value: originalHex, }, @@ -613,16 +665,16 @@ describe('common', () => { }); }); - describe('size/sp', () => { + describe(sizeSp, () => { it('should work', () => { - const value = transforms['size/sp'].transform( + const value = transforms[sizeSp].transform( { value: '12px', }, {}, {}, ); - const value2 = transforms['size/sp'].transform( + const value2 = transforms[sizeSp].transform( { value: '12', }, @@ -633,20 +685,20 @@ describe('common', () => { expect(value2).to.equal('12.00sp'); }); it('should throw an error if prop value is Nan', () => { - expect(() => transforms['size/sp'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeSp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/dp', () => { + describe(sizeDp, () => { it('should work', () => { - const value = transforms['size/dp'].transform( + const value = transforms[sizeDp].transform( { value: '12px', }, {}, {}, ); - const value2 = transforms['size/dp'].transform( + const value2 = transforms[sizeDp].transform( { value: '12', }, @@ -657,13 +709,13 @@ describe('common', () => { expect(value2).to.equal('12.00dp'); }); it('should throw an error if prop value is Nan', () => { - expect(() => transforms['size/dp'].transform({ value: 'a' })).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' })).to.throw(); }); }); - describe('size/object', () => { + describe(sizeObject, () => { it('should work', () => { - const value = transforms['size/object'].transform( + const value = transforms[sizeObject].transform( { value: '1px', }, @@ -676,24 +728,20 @@ describe('common', () => { expect(value.scale).to.equal(16); }); it('should work with custom base font', () => { - const value = transforms['size/object'].transform( - { value: '1' }, - { basePxFontSize: 14 }, - {}, - ); + const value = transforms[sizeObject].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'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeObject].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/remToSp', () => { + describe(sizeRemToSp, () => { it('should work', () => { - const value = transforms['size/remToSp'].transform( + const value = transforms[sizeRemToSp].transform( { value: '1', }, @@ -703,21 +751,17 @@ describe('common', () => { expect(value).to.equal('16.00sp'); }); it('converts rem to sp using custom base font', () => { - const value = transforms['size/remToSp'].transform( - { value: '1' }, - { basePxFontSize: 14 }, - {}, - ); + const value = transforms[sizeRemToSp].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'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/remToDp', () => { + describe(sizeRemToDp, () => { it('should work', () => { - const value = transforms['size/remToDp'].transform( + const value = transforms[sizeRemToDp].transform( { value: '1', }, @@ -727,21 +771,17 @@ describe('common', () => { expect(value).to.equal('16.00dp'); }); it('converts rem to dp using custom base font', () => { - const value = transforms['size/remToDp'].transform( - { value: '1' }, - { basePxFontSize: 14 }, - {}, - ); + const value = transforms[sizeRemToDp].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'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/px', () => { + describe(sizePx, () => { it('should work', () => { - const value = transforms['size/px'].transform( + const value = transforms[sizePx].transform( { value: '10', }, @@ -751,13 +791,13 @@ describe('common', () => { expect(value).to.equal('10px'); }); it('should throw an error if prop value is Nan', () => { - expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/remToPt', () => { + describe(sizeRemToPt, () => { it('should work', () => { - const value = transforms['size/remToPt'].transform( + const value = transforms[sizeRemToPt].transform( { value: '1', }, @@ -767,21 +807,17 @@ describe('common', () => { expect(value).to.equal('16.00f'); }); it('converts rem to pt using custom base font', () => { - const value = transforms['size/remToPt'].transform( - { value: '1' }, - { basePxFontSize: 14 }, - {}, - ); + const value = transforms[sizeRemToPt].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'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/compose/remToSp', () => { + describe(sizeComposeRemToSp, () => { it('should work', () => { - const value = transforms['size/compose/remToSp'].transform( + const value = transforms[sizeComposeRemToSp].transform( { value: '1', }, @@ -791,7 +827,7 @@ describe('common', () => { expect(value).to.equal('16.00.sp'); }); it('converts rem to sp using custom base font', () => { - const value = transforms['size/compose/remToSp'].transform( + const value = transforms[sizeComposeRemToSp].transform( { value: '1' }, { basePxFontSize: 14 }, {}, @@ -799,15 +835,13 @@ describe('common', () => { expect(value).to.equal('14.00.sp'); }); it('should throw an error if prop value is Nan', () => { - expect(() => - transforms['size/compose/remToSp'].transform({ value: 'a' }, {}, {}), - ).to.throw(); + expect(() => transforms[sizeComposeRemToSp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/compose/em', () => { + describe(sizeComposeEm, () => { it('should work', () => { - const value = transforms['size/compose/em'].transform( + const value = transforms[sizeComposeEm].transform( { value: '10', }, @@ -817,13 +851,13 @@ describe('common', () => { expect(value).to.equal('10.em'); }); it('should throw an error if prop value is Nan', () => { - expect(() => transforms['size/compose/em'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeComposeEm].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/compose/remToDp', () => { + describe(sizeComposeRemToDp, () => { it('should work', () => { - const value = transforms['size/compose/remToDp'].transform( + const value = transforms[sizeComposeRemToDp].transform( { value: '1', }, @@ -833,7 +867,7 @@ describe('common', () => { expect(value).to.equal('16.00.dp'); }); it('converts rem to dp using custom base font', () => { - const value = transforms['size/compose/remToDp'].transform( + const value = transforms[sizeComposeRemToDp].transform( { value: '1' }, { basePxFontSize: 14 }, {}, @@ -841,15 +875,13 @@ describe('common', () => { expect(value).to.equal('14.00.dp'); }); it('should throw an error if prop value is Nan', () => { - expect(() => - transforms['size/compose/remToDp'].transform({ value: 'a' }, {}, {}), - ).to.throw(); + expect(() => transforms[sizeComposeRemToDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/swift/remToCGFloat', () => { + describe(sizeSwiftRemToCGFloat, () => { it('should work', () => { - const value = transforms['size/swift/remToCGFloat'].transform( + const value = transforms[sizeSwiftRemToCGFloat].transform( { value: '1', }, @@ -859,7 +891,7 @@ describe('common', () => { expect(value).to.equal('CGFloat(16.00)'); }); it('converts rem to CGFloat using custom base font', () => { - const value = transforms['size/swift/remToCGFloat'].transform( + const value = transforms[sizeSwiftRemToCGFloat].transform( { value: '1' }, { basePxFontSize: 14 }, {}, @@ -873,9 +905,9 @@ describe('common', () => { }); }); - describe('size/remToPx', () => { + describe(sizeRemToPx, () => { it('should work', () => { - const value = transforms['size/remToPx'].transform( + const value = transforms[sizeRemToPx].transform( { value: '1', }, @@ -885,20 +917,16 @@ describe('common', () => { expect(value).to.equal('16px'); }); it('converts rem to px using custom base font', () => { - const value = transforms['size/remToPx'].transform( - { value: '1' }, - { basePxFontSize: 14 }, - {}, - ); + const value = transforms[sizeRemToPx].transform({ value: '1' }, { basePxFontSize: 14 }, {}); expect(value).to.equal('14px'); }); it('should throw an error if prop value is Nan', () => { - expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/pxToRem', () => { - const pxToRemtransform = transforms['size/pxToRem'].transform; + describe(sizePxToRem, () => { + const pxToRemtransform = transforms[sizePxToRem].transform; ['12', '12px', '12rem'].forEach((value) => { it(`ignoring unit, scales "${value}" to rem`, () => { @@ -918,9 +946,9 @@ describe('common', () => { }); }); - describe('size/rem', () => { + describe(sizeRem, () => { it('should work', () => { - const value = transforms['size/rem'].transform( + const value = transforms[sizeRem].transform( { value: '1', }, @@ -932,7 +960,7 @@ describe('common', () => { ['0', 0].forEach((value) => { it('zero value is returned without a unit and remains same type', () => { expect( - transforms['size/rem'].transform( + transforms[sizeRem].transform( { value, }, @@ -943,13 +971,13 @@ describe('common', () => { }); }); it('should throw an error if prop value is Nan', () => { - expect(() => transforms['size/dp'].transform({ value: 'a' }, {}, {})).to.throw(); + expect(() => transforms[sizeDp].transform({ value: 'a' }, {}, {})).to.throw(); }); }); - describe('size/flutter/remToDouble', () => { + describe(sizeFlutterRemToDouble, () => { it('should work', () => { - const value = transforms['size/flutter/remToDouble'].transform( + const value = transforms[sizeFlutterRemToDouble].transform( { value: '1', }, @@ -959,7 +987,7 @@ describe('common', () => { expect(value).to.equal('16.00'); }); it('converts rem to double using custom base font', () => { - const value = transforms['size/flutter/remToDouble'].transform( + const value = transforms[sizeFlutterRemToDouble].transform( { value: '1' }, { basePxFontSize: 14 }, {}, @@ -968,9 +996,9 @@ describe('common', () => { }); }); - describe('content/quote', () => { + describe(contentQuote, () => { it('should work', () => { - const value = transforms['content/quote'].transform( + const value = transforms[contentQuote].transform( { value: 'hello', }, @@ -981,9 +1009,9 @@ describe('common', () => { }); }); - describe('html/icon', () => { + describe(htmlIcon, () => { it('should work', () => { - const value = transforms['html/icon'].transform( + const value = transforms[htmlIcon].transform( { value: '', }, @@ -994,9 +1022,9 @@ describe('common', () => { }); }); - describe('content/objC/literal', () => { + describe(contentObjCLiteral, () => { it('should work', () => { - const value = transforms['content/objC/literal'].transform( + const value = transforms[contentObjCLiteral].transform( { value: 'hello', }, @@ -1007,9 +1035,9 @@ describe('common', () => { }); }); - describe('asset/url', () => { + describe(assetUrl, () => { it('should work', () => { - const value = transforms['asset/url'].transform( + const value = transforms[assetUrl].transform( { value: 'https://example.com', }, @@ -1020,7 +1048,7 @@ describe('common', () => { }); it('should escape double quotes', () => { - const value = transforms['asset/url'].transform( + const value = transforms[assetUrl].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"', @@ -1034,9 +1062,9 @@ describe('common', () => { }); }); - describe('asset/objC/literal', () => { + describe(assetObjCLiteral, () => { it('should work', () => { - const value = transforms['asset/objC/literal'].transform( + const value = transforms[assetObjCLiteral].transform( { value: 'hello', }, @@ -1047,9 +1075,9 @@ describe('common', () => { }); }); - describe('time/seconds', () => { + describe(timeSeconds, () => { it('should work', () => { - const value = transforms['time/seconds'].transform( + const value = transforms[timeSeconds].transform( { value: '1000', }, @@ -1060,8 +1088,8 @@ describe('common', () => { }); }); - describe('fontFamily/css', () => { - const fontFamilyTransform = (token) => transforms['fontFamily/css'].transform(token, {}, {}); + describe(fontFamilyCss, () => { + const fontFamilyTransform = (token) => transforms[fontFamilyCss].transform(token, {}, {}); it('should handle simple fontFamily as is', () => { expect(fontFamilyTransform({ value: 'Arial', type: 'fontFamily' })).to.equal('Arial'); @@ -1132,9 +1160,8 @@ describe('common', () => { }); }); - describe('cubicBezier/css', () => { - const cubicBezierTransform = (token) => - transforms['cubicBezier/css'].transform(token, {}, {}); + describe(cubicBezierCss, () => { + const cubicBezierTransform = (token) => transforms[cubicBezierCss].transform(token, {}, {}); it('should stringify cubicBezier values to cubicBezier() CSS function', () => { expect(cubicBezierTransform({ value: [0.5, 0, 1, 1], type: 'cubicBezier' })).to.equal( @@ -1190,9 +1217,9 @@ describe('common', () => { }); }); - describe('typography/css/shorthand', () => { + describe(typographyCssShorthand, () => { const typographyTransform = (value, platformConfig = {}) => - transforms['typography/css/shorthand'].transform({ value }, platformConfig, {}); + transforms[typographyCssShorthand].transform({ value }, platformConfig, {}); it('transforms typography object to typography shorthand', () => { expect( @@ -1226,9 +1253,9 @@ describe('common', () => { }); // https://design-tokens.github.io/community-group/format/#border - describe('border/css/shorthand', () => { + describe(borderCssShorthand, () => { const borderTransform = (value) => - transforms['border/css/shorthand'].transform({ value, type: 'border' }, {}, {}); + transforms[borderCssShorthand].transform({ value, type: 'border' }, {}, {}); it('transforms border object to border shorthand', () => { expect( @@ -1259,9 +1286,9 @@ describe('common', () => { }); }); - describe('strokeStyle/css/shorthand', () => { + describe(strokeStyleCssShorthand, () => { const strokeTransform = (value, platformConfig = {}) => - transforms['strokeStyle/css/shorthand'].transform({ value }, platformConfig, {}); + transforms[strokeStyleCssShorthand].transform({ value }, platformConfig, {}); it('transforms strokeStyle object value to strokeStyle CSS fallback string value', () => { expect( @@ -1275,9 +1302,9 @@ describe('common', () => { }); }); - describe('transition/css/shorthand', () => { + describe(transitionCssShorthand, () => { const transitionTransform = (value, platformConfig = {}) => - transforms['transition/css/shorthand'].transform({ value }, platformConfig, {}); + transforms[transitionCssShorthand].transform({ value }, platformConfig, {}); it('transforms transition object value to transition CSS shorthand string value', () => { expect( @@ -1300,9 +1327,9 @@ describe('common', () => { }); }); - describe('shadow/css/shorthand', () => { + describe(shadowCssShorthand, () => { const shadowTransform = (value, platformConfig = {}) => - transforms['shadow/css/shorthand'].transform({ value }, platformConfig, {}); + transforms[transformNames.shadowCssShorthand].transform({ value }, platformConfig, {}); it('transforms shadow object value to shadow CSS shorthand string value', () => { expect( @@ -1381,9 +1408,9 @@ describe('common', () => { // 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', () => { + describe.skip(assetPath, () => { it('should work', () => { - const value = transforms['asset/path'].transform( + const value = transforms[transformNames.assetPath].transform( { value: 'foo.json', }, diff --git a/__tests__/exportPlatform.test.js b/__tests__/exportPlatform.test.js index 565e221d7..6805c861c 100644 --- a/__tests__/exportPlatform.test.js +++ b/__tests__/exportPlatform.test.js @@ -15,8 +15,28 @@ import { stubMethod, restore } from 'hanbi'; import StyleDictionary from 'style-dictionary'; import { usesReferences } from 'style-dictionary/utils'; import { fileToJSON, cleanConsoleOutput } from './__helpers.js'; +import { + logWarningLevels, + logVerbosityLevels, + transforms, + transformGroups, + transformTypes, +} from '../lib/enums/index.js'; const config = fileToJSON('__tests__/__configs/test.json'); +const { default: defaultVerbosity, silent, verbose } = logVerbosityLevels; +const { error: errorLog, disabled } = logWarningLevels; +const { css, web } = transformGroups; +const { + colorCss, + nameKebab, + typographyCssShorthand, + borderCssShorthand, + shadowCssShorthand, + cubicBezierCss, + transitionCssShorthand, +} = transforms; +const { value: transformTypeValue } = transformTypes; describe('exportPlatform', () => { let styleDictionary; @@ -67,12 +87,12 @@ describe('exportPlatform', () => { const StyleDictionaryExtended = await styleDictionary.extend({ platforms: { test: { - transforms: ['color/css', 'color/darken'], + transforms: [colorCss, 'color/darken'], }, }, }); StyleDictionary.registerTransform({ - type: 'value', + type: transformTypeValue, name: 'color/darken', transitive: true, filter: function (prop) { @@ -103,7 +123,7 @@ describe('exportPlatform', () => { hooks: { transforms: { transitive: { - type: 'value', + type: transformTypeValue, transitive: true, transform: (token) => `${token.value}-bar`, }, @@ -150,7 +170,7 @@ describe('exportPlatform', () => { }, }); StyleDictionaryExtended.registerTransform({ - type: 'value', + type: transformTypeValue, name: 'color/darken', transitive: true, filter: (token) => token.type === 'color', @@ -205,7 +225,7 @@ describe('exportPlatform', () => { }, platforms: { web: { - transformGroup: 'web', + transformGroup: web, }, }, }); @@ -279,7 +299,7 @@ describe('exportPlatform', () => { tokens, platforms: { css: { - transformGroup: `css`, + transformGroup: css, }, }, }).exportPlatform('css'); @@ -302,7 +322,7 @@ describe('exportPlatform', () => { tokens, platforms: { css: { - transformGroup: 'css', + transformGroup: css, }, }, }); @@ -358,7 +378,7 @@ describe('exportPlatform', () => { }; // making the css/color transform transitive so we can be sure the references // get resolved properly and transformed. - const transitiveTransform = Object.assign({}, StyleDictionary.hooks.transforms['color/css'], { + const transitiveTransform = Object.assign({}, StyleDictionary.hooks.transforms[colorCss], { transitive: true, }); @@ -371,7 +391,7 @@ describe('exportPlatform', () => { }, platforms: { css: { - transforms: ['name/kebab', 'transitiveTransform'], + transforms: [nameKebab, 'transitiveTransform'], }, }, }); @@ -397,7 +417,7 @@ 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`, + transformGroup: css, }, }; @@ -470,7 +490,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details.`; }, platforms: { css: { - transforms: ['typography/css/shorthand'], + transforms: [typographyCssShorthand], }, }, }); @@ -484,7 +504,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. Refer to: https://styledictionary.com/reference/logging/ `); - sd.log.verbosity = 'verbose'; + sd.log.verbosity = verbose; await sd.exportPlatform('css', { cache: false }); expect(cleanConsoleOutput(Array.from(logStub.calls)[1].args[0])).to.equal(` @@ -502,16 +522,16 @@ Unknown CSS Font Shorthand properties found for 1 tokens, CSS output for Font va letterSpacing, paragraphSpacing, textColor for token at foo.bar in /tokens.json `); - sd.log.verbosity = 'silent'; + sd.log.verbosity = silent; await sd.exportPlatform('css', { cache: false }); expect(Array.from(logStub.calls)[3]).to.be.undefined; - sd.log.verbosity = 'default'; - sd.log.warnings = 'disabled'; + sd.log.verbosity = defaultVerbosity; + sd.log.warnings = disabled; await sd.exportPlatform('css', { cache: false }); expect(Array.from(logStub.calls)[3]).to.be.undefined; - sd.log.warnings = 'error'; + sd.log.warnings = errorLog; await expect(sd.exportPlatform('css', { cache: false })).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. @@ -538,7 +558,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['typography/css/shorthand'], + transforms: [typographyCssShorthand], }, }, }); @@ -567,7 +587,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['typography/css/shorthand'], + transforms: [typographyCssShorthand], }, }, }); @@ -596,7 +616,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['border/css/shorthand'], + transforms: [borderCssShorthand], }, }, }); @@ -623,7 +643,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['border/css/shorthand'], + transforms: [borderCssShorthand], }, }, }); @@ -652,7 +672,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['cubicBezier/css', 'transition/css/shorthand'], + transforms: [cubicBezierCss, transitionCssShorthand], }, }, }); @@ -679,7 +699,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['cubicBezier/css', 'transition/css/shorthand'], + transforms: [cubicBezierCss, transitionCssShorthand], }, }, }); @@ -709,7 +729,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['shadow/css/shorthand'], + transforms: [shadowCssShorthand], }, }, }); @@ -745,7 +765,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['shadow/css/shorthand'], + transforms: [shadowCssShorthand], }, }, }); @@ -788,7 +808,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. hooks: { transforms: { 'custom/add/px': { - type: 'value', + type: transformTypeValue, filter: (token) => { return token.$type === 'dimension'; }, @@ -800,7 +820,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. }, platforms: { css: { - transforms: ['name/kebab', 'custom/add/px'], + transforms: [nameKebab, 'custom/add/px'], }, }, }); diff --git a/__tests__/formats/__snapshots__/all.test.snap.js b/__tests__/formats/__snapshots__/all.test.snap.js index 7fa589665..6ed5bd796 100644 --- a/__tests__/formats/__snapshots__/all.test.snap.js +++ b/__tests__/formats/__snapshots__/all.test.snap.js @@ -12,772 +12,6 @@ snapshots["formats all should match css/variables snapshot"] = `; /* 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. @@ -790,6 +24,18 @@ snapshots["formats all should match css/variables snapshot with fileHeaderTimest `; /* end snapshot formats all should match css/variables snapshot with fileHeaderTimestamp set */ +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-flat snapshot with fileHeaderTimestamp set"] = ` /** @@ -803,6 +49,22 @@ $tokens: ( );`; /* end snapshot formats all should match scss/map-flat snapshot with fileHeaderTimestamp set */ +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/map-deep snapshot with fileHeaderTimestamp set"] = ` /** @@ -820,6 +82,14 @@ $tokens: ( `; /* end snapshot formats all should match scss/map-deep snapshot with fileHeaderTimestamp set */ +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/variables snapshot with fileHeaderTimestamp set"] = ` // Do not edit directly, this file was auto-generated. @@ -829,6 +99,13 @@ $color_red: #FF0000; // comment `; /* end snapshot formats all should match scss/variables snapshot with fileHeaderTimestamp set */ +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 scss/icons snapshot with fileHeaderTimestamp set"] = ` // Do not edit directly, this file was auto-generated. @@ -837,6 +114,14 @@ snapshots["formats all should match scss/icons snapshot with fileHeaderTimestamp `; /* end snapshot formats all should match scss/icons snapshot with fileHeaderTimestamp set */ +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/variables snapshot with fileHeaderTimestamp set"] = ` // Do not edit directly, this file was auto-generated. @@ -846,6 +131,13 @@ snapshots["formats all should match less/variables snapshot with fileHeaderTimes `; /* end snapshot formats all should match less/variables snapshot with fileHeaderTimestamp set */ +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 less/icons snapshot with fileHeaderTimestamp set"] = ` // Do not edit directly, this file was auto-generated. @@ -854,6 +146,14 @@ snapshots["formats all should match less/icons snapshot with fileHeaderTimestamp `; /* end snapshot formats all should match less/icons snapshot with fileHeaderTimestamp set */ +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 stylus/variables snapshot with fileHeaderTimestamp set"] = ` // Do not edit directly, this file was auto-generated. @@ -863,6 +163,28 @@ $color_red= #FF0000; // comment `; /* end snapshot formats all should match stylus/variables snapshot with fileHeaderTimestamp set */ +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 snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -886,6 +208,17 @@ module.exports = { `; /* end snapshot formats all should match javascript/module snapshot with fileHeaderTimestamp set */ +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/module-flat snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -898,6 +231,28 @@ module.exports = { `; /* end snapshot formats all should match javascript/module-flat snapshot with fileHeaderTimestamp set */ +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/object snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -921,6 +276,40 @@ var _styleDictionary = { `; /* end snapshot formats all should match javascript/object snapshot with fileHeaderTimestamp set */ +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/umd snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -956,6 +345,15 @@ snapshots["formats all should match javascript/umd snapshot with fileHeaderTimes `; /* end snapshot formats all should match javascript/umd snapshot with fileHeaderTimestamp set */ +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 javascript/es6 snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -966,6 +364,61 @@ export const color_red = "#FF0000"; // comment `; /* end snapshot formats all should match javascript/es6 snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match javascript/esm snapshot"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +export default { + color: { + red: { + value: "#FF0000", + type: "color", + original: { + value: "#FF0000", + }, + name: "color_red", + comment: "comment", + path: ["color", "red"], + }, + }, +}; +`; +/* end snapshot formats all should match javascript/esm snapshot */ + +snapshots["formats all should match javascript/esm 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 { + color: { + red: { + value: "#FF0000", + type: "color", + original: { + value: "#FF0000", + }, + name: "color_red", + comment: "comment", + path: ["color", "red"], + }, + }, +}; +`; +/* end snapshot formats all should match javascript/esm snapshot with fileHeaderTimestamp set */ + +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/es6-declarations snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -977,6 +430,31 @@ 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"] = +`/** + * 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 typescript/module-declarations snapshot with fileHeaderTimestamp set"] = `/** * Do not edit directly, this file was auto-generated. @@ -1003,17 +481,39 @@ declare const tokens: { `; /* end snapshot formats all should match typescript/module-declarations snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match android/resources snapshot"] = +` + + + + #FF0000 +`; +/* end snapshot formats all should match android/resources snapshot */ + 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"] = +` + + #FF0000 `; -/* end snapshot formats all should match android/resources snapshot with fileHeaderTimestamp set */ +/* end snapshot formats all should match android/colors snapshot */ snapshots["formats all should match android/colors snapshot with fileHeaderTimestamp set"] = ` @@ -1027,6 +527,17 @@ snapshots["formats all should match android/colors snapshot with fileHeaderTimes `; /* end snapshot formats all should match android/colors snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match android/dimens snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/dimens snapshot */ + snapshots["formats all should match android/dimens snapshot with fileHeaderTimestamp set"] = ` @@ -1039,6 +550,17 @@ snapshots["formats all should match android/dimens snapshot with fileHeaderTimes `; /* end snapshot formats all should match android/dimens snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match android/fontDimens snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/fontDimens snapshot */ + snapshots["formats all should match android/fontDimens snapshot with fileHeaderTimestamp set"] = ` @@ -1051,6 +573,17 @@ snapshots["formats all should match android/fontDimens snapshot with fileHeaderT `; /* end snapshot formats all should match android/fontDimens snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match android/integers snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/integers snapshot */ + snapshots["formats all should match android/integers snapshot with fileHeaderTimestamp set"] = ` @@ -1063,6 +596,17 @@ snapshots["formats all should match android/integers snapshot with fileHeaderTim `; /* end snapshot formats all should match android/integers snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match android/strings snapshot"] = +` + + + + +`; +/* end snapshot formats all should match android/strings snapshot */ + snapshots["formats all should match android/strings snapshot with fileHeaderTimestamp set"] = ` @@ -1075,6 +619,25 @@ snapshots["formats all should match android/strings snapshot with fileHeaderTime `; /* end snapshot formats all should match android/strings snapshot with fileHeaderTimestamp set */ +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 compose/object snapshot with fileHeaderTimestamp set"] = ` @@ -1095,6 +658,22 @@ object { `; /* end snapshot formats all should match compose/object snapshot with fileHeaderTimestamp set */ +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/macros snapshot with fileHeaderTimestamp set"] = ` // @@ -1112,6 +691,31 @@ snapshots["formats all should match ios/macros snapshot with fileHeaderTimestamp `; /* end snapshot formats all should match ios/macros snapshot with fileHeaderTimestamp set */ +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/plist snapshot with fileHeaderTimestamp set"] = ` @@ -1138,6 +742,50 @@ snapshots["formats all should match ios/plist snapshot with fileHeaderTimestamp `; /* end snapshot formats all should match ios/plist snapshot with fileHeaderTimestamp set */ +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.m snapshot with fileHeaderTimestamp set"] = ` // @@ -1183,6 +831,27 @@ snapshots["formats all should match ios/singleton.m snapshot with fileHeaderTime `; /* end snapshot formats all should match ios/singleton.m snapshot with fileHeaderTimestamp set */ +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/singleton.h snapshot with fileHeaderTimestamp set"] = ` // @@ -1205,6 +874,20 @@ snapshots["formats all should match ios/singleton.h snapshot with fileHeaderTime @end`; /* end snapshot formats all should match ios/singleton.h snapshot with fileHeaderTimestamp set */ +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.h snapshot with fileHeaderTimestamp set"] = ` // __output/ @@ -1220,6 +903,21 @@ snapshots["formats all should match ios/static.h snapshot with fileHeaderTimesta 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"] = +` +// +// __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/static.m snapshot with fileHeaderTimestamp set"] = ` // @@ -1236,6 +934,27 @@ snapshots["formats all should match ios/static.m snapshot with fileHeaderTimesta 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"] = +` +// +// __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.h snapshot with fileHeaderTimestamp set"] = ` // @@ -1246,17 +965,50 @@ snapshots["formats all should match ios/colors.h snapshot with fileHeaderTimesta // Generated on Sat, 01 Jan 2000 00:00:00 GMT -#import +#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"] = +` +// +// __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 + ]; + }); -typedef NS_ENUM(NSInteger, ) { -color_red -}; + return colorArray; +} -@interface : NSObject -+ (NSArray *)values; -+ (UIColor *)color:()color; @end`; -/* end snapshot formats all should match ios/colors.h snapshot with fileHeaderTimestamp set */ +/* end snapshot formats all should match ios/colors.m snapshot */ snapshots["formats all should match ios/colors.m snapshot with fileHeaderTimestamp set"] = ` @@ -1292,6 +1044,25 @@ snapshots["formats all should match ios/colors.m snapshot with fileHeaderTimesta @end`; /* end snapshot formats all should match ios/colors.m snapshot with fileHeaderTimestamp set */ +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.h snapshot with fileHeaderTimestamp set"] = ` // @@ -1312,6 +1083,43 @@ extern NSString * const color_red; @end`; /* end snapshot formats all should match ios/strings.h snapshot with fileHeaderTimestamp set */ +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/strings.m snapshot with fileHeaderTimestamp set"] = ` // @@ -1350,6 +1158,22 @@ NSString * const color_red = #FF0000; `; /* end snapshot formats all should match ios/strings.m snapshot with fileHeaderTimestamp set */ +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/class.swift snapshot with fileHeaderTimestamp set"] = ` // @@ -1367,6 +1191,22 @@ public class { }`; /* end snapshot formats all should match ios-swift/class.swift snapshot with fileHeaderTimestamp set */ +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/enum.swift snapshot with fileHeaderTimestamp set"] = ` // @@ -1384,6 +1224,22 @@ public enum { }`; /* end snapshot formats all should match ios-swift/enum.swift snapshot with fileHeaderTimestamp set */ +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 ios-swift/any.swift snapshot with fileHeaderTimestamp set"] = ` // @@ -1401,10 +1257,35 @@ public class { }`; /* end snapshot formats all should match ios-swift/any.swift snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match css/fonts.css snapshot"] = +``; +/* end snapshot formats all should match css/fonts.css snapshot */ + 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"] = +`{ + "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 snapshot with fileHeaderTimestamp set"] = `{ "color": { @@ -1426,10 +1307,23 @@ snapshots["formats all should match json snapshot with fileHeaderTimestamp set"] `; /* end snapshot formats all should match json snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match json/asset snapshot"] = +`{}`; +/* end snapshot formats all should match json/asset snapshot */ + 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"] = +`{ + "color": { + "red": "#FF0000" + } +} +`; +/* end snapshot formats all should match json/nested snapshot */ + snapshots["formats all should match json/nested snapshot with fileHeaderTimestamp set"] = `{ "color": { @@ -1439,6 +1333,13 @@ snapshots["formats all should match json/nested snapshot with fileHeaderTimestam `; /* end snapshot formats all should match json/nested snapshot with fileHeaderTimestamp set */ +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 json/flat snapshot with fileHeaderTimestamp set"] = `{ "color_red": "#FF0000" @@ -1446,7 +1347,18 @@ snapshots["formats all should match json/flat snapshot with fileHeaderTimestamp `; /* end snapshot formats all should match json/flat snapshot with fileHeaderTimestamp set */ -snapshots["formats all should match sketch/palette snapshot with fileHeaderTimestamp set"] = +snapshots["formats all should match sketchPalette snapshot"] = +`{ + "compatibleVersion": "1.0", + "pluginVersion": "1.1", + "colors": [ + "#FF0000" + ] +} +`; +/* end snapshot formats all should match sketchPalette snapshot */ + +snapshots["formats all should match sketchPalette snapshot with fileHeaderTimestamp set"] = `{ "compatibleVersion": "1.0", "pluginVersion": "1.1", @@ -1455,7 +1367,27 @@ snapshots["formats all should match sketch/palette snapshot with fileHeaderTimes ] } `; -/* end snapshot formats all should match sketch/palette snapshot with fileHeaderTimestamp set */ +/* end snapshot formats all should match sketchPalette snapshot with fileHeaderTimestamp set */ + +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 sketch/palette/v2 snapshot with fileHeaderTimestamp set"] = `{ @@ -1477,14 +1409,13 @@ snapshots["formats all should match sketch/palette/v2 snapshot with fileHeaderTi `; /* 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"] = +snapshots["formats all should match flutter/class.dart snapshot"] = ` // // __output/ // // Do not edit directly, this file was auto-generated. -// Generated on Sat, 01 Jan 2000 00:00:00 GMT @@ -1495,50 +1426,25 @@ class { static const color_red = #FF0000; /* comment */ }`; -/* end snapshot formats all should match flutter/class.dart snapshot with fileHeaderTimestamp set */ +/* end snapshot formats all should match flutter/class.dart snapshot */ -snapshots["formats all should match javascript/esm snapshot"] = -`/** - * Do not edit directly, this file was auto-generated. - */ +snapshots["formats all should match flutter/class.dart snapshot with fileHeaderTimestamp set"] = +` +// +// __output/ +// -export default { - color: { - red: { - value: "#FF0000", - type: "color", - original: { - value: "#FF0000", - }, - name: "color_red", - comment: "comment", - path: ["color", "red"], - }, - }, -}; -`; -/* end snapshot formats all should match javascript/esm snapshot */ +// Do not edit directly, this file was auto-generated. +// Generated on Sat, 01 Jan 2000 00:00:00 GMT -snapshots["formats all should match javascript/esm 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 { - color: { - red: { - value: "#FF0000", - type: "color", - original: { - value: "#FF0000", - }, - name: "color_red", - comment: "comment", - path: ["color", "red"], - }, - }, -}; -`; -/* end snapshot formats all should match javascript/esm snapshot with fileHeaderTimestamp set */ + +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__/es6Module.test.snap.js b/__tests__/formats/__snapshots__/javascriptEsm.test.snap.js similarity index 100% rename from __tests__/formats/__snapshots__/es6Module.test.snap.js rename to __tests__/formats/__snapshots__/javascriptEsm.test.snap.js diff --git a/__tests__/formats/__snapshots__/es6ModuleMinify.test.snap.js b/__tests__/formats/__snapshots__/javascriptEsmMinify.test.snap.js similarity index 100% rename from __tests__/formats/__snapshots__/es6ModuleMinify.test.snap.js rename to __tests__/formats/__snapshots__/javascriptEsmMinify.test.snap.js diff --git a/__tests__/formats/all.test.js b/__tests__/formats/all.test.js index de2233866..4082f6f9b 100644 --- a/__tests__/formats/all.test.js +++ b/__tests__/formats/all.test.js @@ -15,10 +15,11 @@ import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; import { deepmerge } from '../../lib/utils/deepmerge.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; const file = { destination: '__output/', - format: 'javascript/es6', + format: fileFormats.javascriptEs6, filter: { type: 'color', }, diff --git a/__tests__/formats/androidResources.test.js b/__tests__/formats/androidResources.test.js index a85564f27..94141c4f4 100644 --- a/__tests__/formats/androidResources.test.js +++ b/__tests__/formats/androidResources.test.js @@ -14,6 +14,9 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { androidResources } = fileFormats; const tokens = { size: { @@ -89,10 +92,10 @@ const customTokens = { }, }; -const format = formats['android/resources']; +const format = formats[androidResources]; const file = { destination: '__output/', - format: 'android/resources', + format: androidResources, }; describe('formats', () => { diff --git a/__tests__/formats/es6Constants.test.js b/__tests__/formats/es6Constants.test.js index b2440228f..88f381378 100644 --- a/__tests__/formats/es6Constants.test.js +++ b/__tests__/formats/es6Constants.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { javascriptEs6 } = fileFormats; const file = { destination: '__output/', - format: 'javascript/es6', + format: javascriptEs6, filter: { type: 'color', }, @@ -36,10 +39,10 @@ const tokens = { }, }; -const format = formats['javascript/es6']; +const format = formats[javascriptEs6]; describe('formats', () => { - describe('javascript/es6', () => { + describe(javascriptEs6, () => { it('should be a valid JS file and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/es6Module.test.js b/__tests__/formats/javascriptEsm.test.js similarity index 95% rename from __tests__/formats/es6Module.test.js rename to __tests__/formats/javascriptEsm.test.js index 4296b91fa..22f3e4eae 100644 --- a/__tests__/formats/es6Module.test.js +++ b/__tests__/formats/javascriptEsm.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as formatsEnum } from '../../lib/enums/formats.js'; + +const { javascriptEsm } = formatsEnum; const file = { destination: '__output/', - format: 'javascript/esm', + format: javascriptEsm, filter: { type: 'color', }, @@ -81,10 +84,10 @@ const DTCGTokens = { }, }; -const format = formats['javascript/esm']; +const format = formats[javascriptEsm]; describe('formats', () => { - describe('javascript/esm', () => { + describe(javascriptEsm, () => { it('should be a valid JS file and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/es6ModuleMinify.test.js b/__tests__/formats/javascriptEsmMinify.test.js similarity index 87% rename from __tests__/formats/es6ModuleMinify.test.js rename to __tests__/formats/javascriptEsmMinify.test.js index 6fc78aa3c..35fbc1488 100644 --- a/__tests__/formats/es6ModuleMinify.test.js +++ b/__tests__/formats/javascriptEsmMinify.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as formatsEnum } from '../../lib/enums/formats.js'; + +const { javascriptEsm } = formatsEnum; const file = { destination: '__output/', - format: 'javascript/esm', + format: javascriptEsm, options: { minify: true, }, @@ -32,10 +35,10 @@ const tokens = { }, }; -const format = formats['javascript/esm']; +const format = formats[javascriptEsm]; describe('formats', () => { - describe('javascript/esm', () => { + describe(javascriptEsm, () => { it('should be a valid JS file and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/javascriptModule.test.js b/__tests__/formats/javascriptModule.test.js index ef205c51d..6693ad3eb 100644 --- a/__tests__/formats/javascriptModule.test.js +++ b/__tests__/formats/javascriptModule.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { javascriptModule } = fileFormats; const file = { destination: '__output/', - format: 'javascript/module', + format: javascriptModule, filter: { type: 'color', }, @@ -29,10 +32,10 @@ const tokens = { }, }; -const format = formats['javascript/module']; +const format = formats[javascriptModule]; describe('formats', () => { - describe('javascript/module', () => { + describe(javascriptModule, () => { it('should be a valid JS file and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/javascriptModuleFlat.test.js b/__tests__/formats/javascriptModuleFlat.test.js index 80a0d01aa..fb06aa060 100644 --- a/__tests__/formats/javascriptModuleFlat.test.js +++ b/__tests__/formats/javascriptModuleFlat.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { javascriptModuleFlat } = fileFormats; const file = { destination: '__output/', - format: 'javascript/module-flat', + format: javascriptModuleFlat, }; const tokens = { color: { @@ -32,10 +35,10 @@ const tokens = { }, }; -const format = formats['javascript/module-flat']; +const format = formats[javascriptModuleFlat]; describe('formats', () => { - describe('javascript/module-flat', () => { + describe(javascriptModuleFlat, () => { it('should be a valid JS file and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/javascriptObject.test.js b/__tests__/formats/javascriptObject.test.js index 8a0aa249f..c3d8b56be 100644 --- a/__tests__/formats/javascriptObject.test.js +++ b/__tests__/formats/javascriptObject.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { javascriptObject } = fileFormats; const file = { destination: '__output/', - format: 'javascript/object', + format: javascriptObject, options: { name: 'foo' }, }; @@ -27,10 +30,10 @@ const tokens = { }, }; -const format = formats['javascript/object']; +const format = formats[javascriptObject]; describe('formats', () => { - describe('javascript/object', () => { + describe(javascriptObject, () => { it('should be valid JS syntax and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/javascriptUmd.test.js b/__tests__/formats/javascriptUmd.test.js index f46d1096e..173a3d84d 100644 --- a/__tests__/formats/javascriptUmd.test.js +++ b/__tests__/formats/javascriptUmd.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { javascriptUmd } = fileFormats; const file = { destination: '__output/', - format: 'javascript/umd', + format: javascriptUmd, filter: { type: 'color', }, @@ -29,10 +32,10 @@ const tokens = { }, }; -const format = formats['javascript/umd']; +const format = formats[javascriptUmd]; describe('formats', () => { - describe('javascript/umd', () => { + describe(javascriptUmd, () => { it('should be a valid JS file and match snapshot', async () => { await expect( await format( diff --git a/__tests__/formats/json.test.js b/__tests__/formats/json.test.js index 9fb918fd5..7a3a1b524 100644 --- a/__tests__/formats/json.test.js +++ b/__tests__/formats/json.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { json } = fileFormats; const file = { destination: '__output/', - format: 'json', + format: json, }; const tokens = { @@ -78,10 +81,10 @@ const DTCGTokens = { }, }; -const format = formats['json']; +const format = formats[json]; describe('formats', () => { - describe('json', () => { + describe(json, () => { it('should be a valid JSON file and match snapshot', async () => { await expect( format( diff --git a/__tests__/formats/jsonFlat.test.js b/__tests__/formats/jsonFlat.test.js index 86ed035b8..2d72d4352 100644 --- a/__tests__/formats/jsonFlat.test.js +++ b/__tests__/formats/jsonFlat.test.js @@ -14,6 +14,7 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; const colorTokenName = 'color-base-red-400'; const colorTokenValue = '#EF5350'; @@ -37,13 +38,13 @@ const colorTokens = { const file = { destination: '__output/', - format: 'json/flat', + format: fileFormats.jsonFlat, }; -const format = formats['json/flat']; +const format = formats[fileFormats.jsonFlat]; describe('formats', () => { - describe('json/flat', () => { + describe(fileFormats.jsonFlat, () => { it('should be a valid JSON file and match snapshot', async () => { await expect( format( diff --git a/__tests__/formats/jsonNested.test.js b/__tests__/formats/jsonNested.test.js index 3b0fcb576..476fe4be8 100644 --- a/__tests__/formats/jsonNested.test.js +++ b/__tests__/formats/jsonNested.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { jsonNested } = fileFormats; const file = { destination: 'output/', - format: 'json/nested', + format: jsonNested, }; const tokens = { @@ -35,10 +38,10 @@ const tokens = { }, }; -const format = formats['json/nested']; +const format = formats[jsonNested]; describe('formats', function () { - describe('json/nested', function () { + describe(jsonNested, function () { it('should be a valid JSON file and match snapshot', async () => { await expect( format( diff --git a/__tests__/formats/lessIcons.test.js b/__tests__/formats/lessIcons.test.js index 707df30ed..d04797ad2 100644 --- a/__tests__/formats/lessIcons.test.js +++ b/__tests__/formats/lessIcons.test.js @@ -15,10 +15,13 @@ import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; import { isNode } from '../../lib/utils/isNode.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { lessIcons } = fileFormats; const file = { destination: '__output/', - format: 'less/icons', + format: lessIcons, name: 'foo', }; @@ -54,10 +57,10 @@ const platform = { }, }; -const format = formats['less/icons']; +const format = formats[lessIcons]; describe('formats', () => { - describe('less/icons', () => { + describe(lessIcons, () => { it('should have a valid less syntax and match snapshot', async () => { const result = await format( createFormatArgs({ diff --git a/__tests__/formats/lessVariables.test.js b/__tests__/formats/lessVariables.test.js index 048f4e931..c4773df38 100644 --- a/__tests__/formats/lessVariables.test.js +++ b/__tests__/formats/lessVariables.test.js @@ -15,10 +15,13 @@ import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; import { isNode } from '../../lib/utils/isNode.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { lessVariables } = fileFormats; const file = { destination: '__output/', - format: 'less/variables', + format: lessVariables, name: 'foo', }; @@ -42,10 +45,10 @@ const tokens = { }, }; -const format = formats['less/variables']; +const format = formats[lessVariables]; describe('formats', () => { - describe('less/variables', () => { + describe(lessVariables, () => { it('should have a valid less syntax and match snapshot', async () => { const result = await format( createFormatArgs({ diff --git a/__tests__/formats/scssIcons.test.js b/__tests__/formats/scssIcons.test.js index 2f4dc20c5..d764cb69e 100644 --- a/__tests__/formats/scssIcons.test.js +++ b/__tests__/formats/scssIcons.test.js @@ -15,10 +15,13 @@ import { compileString } from 'sass'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { scssIcons } = fileFormats; const file = { destination: '__output/', - format: 'scss/icons', + format: scssIcons, name: 'foo', }; @@ -54,10 +57,10 @@ const platform = { }, }; -const format = formats['scss/icons']; +const format = formats[scssIcons]; describe('formats', () => { - describe('scss/icons', () => { + describe(scssIcons, () => { it('should have a valid scss syntax and match snapshot', async () => { const result = await format( createFormatArgs({ diff --git a/__tests__/formats/scssMaps.test.js b/__tests__/formats/scssMaps.test.js index 2f8c90136..a5f308436 100644 --- a/__tests__/formats/scssMaps.test.js +++ b/__tests__/formats/scssMaps.test.js @@ -15,6 +15,7 @@ import { compileString } from 'sass'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { commentStyles, commentPositions, formats as fileFormats } from '../../lib/enums/index.js'; const tokens = { size: { @@ -76,7 +77,7 @@ const tokens = { }; describe('formats', () => { - for (const key of ['scss/map-flat', 'scss/map-deep']) { + for (const key of [fileFormats.scssMapFlat, fileFormats.scssMapDeep]) { describe(key, async () => { const file = { destination: '__output/', @@ -115,8 +116,8 @@ describe('formats', () => { formatting: { fileHeaderTimestamp: true, indentation: ' ', - commentStyle: 'long', - commentPosition: 'above', + commentStyle: commentStyles.long, + commentPosition: commentPositions.above, }, }, }; diff --git a/__tests__/formats/scssVariables.test.js b/__tests__/formats/scssVariables.test.js index 34217904c..7089ed200 100644 --- a/__tests__/formats/scssVariables.test.js +++ b/__tests__/formats/scssVariables.test.js @@ -15,10 +15,13 @@ import { compileString } from 'sass'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { scssVariables } = fileFormats; const file = { destination: '__output/', - format: 'scss/variables', + format: scssVariables, name: 'foo', }; @@ -42,10 +45,10 @@ const tokens = { }, }; -const format = formats['scss/variables']; +const format = formats[scssVariables]; describe('formats', () => { - describe('scss/variables', () => { + describe(scssVariables, () => { it('should have a valid scss syntax and match snapshot', async () => { const result = await format( createFormatArgs({ diff --git a/__tests__/formats/stylusVariable.test.js b/__tests__/formats/stylusVariable.test.js index 61072c981..a03847019 100644 --- a/__tests__/formats/stylusVariable.test.js +++ b/__tests__/formats/stylusVariable.test.js @@ -15,10 +15,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { stylusVariables } = fileFormats; const file = { destination: '__output/', - format: 'stylus/variables', + format: stylusVariables, name: 'foo', }; @@ -42,10 +45,10 @@ const tokens = { }, }; -const format = formats['stylus/variables']; +const format = formats[stylusVariables]; describe('formats', () => { - describe('stylus/variables', () => { + describe(stylusVariables, () => { it('should have a valid stylus syntax and match snapshot', async () => { const result = format( createFormatArgs({ diff --git a/__tests__/formats/swiftFile.test.js b/__tests__/formats/swiftFile.test.js index 71ef8bfa5..ac4056966 100644 --- a/__tests__/formats/swiftFile.test.js +++ b/__tests__/formats/swiftFile.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { iosSwiftAnySwift } = fileFormats; const originalFile = { destination: '__output/', - format: 'ios-swift/any.swift', + format: iosSwiftAnySwift, options: { className: 'StyleDictionary', }, @@ -42,10 +45,10 @@ const tokens = { }, }; -const format = formats['ios-swift/any.swift']; +const format = formats[iosSwiftAnySwift]; describe('formats', () => { - describe('ios-swift/any.swift', () => { + describe(iosSwiftAnySwift, () => { beforeEach(() => { file = structuredClone(originalFile); }); diff --git a/__tests__/formats/typeScriptEs6Declarations.test.js b/__tests__/formats/typeScriptEs6Declarations.test.js index 5e6590cc9..7feed21c1 100644 --- a/__tests__/formats/typeScriptEs6Declarations.test.js +++ b/__tests__/formats/typeScriptEs6Declarations.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { typescriptEs6Declarations } = fileFormats; const file = { destination: '__output/', - format: 'typescript/es6-declarations', + format: typescriptEs6Declarations, }; const tokens = { @@ -36,10 +39,10 @@ const tokens = { }, }; -const format = formats['typescript/es6-declarations']; +const format = formats[typescriptEs6Declarations]; describe('formats', () => { - describe('typescript/es6-declarations', () => { + describe(typescriptEs6Declarations, () => { it('should be a valid TS file', async () => { const output = await format( createFormatArgs({ diff --git a/__tests__/formats/typeScriptModuleDeclarations.test.js b/__tests__/formats/typeScriptModuleDeclarations.test.js index c0a4a5dc4..ce16cb04d 100644 --- a/__tests__/formats/typeScriptModuleDeclarations.test.js +++ b/__tests__/formats/typeScriptModuleDeclarations.test.js @@ -14,10 +14,13 @@ import { expect } from 'chai'; import formats from '../../lib/common/formats.js'; import createFormatArgs from '../../lib/utils/createFormatArgs.js'; import { convertTokenData } from '../../lib/utils/convertTokenData.js'; +import { formats as fileFormats } from '../../lib/enums/index.js'; + +const { typescriptModuleDeclarations } = fileFormats; const file = { destination: '__output/', - format: 'typescript/module-declarations', + format: typescriptModuleDeclarations, filter: { type: 'color' }, }; @@ -27,10 +30,10 @@ const tokens = { }, }; -const format = formats['typescript/module-declarations'].bind(file); +const format = formats[typescriptModuleDeclarations].bind(file); describe('formats', () => { - describe('typescript/module-declarations', () => { + describe(typescriptModuleDeclarations, () => { it('should be a valid TS file', async () => { const output = await format( createFormatArgs({ diff --git a/__tests__/register/overwrite.test.js b/__tests__/register/overwrite.test.js index 5badd68e8..0b234b877 100644 --- a/__tests__/register/overwrite.test.js +++ b/__tests__/register/overwrite.test.js @@ -2,10 +2,14 @@ import StyleDictionary from 'style-dictionary'; import { expect } from 'chai'; import transformBuiltins from '../../lib/common/transforms.js'; import { isNode } from '../../lib/utils/isNode.js'; +import { transforms, transformTypes } from '../../lib/enums/index.js'; + +const { colorHex } = transforms; +const { value: transformTypeValue, name } = transformTypes; describe('Register overwrites', () => { const reset = () => { - StyleDictionary.hooks.transforms['color/hex'] = transformBuiltins['color/hex']; + StyleDictionary.hooks.transforms[colorHex] = transformBuiltins[colorHex]; }; beforeEach(() => { reset(); @@ -17,12 +21,12 @@ describe('Register overwrites', () => { it(`should allow overwriting built-in hooks on class, affecting any instance created AFTER doing so`, async () => { const sd1 = new StyleDictionary(); - const builtInHookName = 'color/hex'; + const builtInHookName = colorHex; const builtInHook = StyleDictionary.hooks.transforms[builtInHookName]; StyleDictionary.registerTransform({ ...builtInHook, name: builtInHookName, - type: 'name', + type: name, }); const sd2 = new StyleDictionary(); @@ -33,28 +37,28 @@ describe('Register overwrites', () => { // fail purely due to multiple test files writing stuff to the Register class // TODO: In the future we may be able to run mocha test files in parallel processes if (!isNode) { - expect(sd1.hooks.transforms[builtInHookName].type).to.equal('value'); - expect(sd2.hooks.transforms[builtInHookName].type).to.equal('name'); - expect(sd3.hooks.transforms[builtInHookName].type).to.equal('name'); + expect(sd1.hooks.transforms[builtInHookName].type).to.equal(transformTypeValue); + expect(sd2.hooks.transforms[builtInHookName].type).to.equal(name); + expect(sd3.hooks.transforms[builtInHookName].type).to.equal(name); } }); it(`should allow overwriting built-in hooks on instance, affecting only that instance or its direct extensions`, async () => { const sd1 = new StyleDictionary(); - const builtInHookName = 'color/hex'; + const builtInHookName = colorHex; const builtInHook = StyleDictionary.hooks.transforms[builtInHookName]; sd1.registerTransform({ ...builtInHook, name: builtInHookName, - type: 'name', + type: name, }); const sd2 = new StyleDictionary(); const sd3 = await sd2.extend(); - expect(sd1.hooks.transforms[builtInHookName].type).to.equal('name'); - expect(sd2.hooks.transforms[builtInHookName].type).to.equal('value'); - expect(sd3.hooks.transforms[builtInHookName].type).to.equal('value'); + expect(sd1.hooks.transforms[builtInHookName].type).to.equal(name); + expect(sd2.hooks.transforms[builtInHookName].type).to.equal(transformTypeValue); + expect(sd3.hooks.transforms[builtInHookName].type).to.equal(transformTypeValue); }); }); diff --git a/__tests__/register/preprocessor.test.js b/__tests__/register/preprocessor.test.js index da846759e..d73d0ea63 100644 --- a/__tests__/register/preprocessor.test.js +++ b/__tests__/register/preprocessor.test.js @@ -13,6 +13,7 @@ import { expect } from 'chai'; import StyleDictionary from 'style-dictionary'; import { registerSuite } from './register.suite.js'; +import { formats } from '../../lib/enums/index.js'; registerSuite({ config: { @@ -188,7 +189,7 @@ describe('register/transformGroup', async () => { prefix: 'foo', files: [ { - format: 'css/variables', + format: formats.cssVariables, }, ], }, diff --git a/__tests__/register/transform.test.js b/__tests__/register/transform.test.js index 4a45b1bf0..8f6e878a7 100644 --- a/__tests__/register/transform.test.js +++ b/__tests__/register/transform.test.js @@ -14,23 +14,26 @@ import { expect } from 'chai'; import StyleDictionary from 'style-dictionary'; import { registerSuite } from './register.suite.js'; import transformBuiltins from '../../lib/common/transforms.js'; +import { transformTypes } from '../../lib/enums/index.js'; + +const { value: transformTypeValue, name } = transformTypes; const transformPxAppender = { name: 'px-appender', - type: 'value', + type: transformTypeValue, transform: (token) => `${token.value}px`, }; const transformValueIncrementer = { name: 'value-incrementer', - type: 'value', + type: transformTypeValue, filter: (token) => typeof token.value === 'number', transform: (token) => token.value + 1, }; registerSuite({ config: { - type: 'value', + type: transformTypeValue, transform: () => {}, }, registerMethod: 'registerTransform', @@ -194,7 +197,7 @@ describe('register', () => { it('should error if name is not a string', () => { expect(() => { StyleDictionaryExtended.registerTransform({ - type: 'name', + type: name, }); }).to.throw('name must be a string'); }); @@ -202,7 +205,7 @@ describe('register', () => { it('should error if filter is not a function', () => { expect(() => { StyleDictionaryExtended.registerTransform({ - type: 'name', + type: name, name: 'name', filter: 'foo', }); @@ -212,7 +215,7 @@ describe('register', () => { it('should error if transform is not a function', () => { expect(() => { StyleDictionaryExtended.registerTransform({ - type: 'name', + type: name, name: 'name', filter: function () { return true; @@ -224,7 +227,7 @@ describe('register', () => { it('should work if type, filter, and transform are all proper', () => { StyleDictionaryExtended.registerTransform({ - type: 'name', + type: name, name: 'foo', filter: function () { return true; @@ -234,7 +237,7 @@ describe('register', () => { }, }); expect(typeof StyleDictionaryExtended.hooks.transforms.foo).to.equal('object'); - expect(StyleDictionaryExtended).to.have.nested.property('hooks.transforms.foo.type', 'name'); + 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'); }); @@ -242,7 +245,7 @@ describe('register', () => { 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(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 9410e273f..808226acc 100644 --- a/__tests__/register/transformGroup.test.js +++ b/__tests__/register/transformGroup.test.js @@ -13,12 +13,14 @@ import { expect } from 'chai'; import StyleDictionary from 'style-dictionary'; import { registerSuite } from './register.suite.js'; +import { transforms } from '../../lib/enums/index.js'; const dummyTransformName = 'transformGroup.test.js'; +const { sizePx } = transforms; registerSuite({ config: { - transforms: ['size/px'], + transforms: [sizePx], }, registerMethod: 'registerTransformGroup', prop: 'transformGroups', @@ -104,22 +106,22 @@ describe('register/transformGroup', async () => { it('should work if everything is good', () => { StyleDictionaryExtended.registerTransformGroup({ name: 'foo', - transforms: ['size/px'], + transforms: [sizePx], }); 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'); + expect(StyleDictionaryExtended.hooks.transformGroups.foo[0]).to.equal(sizePx); }); it('should properly pass the registered transformGroup to instances when extending', async () => { const StyleDictionaryBase = new StyleDictionary({}); StyleDictionaryBase.registerTransformGroup({ name: 'bar', - transforms: ['size/px'], + transforms: [sizePx], }); 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'); + expect(SDE2.hooks.transformGroups.bar[0]).to.equal(sizePx); }); }); diff --git a/__tests__/transform/config.test.js b/__tests__/transform/config.test.js index 5319ac760..b8658aea2 100644 --- a/__tests__/transform/config.test.js +++ b/__tests__/transform/config.test.js @@ -14,12 +14,15 @@ import { expect } from 'chai'; import { restore, stubMethod } from 'hanbi'; import transformConfig from '../../lib/transform/config.js'; import chalk from 'chalk'; +import { logWarningLevels, logVerbosityLevels, transformTypes } from '../../lib/enums/index.js'; + +const { attribute } = transformTypes; const dictionary = { hooks: { transforms: { fooTransform: { - type: 'attribute', + type: attribute, transform: function () { return { bar: 'foo' }; }, @@ -65,21 +68,21 @@ None of "barTransform", "bazTransform" match the name of a registered transform. transforms: { fooTransform: { name: 'fooTransform', - type: 'attribute', + type: attribute, transform: function () { return { foo: 'foo' }; }, }, barTransform: { name: 'barTransform', - type: 'attribute', + type: attribute, transform: function () { return { bar: 'bar' }; }, }, quxTransform: { name: 'quxTransform', - type: 'attribute', + type: attribute, transform: function () { return { qux: 'qux' }; }, @@ -126,7 +129,7 @@ None of "barTransform", "bazTransform" match the name of a registered transform. it('throws if an action is used without a clean function with log.warnings set to error', () => { const cfg = { - log: { warnings: 'error' }, + log: { warnings: logWarningLevels.error }, hooks: { actions: { foo: {}, @@ -144,7 +147,7 @@ None of "barTransform", "bazTransform" match the name of a registered transform. it('does not warn user at all when log.verbosity silent is used', () => { const cfg = { - log: { verbosity: 'silent' }, + log: { verbosity: logVerbosityLevels.silent }, hooks: { actions: { foo: {}, diff --git a/__tests__/transform/object.test.js b/__tests__/transform/object.test.js index fc22eb960..61fb05f7a 100644 --- a/__tests__/transform/object.test.js +++ b/__tests__/transform/object.test.js @@ -12,17 +12,20 @@ */ import { expect } from 'chai'; import transformObject from '../../lib/transform/object.js'; +import { transformTypes } from '../../lib/enums/index.js'; + +const { value: transformTypeValue, name, attribute } = transformTypes; const config = { transforms: [ { - type: 'attribute', + type: attribute, transform: function () { return { foo: 'bar' }; }, }, { - type: 'attribute', + type: attribute, // verify async transforms to also work properly transform: async function () { await new Promise((resolve) => setTimeout(resolve, 100)); @@ -30,7 +33,7 @@ const config = { }, }, { - type: 'name', + type: name, filter: function (token) { return token.attributes.foo === 'bar'; }, @@ -41,7 +44,7 @@ const config = { }, }, { - type: 'value', + type: transformTypeValue, filter: function (token) { return token.path[0] === 'spacing'; }, diff --git a/__tests__/transform/tokenSetup.test.js b/__tests__/transform/tokenSetup.test.js index 6ebf79dd6..cade6377f 100644 --- a/__tests__/transform/tokenSetup.test.js +++ b/__tests__/transform/tokenSetup.test.js @@ -55,7 +55,7 @@ describe('transform', () => { it('should use the name on the property if set', () => { const name = 'name'; - const test = tokenSetup({ value: '#fff', name: name }, 'white', ['color', 'base']); + const test = tokenSetup({ value: '#fff', name }, 'white', ['color', 'base']); expect(test).to.have.property('name', name); }); diff --git a/__tests__/transform/transformToken.test.js b/__tests__/transform/transformToken.test.js index ff281c975..0975a3970 100644 --- a/__tests__/transform/transformToken.test.js +++ b/__tests__/transform/transformToken.test.js @@ -12,11 +12,14 @@ */ import { expect } from 'chai'; import transformToken from '../../lib/transform/token.js'; +import { transformTypes } from '../../lib/enums/index.js'; + +const { value: transformTypeValue, name, attribute } = transformTypes; const config = { transforms: [ { - type: 'attribute', + type: attribute, transform: function () { return { foo: 'bar', @@ -24,13 +27,13 @@ const config = { }, }, { - type: 'attribute', + type: attribute, transform: function () { return { bar: 'foo' }; }, }, { - type: 'name', + type: name, filter: function (prop) { return prop.attributes.foo === 'bar'; }, @@ -61,7 +64,7 @@ describe('transform', () => { { transforms: [ { - type: 'value', + type: transformTypeValue, transitive: true, transform: () => { return undefined; diff --git a/bin/style-dictionary.js b/bin/style-dictionary.js index ceb7db66d..6365a1513 100755 --- a/bin/style-dictionary.js +++ b/bin/style-dictionary.js @@ -10,9 +10,10 @@ 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'; +import { logWarningLevels, logVerbosityLevels } from '../lib/enums/index.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); - +const { silent, verbose } = logVerbosityLevels; const pkg = JSON5.parse(node_fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); function collect(val, arr) { @@ -111,10 +112,10 @@ function getSD(configPath, options) { let verbosity; let warnings; if (options.verbose || options.silent) { - verbosity = options.verbose ? 'verbose' : 'silent'; + verbosity = options.verbose ? verbose : silent; } if (options.warn === false) { - warnings = 'disabled'; + warnings = logWarningLevels.disabled; } return new StyleDictionary(configPath, { verbosity, warnings }); } diff --git a/docs/src/components/sd-playground.ts b/docs/src/components/sd-playground.ts index 63b826039..5c463ea68 100644 --- a/docs/src/components/sd-playground.ts +++ b/docs/src/components/sd-playground.ts @@ -12,6 +12,7 @@ import { analyzeDependencies } from '../utils/analyzeDependencies.js'; import { downloadZIP } from '../../../lib/utils/downloadFile.js'; import type SlRadioGroup from '@shoelace-style/shoelace/dist/components/radio-group/radio-group.js'; import type { Config } from '../../../types/Config.js'; +import { formats, transformGroups } from '../../../lib/enums/index.js'; const defaults = { tokens: { @@ -25,11 +26,11 @@ const defaults = { config: { platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, }, ], }, diff --git a/docs/src/content/docs/examples/splitting-output-files.md b/docs/src/content/docs/examples/splitting-output-files.md index 7ba191a02..f73314f1a 100644 --- a/docs/src/content/docs/examples/splitting-output-files.md +++ b/docs/src/content/docs/examples/splitting-output-files.md @@ -258,11 +258,15 @@ The trick is to dynamically generate the files array, generate one for each outp ``` ```js config +import { formats, transformGroups } from 'style-dictionary/enums'; + +const { cssVariables } = formats; + function generateComponentFiles(components) { return components.map((comp) => ({ // output the component tokens in the right folder and file e.g. components/button/button-vars.css destination: `components/${comp}/${comp}-vars.css`, - format: 'css/variables', + format: cssVariables, // only include the tokens that are inside this component token group filter: (token) => token.path[0] === comp, })); @@ -272,11 +276,11 @@ export default { source: ['tokens.json'], platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'global.css', - format: 'css/variables', + format: cssVariables, // filter only the tokens that are inside the global object filter: (token) => token.path[0] === 'global', }, diff --git a/docs/src/content/docs/getting-started/installation.mdx b/docs/src/content/docs/getting-started/installation.mdx index 30ba502fc..af8342fdd 100644 --- a/docs/src/content/docs/getting-started/installation.mdx +++ b/docs/src/content/docs/getting-started/installation.mdx @@ -320,17 +320,18 @@ The StyleDictionary constructor can also take a [configuration](/reference/confi ```javascript title="build-tokens.js" import StyleDictionary from 'style-dictionary'; +import { formats, transformGroups } from 'style-dictionary/enums'; const sd = new StyleDictionary({ source: ['tokens/**/*.json'], platforms: { scss: { - transformGroup: 'scss', + transformGroup: transformGroups.scss, buildPath: 'build/', files: [ { destination: 'variables.scss', - format: 'scss/variables', + format: formats.scssVariables, }, ], }, diff --git a/docs/src/content/docs/reference/Hooks/Formats/helpers.md b/docs/src/content/docs/reference/Hooks/Formats/helpers.md index b5efff8c1..bc49a4e5b 100644 --- a/docs/src/content/docs/reference/Hooks/Formats/helpers.md +++ b/docs/src/content/docs/reference/Hooks/Formats/helpers.md @@ -11,6 +11,7 @@ They are accessible at `style-dictionary/utils` entrypoint, you can read more ab ```javascript import StyleDictionary from 'style-dictionary'; import { fileHeader, formattedVariables } from 'style-dictionary/utils'; +import { propertyFormatNames } from 'style-dictionary/enums'; StyleDictionary.registerFormat({ name: 'myCustomFormat', @@ -20,7 +21,11 @@ StyleDictionary.registerFormat({ return ( header + ':root {\n' + - formattedVariables({ format: 'css', dictionary, outputReferences }) + + formattedVariables({ + format: propertyFormatNames.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 index b0a38617f..feba8ef36 100644 --- a/docs/src/content/docs/reference/Hooks/Formats/index.md +++ b/docs/src/content/docs/reference/Hooks/Formats/index.md @@ -144,15 +144,17 @@ It is also possible to provide a function instead of `true` or `false` to `outpu ```js // config.js +import { formats, transformGroups } from 'style-dictionary/enums'; + export default { source: ['tokens.json'], platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'variables.css', - format: 'css/variables', + format: formats.cssVariables, options: { // Look here 👇 outputReferences: (token, { dictionary, usesDtcg }) => { diff --git a/docs/src/content/docs/reference/Hooks/Formats/predefined.md b/docs/src/content/docs/reference/Hooks/Formats/predefined.md index c102c80d0..5ed292230 100644 --- a/docs/src/content/docs/reference/Hooks/Formats/predefined.md +++ b/docs/src/content/docs/reference/Hooks/Formats/predefined.md @@ -510,7 +510,7 @@ It is recommended to use the 'android/resources' format with a custom filter instead of this format: ```javascript title="config.js" -format: 'android/resources', +format: formats.androidResources, // formats enum for string 'android/resources' filter: { type: "color" } @@ -536,7 +536,7 @@ It is recommended to use the 'android/resources' format with a custom filter instead of this format: ```javascript title="config.js" -format: 'android/resources', +format: formats.androidResources, // formats enum for string 'android/resources' filter: { type: "dimension" } @@ -562,7 +562,7 @@ It is recommended to use the 'android/resources' format with a custom filter instead of this format: ```javascript title="config.js" -format: 'android/resources', +format: formats.androidResources, // formats enum for string 'android/resources' filter: { type: "dimension" } @@ -589,7 +589,7 @@ It is recommended to use the 'android/resources' format with a custom filter instead of this format: ```javascript title="config.js" -format: 'android/resources', +format: formats.androidResources, // formats enum for string 'android/resources' filter: { type: 'time' } @@ -616,7 +616,7 @@ It is recommended to use the 'android/resources' format with a custom filter instead of this format: ```javascript title="config.js" -format: 'android/resources', +format: formats.androidResources, // formats enum for string 'android/resources' filter: { type: 'content' } diff --git a/docs/src/content/docs/reference/Hooks/Transforms/index.md b/docs/src/content/docs/reference/Hooks/Transforms/index.md index 8fa28aed8..d8ef3b7d5 100644 --- a/docs/src/content/docs/reference/Hooks/Transforms/index.md +++ b/docs/src/content/docs/reference/Hooks/Transforms/index.md @@ -108,7 +108,7 @@ import { usesReferences } from 'style-dictionary/utils'; StyleDictionary.registerTransform({ name: '', - type: 'value', + type: transformTypes.value, transitive: true, transform: (token) => { const darkenModifier = token.darken; diff --git a/docs/src/content/docs/reference/Hooks/file-headers.md b/docs/src/content/docs/reference/Hooks/file-headers.md index f303a49f6..c9b087887 100644 --- a/docs/src/content/docs/reference/Hooks/file-headers.md +++ b/docs/src/content/docs/reference/Hooks/file-headers.md @@ -117,6 +117,8 @@ or platform-specific: ~ sd-playground ```js config +import { transformGroups } from 'style-dictionary/enums'; + export default { hooks: { fileHeaders: { @@ -129,13 +131,13 @@ export default { }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, options: { fileHeader: 'my-file-header', }, files: [ { - format: 'css/variables', + format: formats.cssVariables, destination: '_variables.css', }, ], diff --git a/docs/src/content/docs/reference/Hooks/filters.md b/docs/src/content/docs/reference/Hooks/filters.md index c985a6d2b..f0ad424fe 100644 --- a/docs/src/content/docs/reference/Hooks/filters.md +++ b/docs/src/content/docs/reference/Hooks/filters.md @@ -114,6 +114,8 @@ export default { ``` ```js config +import { formats, transformGroups } from 'style-dictionary/enums'; + export default { hooks: { filters: { @@ -124,10 +126,10 @@ export default { }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { - format: 'css/variables', + format: formats.cssVariables, destination: '_variables.css', filter: 'no-colors', }, diff --git a/docs/src/content/docs/reference/Utils/format-helpers.md b/docs/src/content/docs/reference/Utils/format-helpers.md index 330eee8e0..da7551b3c 100644 --- a/docs/src/content/docs/reference/Utils/format-helpers.md +++ b/docs/src/content/docs/reference/Utils/format-helpers.md @@ -9,6 +9,7 @@ They are accessible at `style-dictionary/utils` entrypoint. ```javascript import StyleDictionary from 'style-dictionary'; import { fileHeader, formattedVariables } from 'style-dictionary/utils'; +import { propertyFormatNames } from 'style-dictionary/enums'; StyleDictionary.registerFormat({ name: 'myCustomFormat', @@ -18,7 +19,11 @@ StyleDictionary.registerFormat({ return ( header + ':root {\n' + - formattedVariables({ format: 'css', dictionary, outputReferences }) + + formattedVariables({ + format: propertyFormatNames.css, + dictionary, + outputReferences, + }) + '\n}\n' ); }, @@ -53,6 +58,8 @@ which uses: prefix, indentation, separator, suffix, and commentStyle. Example: ```javascript title="build-tokens.js" +import { propertyFormatNames } from 'style-dictionary/enums'; + StyleDictionary.registerFormat({ name: 'myCustomFormat', format: function ({ dictionary, options }) { @@ -60,7 +67,7 @@ StyleDictionary.registerFormat({ const formatProperty = createPropertyFormatter({ outputReferences, dictionary, - format: 'css', + format: propertyFormatNames.css, }); return dictionary.allTokens.map(formatProperty).join('\n'); }, @@ -75,21 +82,23 @@ This is for creating the comment at the top of generated files with the generate 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`. | +| 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'`. There is an [enum-like JS object](/reference/enums#comment-styles) `commentStyles` available for import. | +| `options.commentPosition` | `string` | `'above'` or `'inline'`, so either above the token or inline with the token. There is an [enum-like JS object](/reference/enums#comment-positions) `commentPositions` available for import. | +| `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" +import { commentStyles } from 'style-dictionary/enums'; + StyleDictionary.registerFormat({ name: 'myCustomFormat', format: async ({ dictionary, file }) => { - const header = await fileHeader({ file, commentStyle: 'short' }); + const header = await fileHeader({ file, commentStyle: commentStyles.short }); return ( header + dictionary.allTokens.map((token) => `${token.name} = ${token.value};`).join('\n') ); @@ -122,11 +131,13 @@ This is used to create lists of variables like Sass variables or CSS custom prop Example: ```js title="build-tokens.js" +import { propertyFormatNames } from 'style-dictionary/enums'; + StyleDictionary.registerFormat({ name: 'myCustomFormat', format: function ({ dictionary, options }) { return formattedVariables({ - format: 'less', + format: propertyFormatNames.less, dictionary, outputReferences: options.outputReferences, }); diff --git a/docs/src/content/docs/reference/Utils/references.md b/docs/src/content/docs/reference/Utils/references.md index 557be1930..247f3cae8 100644 --- a/docs/src/content/docs/reference/Utils/references.md +++ b/docs/src/content/docs/reference/Utils/references.md @@ -110,6 +110,7 @@ You can use the `getReferences` utility to create your own custom formats that h ```js title="build-tokens.js" import StyleDictionary from 'style-dictionary'; import { usesReferences, getReferences, fileHeader } from 'style-dictionary/utils'; +import { transformGroups } from 'style-dictionary/enums'; const sd = new StyleDictionary({ tokens: { @@ -146,7 +147,7 @@ const sd = new StyleDictionary({ }, platforms: { es6: { - transformGroup: 'js', + transformGroup: transformGroups.js, files: [ { format: 'es6', @@ -252,6 +253,7 @@ What that means is that you usually have to either adjust your filter or disable ```javascript title="build-tokens.js" import StyleDictionary from 'style-dictionary'; import { outputReferencesFilter } from 'style-dictionary/utils'; +import { formats, transformGroups } from 'style-dictionary/enums'; const sd = new StyleDictionary({ tokens: { @@ -282,11 +284,11 @@ const sd = new StyleDictionary({ }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, filter: (token) => token.name !== 'colors-grey', options: { // returns false for the shadow token because it refs color-grey which is filtered out @@ -345,15 +347,16 @@ Live Demo: ```js config import { outputReferencesFilter } from 'style-dictionary/utils'; +import { formats, transformGroups } from 'style-dictionary/enums'; export default { platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, filter: (token) => token.name !== 'colors-grey', options: { // returns false for the shadow token because it refs color-grey which is filtered out @@ -374,6 +377,7 @@ the value has changed through a transitive transform compared to the original va ```javascript title="build-tokens.js" import StyleDictionary from 'style-dictionary'; import { outputReferencesTransformed } from 'style-dictionary/utils'; +import { formats, transformGroups } from 'style-dictionary/enums'; const sd = new StyleDictionary({ tokens: { @@ -388,7 +392,7 @@ const sd = new StyleDictionary({ }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.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 @@ -396,7 +400,7 @@ const sd = new StyleDictionary({ files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, options: { outputReferences: outputReferencesTransformed, }, @@ -438,16 +442,17 @@ Live Demo: ```js config import { outputReferencesTransformed } from 'style-dictionary/utils'; +import { formats, transformGroups } from 'style-dictionary/enums'; export default { platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, transforms: ['ts/color/css/hexrgba'], files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, options: { outputReferences: outputReferencesTransformed, }, @@ -473,15 +478,16 @@ 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'; +import { formats, transformGroups } from 'style-dictionary/enums'; const sd = new StyleDictionary({ platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'vars.css', - format: 'css/variables', + format: formats.cssVariables, options: { outputReferences: (token, options) => outputReferencesFilter(token, options) && outputReferencesTransformed(token, options), diff --git a/docs/src/content/docs/reference/api.mdx b/docs/src/content/docs/reference/api.mdx index ca214d266..b2918e6d1 100644 --- a/docs/src/content/docs/reference/api.mdx +++ b/docs/src/content/docs/reference/api.mdx @@ -10,31 +10,32 @@ import { Badge } from '@astrojs/starlight/components'; 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 | +| 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. There is an [enum-like JS object](/reference/enums#log-verbosity-levels) `logVerbosityLevels` available, that you can import. | +| `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. There is an [enum-like JS object](/reference/enums#log-warning-levels) `logWarningLevels` available, that you can import. | +| `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'; +import { formats, transformGroups } from 'style-dictionary/enums'; const sd = new StyleDictionary('config.json'); const sdTwo = new StyleDictionary({ source: ['tokens/*.json'], platforms: { scss: { - transformGroup: 'scss', + transformGroup: transformGroups.scss, buildPath: 'build/', files: [ { destination: 'variables.scss', - format: 'scss/variables', + format: formats.scssVariables, }, ], }, @@ -50,10 +51,10 @@ 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; +import { formats, transformGroups } from 'style-dictionary/enums'; +const { Volume } = memfs; const vol = new Volume(); - const sd = new StyleDictionary( { tokens: { @@ -66,11 +67,11 @@ const sd = new StyleDictionary( }, platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, files: [ { destination: 'variables.css', - format: 'css/variables', + format: formats.cssVariables, }, ], }, @@ -80,7 +81,6 @@ const sd = new StyleDictionary( ); await sd.buildAllPlatforms(); - vol.readFileSync('/variables.css'); /** * :root { @@ -100,11 +100,11 @@ 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. | +| 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. There is an [enum-like JS object](/reference/enums#log-verbosity-levels) `logVerbosityLevels` available, that you can import. | +| `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.There is an [enum-like JS object](/reference/enums#log-warning-levels) `logWarningLevels` available, that you can import. | --- @@ -116,19 +116,20 @@ type extend = (config: Config | string, options: Options) ⇒ Promise token.path.join('_').toUpperCase(), }, }, diff --git a/docs/src/content/docs/reference/enums.md b/docs/src/content/docs/reference/enums.md new file mode 100644 index 000000000..9acce1e1f --- /dev/null +++ b/docs/src/content/docs/reference/enums.md @@ -0,0 +1,305 @@ +--- +title: Enums +sidebar: + order: 4 +--- + +This page documents the enums introduced in Style-Dictionary. Enums provide a set of named constants that enhance code maintainability, readability, and type safety. + +Although Style-Dictionary offers TypeScript type definition files, it cannot provide actual TypeScript enums because its code base is written in JavaScript using JSDocs type annotations, and real enums are a TypeScript-only feature. To still leverage the benefits of enums and reduce the use of hardcoded strings throughout the JavaScript codebase of Style-Dictionary itself, we have introduced enum-like JavaScript objects, which provide the same kind of type safety, but can also be used in JavaScript projects. + +These enum-like objects are used internally within Style-Dictionary, and you can also use them in your own configurations, whether you are working with TypeScript or JavaScript. + +## Enums Usage Example + +The following shows how to use some of the provided enum-like objects in an exmaple Style-Dictionary configuration. + +```javascript +import StyleDictionary from 'style-dictionary'; +import { + formats, + logBrokenReferenceLevels, + logWarningLevels, + logVerbosityLevels, + transformGroups, + transforms, +} from 'style-dictionary/enums'; + +const sd = new StyleDictionary({ + source: ['tokens/*.json'], + platforms: { + scss: { + transformGroup: transformGroups.scss, + transforms: [transforms.nameKebab], + buildPath: 'build/', + files: [ + { + destination: 'variables.scss', + format: formats.scssVariables, + }, + ], + }, + }, + log: { + warnings: logWarningLevels.warn, + verbosity: logVerbosityLevels.verbose, + errors: { + brokenReferences: logBrokenReferenceLevels.throw, + }, + }, +}); +``` + +### Read-Only Enums in Typescript + +Optionally, if you want to ensure that the enums are completely read-only, you can use `as const`, like it is described in [the Typescript docs](https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums). +This means a type error will also be shown if the enum itself is being assigned to or if something attempts to introduce or delete a member. + +```typescript +import { formats, transforms } from 'style-dictionary/enums'; + +const formatsReadOnly = formats as const; +``` + +## List of Enums + +### Actions + +```javascript +// enums/actions.js +export const actions = { + androidCopyImages: 'android/copyImages', + copyAssets: 'copy_assets', +}; +``` + +### Comment Positions + +```javascript +// enums/commentPositions.js +export const commentPositions = { + above: 'above', + inline: 'inline', +}; +``` + +### Comment Styles + +```javascript +// enums/commentStyles.js +export const commentStyles = { + short: 'short', + long: 'long', + none: 'none', +}; +``` + +### File Header Comment Styles + +```javascript +// enums/fileHeaderCommentStyles.js +export const fileHeaderCommentStyles = { + short: 'short', + long: 'long', + xml: 'xml', +}; +``` + +### Formats + +```javascript +// enums/formats.js +export const formats = { + androidColors: 'android/colors', + androidDimens: 'android/dimens', + androidFontDimens: 'android/fontDimens', + androidIntegers: 'android/integers', + androidResources: 'android/resources', + androidStrings: 'android/strings', + composeObject: 'compose/object', + cssVariables: 'css/variables', + flutterClassDart: 'flutter/class.dart', + iosColorsH: 'ios/colors.h', + iosColorsM: 'ios/colors.m', + iosMacros: 'ios/macros', + iosPlist: 'ios/plist', + iosSingletonH: 'ios/singleton.h', + iosSingletonM: 'ios/singleton.m', + iosStaticH: 'ios/static.h', + iosStaticM: 'ios/static.m', + iosStringsH: 'ios/strings.h', + iosStringsM: 'ios/strings.m', + iosSwiftAnySwift: 'ios-swift/any.swift', + iosSwiftClassSwift: 'ios-swift/class.swift', + iosSwiftEnumSwift: 'ios-swift/enum.swift', + javascriptEs6: 'javascript/es6', + javascriptModule: 'javascript/module', + javascriptModuleFlat: 'javascript/module-flat', + javascriptObject: 'javascript/object', + javascriptUmd: 'javascript/umd', + json: 'json', + jsonNested: 'json/nested', + jsonFlat: 'json/flat', + sketchPalette: 'sketchPalette', + sketchPaletteV2: 'sketch/palette/v2', + lessIcons: 'less/icons', + lessVariables: 'less/variables', + scssIcons: 'scss/icons', + scssMapDeep: 'scss/map-deep', + scssMapFlat: 'scss/map-flat', + scssVariables: 'scss/variables', + stylusVariables: 'stylus/variables', + typescriptEs6Declarations: 'typescript/es6-declarations', + typescriptModuleDeclarations: 'typescript/module-declarations', +}; +``` + +### Log Broken Reference Levels + +```javascript +// enums/logBrokenReferenceLevels.js +export const logBrokenReferenceLevels = { + throw: 'throw', + console: 'console', +}; +``` + +### Log Verbosity Levels + +```javascript +// enums/logVerbosityLevels.js +export const logVerbosityLevels = { + default: 'default', + silent: 'silent', + verbose: 'verbose', +}; +``` + +### Log Warning Levels + +```javascript +// enums/logWarningLevels.js +export const logWarningLevels = { + warn: 'warn', + error: 'error', + disabled: 'disabled', +}; +``` + +### Property Format Names + +```javascript +// enums/propertyFormatNames.js +export const propertyFormatNames = { + css: 'css', + sass: 'sass', + less: 'less', + stylus: 'stylus', +}; +``` + +### Transform Groups + +```javascript +// enums/transformGroups.js +export const transformGroups = { + web: 'web', + js: 'js', + scss: 'scss', + css: 'css', + less: 'less', + html: 'html', + android: 'android', + compose: 'compose', + ios: 'ios', + iosSwift: 'ios-swift', + iosSwiftSeparate: 'ios-swift-separate', + assets: 'assets', + flutter: 'flutter', + flutterSeparate: 'flutter-separate', + reactNative: 'react-native', +}; +``` + +### Transforms + +```javascript +// enums/transforms.js +export const transforms = { + attributeCti: 'attribute/cti', + attributeColor: 'attribute/color', + nameHuman: 'name/human', + nameCamel: 'name/camel', + nameKebab: 'name/kebab', + nameSnake: 'name/snake', + nameConstant: 'name/constant', + namePascal: 'name/pascal', + colorRgb: 'color/rgb', + colorHsl: 'color/hsl', + colorHsl4: 'color/hsl-4', + colorHex: 'color/hex', + colorHex8: 'color/hex8', + colorHex8android: 'color/hex8android', + colorComposeColor: 'color/composeColor', + colorUIColor: 'color/UIColor', + colorUIColorSwift: 'color/UIColorSwift', + colorColorSwiftUI: 'color/ColorSwiftUI', + colorCss: 'color/css', + colorSketch: 'color/sketch', + sizeSp: 'size/sp', + sizeDp: 'size/dp', + sizeObject: 'size/object', + sizeRemToSp: 'size/remToSp', + sizeRemToDp: 'size/remToDp', + sizePx: 'size/px', + sizeRem: 'size/rem', + sizeRemToPt: 'size/remToPt', + sizeComposeRemToSp: 'size/compose/remToSp', + sizeComposeRemToDp: 'size/compose/remToDp', + sizeComposeEm: 'size/compose/em', + sizeSwiftRemToCGFloat: 'size/swift/remToCGFloat', + sizeRemToPx: 'size/remToPx', + sizePxToRem: 'size/pxToRem', + htmlIcon: 'html/icon', + contentQuote: 'content/quote', + contentObjCLiteral: 'content/objC/literal', + contentSwiftLiteral: 'content/swift/literal', + timeSeconds: 'time/seconds', + fontFamilyCss: 'fontFamily/css', + cubicBezierCss: 'cubicBezier/css', + strokeStyleCssShorthand: 'strokeStyle/css/shorthand', + borderCssShorthand: 'border/css/shorthand', + typographyCssShorthand: 'typography/css/shorthand', + transitionCssShorthand: 'transition/css/shorthand', + shadowCssShorthand: 'shadow/css/shorthand', + assetUrl: 'asset/url', + assetBase64: 'asset/base64', + assetPath: 'asset/path', + assetObjCLiteral: 'asset/objC/literal', + assetSwiftLiteral: 'asset/swift/literal', + colorHex8flutter: 'color/hex8flutter', + contentFlutterLiteral: 'content/flutter/literal', + assetFlutterLiteral: 'asset/flutter/literal', + sizeFlutterRemToDouble: 'size/flutter/remToDouble', +}; +``` + +### Transform Types + +```javascript +// enums/transformTypes.js +export const transformTypes = { + attribute: 'attribute', + name: 'name', + value: 'value', +}; +``` + +## Benefits of Using Enums + +Enums, or enumerations, offer a robust way to define a set of named constants in your code. Unlike hardcoded string values, enums provide several key benefits: + +1. **Consistency**: Enums centralize the definition of constants, making it easier to manage and update them across your codebase. This reduces the risk of typos and inconsistencies that can occur with hardcoded strings. This improves maintainability. +2. **Readability**: By using descriptive names for constants, enums make your code more readable and self-documenting. This helps other developers understand the purpose and usage of the constants without needing to refer to external documentation. +3. **Type Safety**: Enums can provide better type checking during development, catching errors at compile time rather than runtime. This ensures that only valid values are used, reducing the likelihood of bugs. +4. **Future-proofing**: Enums offer greater flexibility for future changes. When you need to add or modify values, you can do so in a single location without having to search and replace hardcoded strings throughout your code. This also means that on the consumer side, such a change is not a breaking change. diff --git a/docs/src/content/docs/reference/logging.md b/docs/src/content/docs/reference/logging.md index cbf607ab0..da1a19907 100644 --- a/docs/src/content/docs/reference/logging.md +++ b/docs/src/content/docs/reference/logging.md @@ -7,13 +7,19 @@ sidebar: You can customize the logging behavior of Style Dictionary. ```js +import { + logBrokenReferenceLevels, + logVerbosityLevels, + logWarningLevels, +} from 'style-dictionary/enums'; + const sd = new StyleDictionary({ // these are the defaults log: { - warnings: 'warn', // 'warn' | 'error' | 'disabled' - verbosity: 'default', // 'default' | 'silent' | 'verbose' + warnings: logWarningLevels.warn, // 'warn' | 'error' | 'disabled' + verbosity: logVerbosityLevels.default, // 'default' | 'silent' | 'verbose' errors: { - brokenReferences: 'throw', // 'throw' | 'console' + brokenReferences: logBrokenReferenceLevels.throw, // 'throw' | 'console' }, }, }); @@ -21,13 +27,13 @@ const sd = new StyleDictionary({ > `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. | +| 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'. There is an [enum-like JS object](/reference/enums#log-warning-levels) `logWarningLevels` available, that you can import. | +| `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. There is an [enum-like JS object](/reference/enums#log-verbosity-levels) `logVerbosityLevels` available, that you can import. | +| `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 is an [enum-like JS object](/reference/enums#log-broken-reference-levels) `logBrokenReferenceLevels` available, that you can import. | 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`: diff --git a/docs/src/utils/rollup-bundle.ts b/docs/src/utils/rollup-bundle.ts index 4239ab216..d5d7d041c 100644 --- a/docs/src/utils/rollup-bundle.ts +++ b/docs/src/utils/rollup-bundle.ts @@ -1,5 +1,6 @@ import * as sdFs from 'style-dictionary/fs'; import * as sdUtils from 'style-dictionary/utils'; +import * as sdEnums from 'style-dictionary/enums'; import { fs } from 'style-dictionary/fs'; import { rollup } from '@rollup/browser'; import { v4 as uuidv4 } from 'uuid'; @@ -20,14 +21,19 @@ import type { Plugin } from '@rollup/browser'; */ export async function bundle(inputString: string, _fs = fs) { const sdName = uuidv4(); - const sdFsName = uuidv4(); - const sdUtilsName = uuidv4(); + const names = { + fs: uuidv4(), + utils: uuidv4(), + enums: 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; + globalThis[names.fs] = sdFs; // @ts-expect-error not allowed to put stuff on global with generated type string index - globalThis[sdUtilsName] = sdUtils; + globalThis[names.utils] = sdUtils; + // @ts-expect-error not allowed to put stuff on global with generated type string index + globalThis[names.enums] = sdEnums; const rollupCfg = await rollup({ input: 'mod', @@ -47,44 +53,54 @@ export async function bundle(inputString: string, _fs = fs) { }, { name: 'sd-external', - // Naive and simplified regex version of rollup externals global plugin just for style-dictionary imports.. + // Naive and simplified regex version of rollup externals global plugin just for style-dictionary local imports.. + // Sorry for the spaghetti... transform(code) { let rewrittenCode = code; - const reg = /import (?.+?) from [',"]style-dictionary(?\/.+?)?[',"];?/; - let matchRes; + const reg = /import (?.+?) from [',"]style-dictionary(?\/.+?)?[',"];?/; + let matchRes: RegExpExecArray | null; while ((matchRes = reg.exec(rewrittenCode)) !== null) { if (matchRes.groups) { - let { id, entrypoint } = matchRes.groups; - let namedImport = id; - let originalNamedImport = id; + let { ids, entrypoint } = matchRes.groups; + let namedImport = ids; + let originalNamedImport = ids; let replacement = ''; - if (id.startsWith('{') && id.endsWith('}') && entrypoint) { - id = id.replace('{', '').replace('}', '').trim(); + const replaceCode = (code: string, replacement: string) => { + // Remove the import statement, replace the id wherever used with the global + return code + .replace((matchRes as RegExpExecArray)[0], '') + .replace(new RegExp(namedImport, 'g'), replacement); + }; + + // named imports + if (ids.startsWith('{') && ids.endsWith('}') && entrypoint) { + ids = ids.replace('{', '').replace('}', '').trim(); const entry = entrypoint.replace(/^\//, ''); - const asMatch = /(.+?) as (.+)/.exec(id); - if (asMatch && asMatch[2]) { - [, originalNamedImport, namedImport] = asMatch; - } else { - originalNamedImport = namedImport = id; - } + // could be multiple named imports + for (let id of ids.split(',')) { + id = id.trim(); + const asMatch = /(.+?) as (.+)/.exec(id); - if (entry === 'fs') { - replacement = `globalThis['${sdFsName}']['${originalNamedImport}']`; - } else if (entry === 'utils') { - replacement = `globalThis['${sdUtilsName}']['${originalNamedImport}']`; + if (asMatch && asMatch[2]) { + [, originalNamedImport, namedImport] = asMatch; + } else { + originalNamedImport = namedImport = id; + } + replacement = `globalThis['${ + names[entry as keyof typeof names] + }']['${originalNamedImport}']`; + + rewrittenCode = replaceCode(rewrittenCode, replacement); } } else { - // Remove the import statement, replace the id wherever used with the global + // default import, which we only have for style dictionary main entrypoint replacement = `globalThis['${sdName}']`; + rewrittenCode = replaceCode(rewrittenCode, replacement); } - rewrittenCode = rewrittenCode - .replace(matchRes[0], '') - .replace(new RegExp(namedImport, 'g'), replacement); } } - return rewrittenCode; }, }, diff --git a/docs/starlight-config.ts b/docs/starlight-config.ts index cafb4f4a3..15ad68ef1 100644 --- a/docs/starlight-config.ts +++ b/docs/starlight-config.ts @@ -51,6 +51,10 @@ export default { label: 'API', link: '/reference/api', }, + { + label: 'Enums', + link: '/reference/enums', + }, { label: 'Configuration', link: '/reference/config', diff --git a/examples/advanced/custom-parser/sd.config.js b/examples/advanced/custom-parser/sd.config.js index 0b102a608..e4b251fb0 100644 --- a/examples/advanced/custom-parser/sd.config.js +++ b/examples/advanced/custom-parser/sd.config.js @@ -1,4 +1,5 @@ import StyleDictionary from 'style-dictionary'; +import { formats, transformGroups } from 'style-dictionary/enums'; // You can use the .registerParser() method like this StyleDictionary.registerParser({ @@ -50,12 +51,12 @@ export default { source: [`tokens/**/*.json`], platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, buildPath: 'build/', files: [ { destination: 'variables.css', - format: 'css/variables', + format: formats.cssVariables, }, ], }, diff --git a/examples/advanced/custom-transforms/README.md b/examples/advanced/custom-transforms/README.md index 23554b24a..0f117a810 100644 --- a/examples/advanced/custom-transforms/README.md +++ b/examples/advanced/custom-transforms/README.md @@ -24,7 +24,7 @@ To declare a custom **transform**, you have to call the `registerTransform` meth ```js StyleDictionary.registerTransform({ name: 'ratio/%', - type: 'value', + type: transformTypes.value, filter: function (token) { return token.group === 'ratio'; }, diff --git a/examples/advanced/custom-transforms/build.js b/examples/advanced/custom-transforms/build.js index 3009318af..6bb08c2f8 100644 --- a/examples/advanced/custom-transforms/build.js +++ b/examples/advanced/custom-transforms/build.js @@ -1,8 +1,11 @@ import StyleDictionary from 'style-dictionary'; import { dirname } from 'path'; import { fileURLToPath } from 'url'; +import { transforms, transformGroups, transformTypes } from 'style-dictionary/enums'; const __dirname = dirname(fileURLToPath(import.meta.url)); +const { attributeCti, nameConstant, sizePx, colorCss, timeSeconds } = transforms; +const { value: transformTypeValue, name } = transformTypes; console.log('Build started...'); console.log('\n=============================================='); @@ -10,8 +13,8 @@ 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', + name: sizePx, // notice: the name is an override of an existing predefined method (yes, you can do it) + type: transformTypeValue, 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'; @@ -23,7 +26,7 @@ StyleDictionary.registerTransform({ StyleDictionary.registerTransform({ name: 'ratio/%', - type: 'value', + type: transformTypeValue, 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'; @@ -35,7 +38,7 @@ StyleDictionary.registerTransform({ StyleDictionary.registerTransform({ name: 'hexRGB/hexARGB', - type: 'value', + type: transformTypeValue, filter: function (token) { return token.type === 'color'; }, @@ -47,7 +50,7 @@ StyleDictionary.registerTransform({ StyleDictionary.registerTransform({ name: 'unitless/sp', - type: 'value', + type: transformTypeValue, filter: function (token) { return token.type === 'fontSize'; }, @@ -60,7 +63,7 @@ StyleDictionary.registerTransform({ StyleDictionary.registerTransform({ // this is a silly example, to show how you can apply transform to names name: 'name/squiggle', - type: 'name', + type: name, // notice: if you don't specify a filter, the transformation will be applied to all the tokens transform: function (token) { return token.path.join('~'); @@ -75,14 +78,14 @@ StyleDictionary.registerTransform({ 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/constant', 'size/px', 'color/css', 'time/seconds', 'ratio/%'], + transforms: [attributeCti, nameConstant, sizePx, colorCss, timeSeconds, '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[transformGroups.scss].concat([sizePx, 'ratio/%']), }); StyleDictionary.registerTransformGroup({ diff --git a/examples/advanced/font-face-rules/sd.config.js b/examples/advanced/font-face-rules/sd.config.js index 756315a60..fde36a1ac 100644 --- a/examples/advanced/font-face-rules/sd.config.js +++ b/examples/advanced/font-face-rules/sd.config.js @@ -1,10 +1,11 @@ import StyleDictionary from 'style-dictionary'; +import { transformTypes } from 'style-dictionary/enums'; // Register an "attribute" transform to codify the font's details // as named attributes. StyleDictionary.registerTransform({ name: 'attribute/font', - type: 'attribute', + type: transformTypes.attribute, transform: (prop) => ({ category: prop.path[0], type: prop.path[1], diff --git a/examples/advanced/format-helpers/sd.config.js b/examples/advanced/format-helpers/sd.config.js index 65c0ae9e6..8f8d3750b 100644 --- a/examples/advanced/format-helpers/sd.config.js +++ b/examples/advanced/format-helpers/sd.config.js @@ -4,6 +4,7 @@ import { formattedVariables, sortByReference, } from 'style-dictionary/utils'; +import { commentStyles, transformGroups } from 'style-dictionary/enums'; export default { hooks: { @@ -29,7 +30,7 @@ export default { // proper style. If the file has a custom file header defined, or // showFileHeader option, it will honor those. return ( - (await fileHeader({ file, commentStyle: 'short' })) + + (await fileHeader({ file, commentStyle: commentStyles.short })) + dictionary.allTokens // sortByReference returns a function that can be used as to sort // an array. This will sort the array so that references always @@ -76,7 +77,7 @@ export default { source: ['tokens/**/*'], platforms: { scss: { - transformGroup: 'scss', + transformGroup: transformGroups.scss, buildPath: 'build/', files: [ { diff --git a/examples/advanced/matching-build-files/config.js b/examples/advanced/matching-build-files/config.js index 3ac78aa4b..83bc5685c 100644 --- a/examples/advanced/matching-build-files/config.js +++ b/examples/advanced/matching-build-files/config.js @@ -1,15 +1,20 @@ import StyleDictionary from 'style-dictionary'; +import { formats, transforms, transformGroups } from 'style-dictionary/enums'; import tokens from './tokens/index.js'; +const { javascriptEs6, scssVariables } = formats; +const { attributeCti, nameCamel, sizePx, colorHex } = transforms; +const { scss } = transformGroups; + export default { source: ['tokens/**/*.json'], platforms: { 'esm/category': { buildPath: 'build/js/esm/', - transforms: ['attribute/cti', 'name/camel', 'size/px', 'color/hex'], + transforms: [attributeCti, nameCamel, sizePx, colorHex], files: tokens.map((tokenSet) => ({ destination: `${tokenSet}.js`, - format: 'javascript/es6', + format: javascriptEs6, filter: { attributes: { category: tokenSet, @@ -19,17 +24,17 @@ export default { }, 'esm/index': { buildPath: 'build/js/esm/', - transforms: ['attribute/cti', 'name/camel', 'size/px', 'color/hex'], + transforms: [attributeCti, nameCamel, sizePx, colorHex], files: [ { destination: `index.js`, - format: 'javascript/es6', + format: javascriptEs6, }, ], }, 'cjs/category': { buildPath: 'build/js/cjs/', - transforms: ['attribute/cti', 'name/camel', 'size/px', 'color/hex'], + transforms: [attributeCti, nameCamel, sizePx, colorHex], files: tokens.map((tokenSet) => ({ destination: `${tokenSet}.js`, format: 'custom/cjsmodule', @@ -42,7 +47,7 @@ export default { }, 'cjs/index': { buildPath: 'build/js/cjs/', - transforms: ['attribute/cti', 'name/camel', 'size/px', 'color/hex'], + transforms: [attributeCti, nameCamel, sizePx, colorHex], files: [ { destination: `index.js`, @@ -53,22 +58,22 @@ export default { // Web output in scss format scss: { - transformGroup: 'scss', + transformGroup: scss, buildPath: `build/scss/`, files: [ { destination: `tokens.scss`, - format: 'scss/variables', + format: scssVariables, }, ], }, // Web output in scss partialformat 'scss/category': { - transformGroup: 'scss', + transformGroup: scss, buildPath: `build/scss/`, files: tokens.map((tokenSet) => ({ destination: `_${tokenSet}.scss`, - format: 'scss/variables', + format: scssVariables, filter: { attributes: { category: tokenSet, diff --git a/examples/advanced/multi-brand-multi-platform/build.js b/examples/advanced/multi-brand-multi-platform/build.js index f2afc7fdc..af3d5bec5 100644 --- a/examples/advanced/multi-brand-multi-platform/build.js +++ b/examples/advanced/multi-brand-multi-platform/build.js @@ -1,7 +1,10 @@ import StyleDictionary from 'style-dictionary'; +import { formats, transformGroups } from 'style-dictionary/enums'; -// HAVE THE STYLE DICTIONARY CONFIG DYNAMICALLY GENERATED +const { androidColors, androidDimens, androidFontDimens, iosMacros, scssVariables } = formats; +const { web } = transformGroups; +// HAVE THE STYLE DICTIONARY CONFIG DYNAMICALLY GENERATED function getStyleDictionaryConfig(brand, platform) { return { source: [ @@ -11,12 +14,12 @@ function getStyleDictionaryConfig(brand, platform) { ], platforms: { web: { - transformGroup: 'web', + transformGroup: web, buildPath: `build/web/${brand}/`, files: [ { destination: 'tokens.scss', - format: 'scss/variables', + format: scssVariables, }, ], }, @@ -26,15 +29,15 @@ function getStyleDictionaryConfig(brand, platform) { files: [ { destination: 'tokens.colors.xml', - format: 'android/colors', + format: androidColors, }, { destination: 'tokens.dimens.xml', - format: 'android/dimens', + format: androidDimens, }, { destination: 'tokens.font_dimens.xml', - format: 'android/fontDimens', + format: androidFontDimens, }, ], }, @@ -44,7 +47,7 @@ function getStyleDictionaryConfig(brand, platform) { files: [ { destination: 'tokens.h', - format: 'ios/macros', + format: iosMacros, }, ], }, diff --git a/examples/advanced/node-modules-as-config-and-properties/config.js b/examples/advanced/node-modules-as-config-and-properties/config.js index 6363315f4..c3190992e 100644 --- a/examples/advanced/node-modules-as-config-and-properties/config.js +++ b/examples/advanced/node-modules-as-config-and-properties/config.js @@ -1,17 +1,22 @@ import StyleDictionary from 'style-dictionary'; +import { formats, transforms, transformGroups, transformTypes } from 'style-dictionary/enums'; +import tokens from './tokens.js'; // Rather than have Style Dictionary handle the merging of token files, // you could use node module export/require to do it yourself. This will // allow you to not have to copy object namespaces like you normally would. // Take a look at any of the .js files in components/ or tokens/ -import tokens from './tokens.js'; +const { cssVariables, scssVariables, javascriptEs6, json } = formats; +const { css, js } = transformGroups; +const { attributeCti, colorHex, colorRgb } = transforms; +const { value: transformTypeValue, name } = transformTypes; const buildPath = 'build/'; // You can still add custom transforms and formats like you // normally would and reference them in the config below. StyleDictionary.registerTransform({ name: 'myRegisteredTransform', - type: 'value', + type: transformTypeValue, filter: (token) => token.attributes.category === 'size', transform: (token) => `${parseInt(token.value) * 16}px`, }); @@ -39,7 +44,7 @@ export default { transforms: { // Now we can use the transform 'myTransform' below myTransform: { - type: 'name', + type: name, transform: (token) => token.path.join('_').toUpperCase(), }, }, @@ -58,7 +63,7 @@ export default { platforms: { custom: { // Using the custom transforms we defined above - transforms: ['attribute/cti', 'myTransform', 'myRegisteredTransform', 'color/hex'], + transforms: [attributeCti, 'myTransform', 'myRegisteredTransform', colorHex], buildPath: buildPath, files: [ { @@ -70,30 +75,30 @@ export default { }, css: { - transformGroup: 'css', + transformGroup: css, buildPath: buildPath, files: [ { destination: 'variables.css', - format: 'css/variables', + format: cssVariables, }, ], }, scss: { // This works, we can create new transform arrays on the fly and edit built-ins - transforms: StyleDictionary.hooks.transformGroups.scss.concat('color/rgb'), + transforms: StyleDictionary.hooks.scss.concat(colorRgb), buildPath: buildPath, files: [ { destination: 'variables.scss', - format: 'scss/variables', + format: scssVariables, }, ], }, js: { - transforms: StyleDictionary.hooks.transformGroups.js.concat('myRegisteredTransform'), + transforms: StyleDictionary.hooks.js.concat('myRegisteredTransform'), buildPath: buildPath, // If you want to get super fancy, you can use node modules // to create a tokens object first, and then you can @@ -101,7 +106,7 @@ export default { // output 1 file per color namespace. files: Object.keys(tokens.color).map((colorType) => ({ destination: `${colorType}.js`, - format: 'javascript/es6', + format: javascriptEs6, // Filters can be functions that return a boolean filter: (token) => token.attributes.type === colorType, })), @@ -109,12 +114,12 @@ export default { // You can still use built-in transformGroups and formats like before json: { - transformGroup: 'js', + transformGroup: js, buildPath: buildPath, files: [ { destination: 'tokens.json', - format: 'json', + format: json, }, ], }, diff --git a/examples/advanced/tokens-deprecation/build.js b/examples/advanced/tokens-deprecation/build.js index e2ffa7c7f..d1654ade7 100644 --- a/examples/advanced/tokens-deprecation/build.js +++ b/examples/advanced/tokens-deprecation/build.js @@ -1,5 +1,6 @@ import StyleDictionary from 'style-dictionary'; import { fileHeader } from 'style-dictionary/utils'; +import { commentStyles } from 'style-dictionary/enums'; import { dirname } from 'path'; import { fileURLToPath } from 'url'; import webScssTemplate from './templates/web-scss.template.js'; @@ -15,7 +16,7 @@ sd.registerFormat({ name: 'custom/format/scss', format: async ({ dictionary, file, options }) => { const { allTokens } = dictionary; - const header = await fileHeader({ file, commentStyle: 'long' }); + const header = await fileHeader({ file, commentStyle: commentStyles.long }); return webScssTemplate({ allTokens, file, options, header }); }, }); diff --git a/examples/advanced/transitive-transforms/sd.config.js b/examples/advanced/transitive-transforms/sd.config.js index 24327dc1f..170ad35f4 100644 --- a/examples/advanced/transitive-transforms/sd.config.js +++ b/examples/advanced/transitive-transforms/sd.config.js @@ -1,12 +1,15 @@ import StyleDictionary from 'style-dictionary'; import { usesReferences } from 'style-dictionary/utils'; +import { formats, transforms } from 'style-dictionary/enums'; import Color from 'colorjs.io'; +const { attributeCti, colorCss, nameKebab } = transforms; + const colorTransform = (token) => { const { value, modify = [] } = token; // This assumes "hex" format, if you want to support { h, s, l } format you have to do - // `new Color('hsl', [value.h, value.s, value.l]);` + // 'new Color('hsl', [value.h, value.s, value.l]);' const color = new Color(value); // defer until reference is resolved @@ -42,14 +45,14 @@ const colorTransform = (token) => { export default { // This will match any files ending in json or json5 // I am using json5 here so I can add comments in the token files for reference - source: [`tokens/**/*.@(json|json5)`], + source: ['tokens/**/*.@(json|json5)'], // I am directly defining transforms here // This would work if you were to call StyleDictionary.registerTransform() as well hooks: { transforms: { colorTransform: { - type: `value`, + type: 'value', // only transforms that have transitive: true will be applied to tokens // that alias/reference other tokens transitive: true, @@ -59,8 +62,8 @@ export default { // For backwards compatibility, all built-in transforms are not transitive // by default. This will make the 'color/css' transform transitive - 'color/css': { - ...StyleDictionary.hooks.transforms[`color/css`], + [colorCss]: { + ...StyleDictionary.hooks.transforms[colorCss], transitive: true, }, }, @@ -68,12 +71,12 @@ export default { platforms: { css: { - transforms: [`attribute/cti`, `name/kebab`, `colorTransform`, `color/css`], - buildPath: `build/`, + transforms: [attributeCti, nameKebab, 'colorTransform', colorCss], + buildPath: 'build/', files: [ { - destination: `variables.css`, - format: `css/variables`, + destination: 'variables.css', + format: formats.cssVariables, }, ], }, diff --git a/examples/advanced/variables-in-outputs/sd.config.js b/examples/advanced/variables-in-outputs/sd.config.js index 5cdaf35a5..5b46476d1 100644 --- a/examples/advanced/variables-in-outputs/sd.config.js +++ b/examples/advanced/variables-in-outputs/sd.config.js @@ -1,3 +1,8 @@ +import { formats, transformGroups } from 'style-dictionary/enums'; + +const { cssVariables, jsonNested, scssVariables } = formats; +const { css, js } = transformGroups; + export default { hooks: { formats: { @@ -37,13 +42,13 @@ export default { files: [ { destination: 'tokens.json', - format: 'json/nested', + format: jsonNested, }, ], }, js: { buildPath: 'build/', - transformGroup: 'js', + transformGroup: js, files: [ { destination: 'tokens.js', @@ -55,19 +60,19 @@ export default { ], }, css: { - transformGroup: 'css', + transformGroup: css, buildPath: 'build/', files: [ { destination: 'tokens.css', - format: 'css/variables', + format: cssVariables, options: { outputReferences: true, // new setting, if true will use variable references }, }, { destination: 'tokens.scss', - format: 'scss/variables', + format: scssVariables, options: { outputReferences: true, // new setting, if true will use variable references }, diff --git a/examples/advanced/yaml-tokens/sd.config.js b/examples/advanced/yaml-tokens/sd.config.js index aeaaae596..97a173200 100644 --- a/examples/advanced/yaml-tokens/sd.config.js +++ b/examples/advanced/yaml-tokens/sd.config.js @@ -1,4 +1,5 @@ import yaml from 'yaml'; +import { formats, transformGroups } from 'style-dictionary/enums'; export default { hooks: { @@ -20,12 +21,12 @@ export default { source: [`tokens/**/*.yaml`], platforms: { css: { - transformGroup: 'css', + transformGroup: transformGroups.css, buildPath: 'build/', files: [ { destination: 'variables.css', - format: 'css/variables', + format: formats.cssVariables, }, ], }, diff --git a/lib/Register.js b/lib/Register.js index 720ad276a..36613d6ca 100644 --- a/lib/Register.js +++ b/lib/Register.js @@ -4,6 +4,7 @@ import formatBuiltins from './common/formats.js'; import actionBuiltins from './common/actions.js'; import filterBuiltins from './common/filters.js'; import { deepmerge } from './utils/deepmerge.js'; +import { transformTypes } from './enums/index.js'; /** * @typedef {import('../types/File.d.ts').FileHeader} FileHeader @@ -16,6 +17,8 @@ import { deepmerge } from './utils/deepmerge.js'; * @typedef {import('../types/Config.d.ts').Hooks} Hooks */ +const { value: transformTypeValue, name: transformTypeName, attribute } = transformTypes; + /** * @return {Required} */ @@ -103,11 +106,11 @@ export class Register { * @param {typeof Register | Register} target */ static __registerTransform(transform, target) { - const transformTypes = ['name', 'value', 'attribute']; + const transformTypeValues = [transformTypeName, transformTypeValue, attribute]; const { type, name, filter, transitive, transform: transformFn } = transform; if (typeof type !== 'string') throw new Error('type must be a string'); - if (transformTypes.indexOf(type) < 0) - throw new Error(type + ' type is not one of: ' + transformTypes.join(', ')); + if (transformTypeValues.indexOf(type) < 0) + throw new Error(type + ' type is not one of: ' + transformTypeValues.join(', ')); if (typeof name !== 'string') throw new Error('name must be a string'); if (filter && typeof filter !== 'function') throw new Error('filter must be a function'); if (typeof transformFn !== 'function') throw new Error('transform must be a function'); diff --git a/lib/StyleDictionary.js b/lib/StyleDictionary.js index 52ed5119e..581efa39b 100644 --- a/lib/StyleDictionary.js +++ b/lib/StyleDictionary.js @@ -39,6 +39,7 @@ import cleanFiles from './cleanFiles.js'; import cleanDirs from './cleanDirs.js'; import cleanActions from './cleanActions.js'; import { isNode } from './utils/isNode.js'; +import { logBrokenReferenceLevels, logVerbosityLevels, logWarningLevels } from './enums/index.js'; /** * @typedef {import('../types/Volume.d.ts').Volume} Volume @@ -61,6 +62,9 @@ const PROPERTY_VALUE_COLLISIONS = GroupMessages.GROUP.PropertyValueCollisions; const PROPERTY_REFERENCE_WARNINGS = GroupMessages.GROUP.PropertyReferenceWarnings; const UNKNOWN_CSS_FONT_PROPS_WARNINGS = GroupMessages.GROUP.UnknownCSSFontProperties; const FILTER_WARNINGS = GroupMessages.GROUP.FilteredOutputReferences; +const { throw: throwBrokenReference } = logBrokenReferenceLevels; +const { default: defaultVerbosity, silent, verbose } = logVerbosityLevels; +const { error, warn, disabled } = logWarningLevels; /** * Style Dictionary module @@ -120,10 +124,10 @@ export default class StyleDictionary extends Register { this.usesDtcg = undefined; /** @type {LogConfig} */ this.log = { - warnings: 'warn', - verbosity: 'default', + warnings: warn, + verbosity: defaultVerbosity, errors: { - brokenReferences: 'throw', + brokenReferences: throwBrokenReference, }, }; /** @type {string[]} */ @@ -330,14 +334,14 @@ export default class StyleDictionary extends Register { if (propValCollisionCount > 0) { const collisions = GroupMessages.flush(PROPERTY_VALUE_COLLISIONS).join('\n'); let warn = `\nToken collisions detected (${propValCollisionCount}):\n`; - if (this.log.verbosity === 'verbose') { + if (this.log.verbosity === verbose) { warn += `\n${collisions}\n\n`; } else { warn += verbosityInfo; } - if (this.log?.warnings === 'error') { + if (this.log?.warnings === error) { throw new Error(warn); - } else if (this.log?.verbosity !== 'silent' && this.log.warnings !== 'disabled') { + } else if (this.log?.verbosity !== silent && this.log.warnings !== disabled) { // eslint-disable-next-line no-console console.log(chalk.rgb(255, 140, 0).bold(warn)); } @@ -576,15 +580,15 @@ export default class StyleDictionary extends Register { const warnings = GroupMessages.flush(PROPERTY_REFERENCE_WARNINGS).join('\n'); let err = `\nReference Errors:\nSome token references (${refWarningCount}) could not be found.\n`; - if (this.log.verbosity === 'verbose') { + if (this.log.verbosity === verbose) { err += `\n${warnings}\n`; } else { err += `${verbosityInfo}\n`; } - if (this.log.errors?.brokenReferences === 'throw') { + if (this.log.errors?.brokenReferences === throwBrokenReference) { throw new Error(err); - } else if (this.log.verbosity !== 'silent') { + } else if (this.log.verbosity !== silent) { console.error(err); } } @@ -594,15 +598,15 @@ export default class StyleDictionary extends Register { const warnings = GroupMessages.flush(UNKNOWN_CSS_FONT_PROPS_WARNINGS).join('\n'); let err = `\nUnknown CSS Font Shorthand properties found for ${unknownPropsWarningCount} tokens, CSS output for Font values will be missing some typography token properties as a result:\n`; - if (this.log.verbosity === 'verbose') { + if (this.log.verbosity === verbose) { err += `\n${warnings}\n`; } else { err += `${verbosityInfo}\n`; } - if (this.log.warnings === 'error') { + if (this.log.warnings === error) { throw new Error(err); - } else if (this.log.warnings !== 'disabled' && this.log.verbosity !== 'silent') { + } else if (this.log.warnings !== disabled && this.log.verbosity !== silent) { // eslint-disable-next-line no-console console.log(chalk.rgb(255, 140, 0).bold(err)); } @@ -699,9 +703,9 @@ export default class StyleDictionary extends Register { filteredTokens.tokens.constructor === Object ) { let warnNoFile = `No tokens for ${destination}. File not created.`; - if (platform.log?.warnings === 'error') { + if (platform.log?.warnings === error) { throw new Error(warnNoFile); - } else if (platform.log?.verbosity !== 'silent' && platform.log?.warnings !== 'disabled') { + } else if (platform.log?.verbosity !== silent && platform.log?.warnings !== disabled) { logs.warning.push(chalk.rgb(255, 140, 0)(warnNoFile)); } return { logs, destination: fullDestination, output: undefined }; @@ -760,7 +764,7 @@ export default class StyleDictionary extends Register { if ( (nested || tokenNamesCollisionCount === 0) && filteredReferencesCount === 0 && - platform.log?.verbosity !== 'silent' + platform.log?.verbosity !== silent ) { logs.success.push(chalk.bold.green(`✔︎ ${fullDestination}`)); } else { @@ -787,12 +791,12 @@ export default class StyleDictionary extends Register { ].join('\n '), ); const warn = - platform.log?.verbosity === 'verbose' + platform.log?.verbosity === verbose ? `${warnHeader}\n${title}\n ${tokenNamesCollisionWarnings}\n${help}` : `${warnHeader}\n${title}\n\n${verbosityInfo}`; - if (platform?.log?.warnings === 'error') { + if (platform?.log?.warnings === error) { throw new Error(warn); - } else if (platform.log?.verbosity !== 'silent' && platform.log?.warnings !== 'disabled') { + } else if (platform.log?.verbosity !== silent && platform.log?.warnings !== disabled) { logs.warning.push(chalk.rgb(255, 140, 0).bold(warn)); } } @@ -810,12 +814,12 @@ export default class StyleDictionary extends Register { 0, )(['This is caused when combining a filter and `outputReferences`.'].join('\n ')); const warn = - platform.log?.verbosity === 'verbose' + platform.log?.verbosity === verbose ? `${warnHeader}\n${title}\nHere are the references that are used but not defined in the file:\n ${filteredReferencesWarnings}\n${help}` : `${warnHeader}\n${title}\n\n${verbosityInfo}`; - if (platform?.log?.warnings === 'error') { + if (platform?.log?.warnings === error) { throw new Error(warn); - } else if (platform.log?.verbosity !== 'silent' && platform.log?.warnings !== 'disabled') { + } else if (platform.log?.verbosity !== silent && platform.log?.warnings !== disabled) { logs.warning.push(chalk.rgb(255, 140, 0).bold(warn)); } } @@ -856,7 +860,7 @@ export default class StyleDictionary extends Register { const logs = formattedFiles.map((formattedFile) => formattedFile.logs); if (logs) { - if (this.log?.verbosity !== 'silent') { + if (this.log?.verbosity !== silent) { // eslint-disable-next-line no-console console.log('\n' + platform); } @@ -935,9 +939,9 @@ export default class StyleDictionary extends Register { files.map(({ destination, output }) => { if (output && destination) { if (typeof output !== 'string') { - if (this.log.verbosity !== 'silent' && this.log.warnings !== 'disabled') { + if (this.log.verbosity !== silent && this.log.warnings !== disabled) { const warn = `Content type of ${destination} is not a string, so no file was created.`; - if (this.log.warnings === 'error') { + if (this.log.warnings === error) { throw new Error(warn); } // eslint-disable-next-line no-console @@ -979,7 +983,7 @@ export default class StyleDictionary extends Register { // collect logs, cleanFiles happens in parallel but we want to log in sequence const logs = await cleanFiles(platformConfig, this.volume); if (logs) { - if (this.log?.verbosity !== 'silent') { + if (this.log?.verbosity !== silent) { // eslint-disable-next-line no-console console.log('\n' + platform); } diff --git a/lib/cleanDir.js b/lib/cleanDir.js index e8493c38f..828413560 100644 --- a/lib/cleanDir.js +++ b/lib/cleanDir.js @@ -14,6 +14,7 @@ import chalk from 'chalk'; import { dirname } from 'path-unified'; import { fs } from 'style-dictionary/fs'; +import { logVerbosityLevels } from './enums/index.js'; /** * @typedef {import('../types/Volume.d.ts').Volume} Volume @@ -45,7 +46,7 @@ export default async function cleanDir(file, platform = {}, vol = fs) { if (vol.existsSync(dir)) { const dirContents = vol.readdirSync(dir, 'buffer'); if (dirContents.length === 0) { - if (platform.log?.verbosity !== 'silent') { + if (platform.log?.verbosity !== logVerbosityLevels.silent) { // eslint-disable-next-line no-console console.log(chalk.bold.red('-') + ' ' + dir); } diff --git a/lib/cleanFile.js b/lib/cleanFile.js index 1adaa3a84..cae205c60 100644 --- a/lib/cleanFile.js +++ b/lib/cleanFile.js @@ -13,6 +13,7 @@ import chalk from 'chalk'; import { fs } from 'style-dictionary/fs'; +import { logVerbosityLevels } from './enums/index.js'; /** * @typedef {import('../types/Volume.d.ts').Volume} Volume @@ -20,6 +21,8 @@ import { fs } from 'style-dictionary/fs'; * @typedef {import('../types/Config.d.ts').PlatformConfig} PlatformConfig */ +const { silent } = logVerbosityLevels; + /** * Takes the style property object and a format and returns a * string that can be written to a file. @@ -43,13 +46,13 @@ export default async function cleanFile(file, platform = {}, vol = fs) { destination = platform.buildPath + destination; } - if (!vol.existsSync(destination) && platform?.log?.verbosity !== 'silent') { + if (!vol.existsSync(destination) && platform?.log?.verbosity !== silent) { cleanLogs.success.push(chalk.bold.red('!') + ' ' + destination + ', does not exist'); return cleanLogs; } vol.unlinkSync(destination); - if (platform?.log?.verbosity !== 'silent') { + if (platform?.log?.verbosity !== silent) { cleanLogs.success.push(chalk.bold.red('-') + ' ' + destination); } return cleanLogs; diff --git a/lib/common/actions.js b/lib/common/actions.js index fb382619e..dcc54afe5 100644 --- a/lib/common/actions.js +++ b/lib/common/actions.js @@ -12,6 +12,7 @@ */ import { fs } from 'style-dictionary/fs'; +import { logVerbosityLevels, actions } from '../enums/index.js'; /** * @typedef {import('../../types/DesignToken.d.ts').Dictionary} Dictionary @@ -20,6 +21,9 @@ import { fs } from 'style-dictionary/fs'; * @typedef {import('../../types/DesignToken.d.ts').TransformedToken} Token */ +const { androidCopyImages, copyAssets } = actions; +const { silent } = logVerbosityLevels; + /** * @namespace Actions * @type {Record>} @@ -30,7 +34,7 @@ export default { * * @memberof Actions */ - 'android/copyImages': { + [androidCopyImages]: { do: async function (dictionary, config, options, vol = fs) { const imagesDir = `${config.buildPath}android/main/res/drawable-`; /** @@ -72,9 +76,9 @@ export default { * * @memberof Actions */ - copy_assets: { + [copyAssets]: { do: async function (_, config, options, vol = fs) { - if (config.log?.verbosity !== 'silent') { + if (config.log?.verbosity !== silent) { // eslint-disable-next-line no-console console.log('Copying assets directory to ' + config.buildPath + 'assets'); } @@ -88,7 +92,7 @@ export default { ); }, undo: async function (_, config, options, vol = fs) { - if (config.log?.verbosity !== 'silent') { + if (config.log?.verbosity !== silent) { // eslint-disable-next-line no-console console.log('Removing assets directory from ' + config.buildPath + 'assets'); } diff --git a/lib/common/formatHelpers/createPropertyFormatter.js b/lib/common/formatHelpers/createPropertyFormatter.js index cdc30e246..ae6557749 100644 --- a/lib/common/formatHelpers/createPropertyFormatter.js +++ b/lib/common/formatHelpers/createPropertyFormatter.js @@ -12,6 +12,7 @@ */ import { getReferences } from '../../utils/references/getReferences.js'; import usesReferences from '../../utils/references/usesReferences.js'; +import { commentStyles, commentPositions, propertyFormatNames } from '../../enums/index.js'; /** * @typedef {import('../../../types/DesignToken.d.ts').TransformedToken} TransformedToken @@ -20,13 +21,17 @@ import usesReferences from '../../utils/references/usesReferences.js'; * @typedef {import('../../../types/Format.d.ts').OutputReferences} OutputReferences */ +const { short, long, none } = commentStyles; +const { above, inline } = commentPositions; +const { css, sass, less, stylus } = propertyFormatNames; + /** * @type {Formatting} */ const defaultFormatting = { prefix: '', - commentStyle: 'long', - commentPosition: 'inline', + commentStyle: long, + commentPosition: inline, indentation: '', separator: ' =', suffix: ';', @@ -46,13 +51,13 @@ export function addComment(to_ret_token, comment, options) { const commentsByNewLine = comment.split('\n'); if (commentsByNewLine.length > 1) { - commentPosition = 'above'; + commentPosition = above; } let processedComment; switch (commentStyle) { - case 'short': - if (commentPosition === 'inline') { + case short: + if (commentPosition === inline) { processedComment = `// ${comment}`; } else { processedComment = commentsByNewLine.reduce( @@ -63,7 +68,7 @@ export function addComment(to_ret_token, comment, options) { processedComment = processedComment.replace(/\n$/g, ''); } break; - case 'long': + case long: if (commentsByNewLine.length > 1) { processedComment = commentsByNewLine.reduce( (acc, curr) => `${acc}${indentation} * ${curr}\n`, @@ -71,12 +76,12 @@ export function addComment(to_ret_token, comment, options) { ); processedComment += `${indentation} */`; } else { - processedComment = `${commentPosition === 'above' ? indentation : ''}/* ${comment} */`; + processedComment = `${commentPosition === above ? indentation : ''}/* ${comment} */`; } break; } - if (commentPosition === 'above') { + if (commentPosition === above) { // put the comment above the token if it's multi-line or if commentStyle ended with -above to_ret_token = `${processedComment}\n${to_ret_token}`; } else { @@ -95,6 +100,8 @@ export function addComment(to_ret_token, comment, options) { * @name createPropertyFormatter * @example * ```javascript + * import { propertyFormatNames } from 'style-dictionary/enums'; + * * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * format: function({ dictionary, options }) { @@ -102,7 +109,7 @@ export function addComment(to_ret_token, comment, options) { * const formatProperty = createPropertyFormatter({ * outputReferences, * dictionary, - * format: 'css' + * format: propertyFormatNames.css * }); * return dictionary.allTokens.map(formatProperty).join('\n'); * } @@ -130,26 +137,26 @@ export default function createPropertyFormatter({ /** @type {Formatting} */ const formatDefaults = {}; switch (format) { - case 'css': + case css: formatDefaults.prefix = '--'; formatDefaults.indentation = ' '; formatDefaults.separator = ':'; break; - case 'sass': + case sass: formatDefaults.prefix = '$'; - formatDefaults.commentStyle = 'short'; + formatDefaults.commentStyle = short; formatDefaults.indentation = ''; formatDefaults.separator = ':'; break; - case 'less': + case less: formatDefaults.prefix = '@'; - formatDefaults.commentStyle = 'short'; + formatDefaults.commentStyle = short; formatDefaults.indentation = ''; formatDefaults.separator = ':'; break; - case 'stylus': + case stylus: formatDefaults.prefix = '$'; - formatDefaults.commentStyle = 'short'; + formatDefaults.commentStyle = short; formatDefaults.indentation = ''; formatDefaults.separator = '='; break; @@ -219,7 +226,7 @@ export default function createPropertyFormatter({ if (Object.hasOwn(ref, `${usesDtcg ? '$' : ''}value`) && Object.hasOwn(ref, 'name')) { const refVal = usesDtcg ? ref.$value : ref.value; const replaceFunc = function () { - if (format === 'css') { + if (format === css) { if (outputReferenceFallbacks) { return `var(${prefix}${ref.name}, ${refVal})`; } else { @@ -242,14 +249,14 @@ export default function createPropertyFormatter({ to_ret_token += value; const themeable_token = typeof token.themeable === 'boolean' ? token.themeable : themeable; - if (format === 'sass' && themeable_token) { + if (format === sass && themeable_token) { to_ret_token += ' !default'; } to_ret_token += suffix; const comment = token.$description ?? token.comment; - if (comment && commentStyle !== 'none') { + if (comment && commentStyle !== none) { to_ret_token = addComment(to_ret_token, comment, mergedOptions); } diff --git a/lib/common/formatHelpers/fileHeader.js b/lib/common/formatHelpers/fileHeader.js index 92827b4fc..436b4a1ac 100644 --- a/lib/common/formatHelpers/fileHeader.js +++ b/lib/common/formatHelpers/fileHeader.js @@ -11,6 +11,8 @@ * and limitations under the License. */ +import { commentStyles } from '../../enums/index.js'; + /** * * @typedef {import('../../../types/File.d.ts').File} File @@ -47,7 +49,7 @@ const defaultFormatting = { * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * format: function({ dictionary, file }) { - * return fileHeader({file, commentStyle: 'short'}) + + * return fileHeader({file, commentStyle: commentStyles.short}) + * dictionary.allTokens.map(token => `${token.name} = ${token.value}`) * .join('\n'); * } @@ -84,7 +86,7 @@ export default async function fileHeader({ file, commentStyle, formatting = {}, ...(fileHeaderTimestamp ? [`Generated on ${new Date().toUTCString()}`] : []), ]; - if (commentStyle === 'short') { + if (commentStyle === commentStyles.short) { prefix = `// `; header = `${lineSeparator}`; footer = `${lineSeparator}${lineSeparator}`; diff --git a/lib/common/formatHelpers/formattedVariables.js b/lib/common/formatHelpers/formattedVariables.js index 4908b85df..99d1108dc 100644 --- a/lib/common/formatHelpers/formattedVariables.js +++ b/lib/common/formatHelpers/formattedVariables.js @@ -42,11 +42,13 @@ const defaultFormatting = { * @returns {String} * @example * ```js + * import { propertyFormatNames } from 'style-dictionary/enums'; + * * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * format: function({ dictionary, options }) { * return formattedVariables({ - * format: 'less', + * format: propertyFormatNames.less, * dictionary, * outputReferences: options.outputReferences * }); diff --git a/lib/common/formats.js b/lib/common/formats.js index 292038a08..abd2f75a2 100644 --- a/lib/common/formats.js +++ b/lib/common/formats.js @@ -30,28 +30,34 @@ import { import { stripMeta as stripMetaUtil } from '../utils/stripMeta.js'; -import androidColors from './templates/android/colors.template.js'; -import androidDimens from './templates/android/dimens.template.js'; -import androidFontDimens from './templates/android/fontDimens.template.js'; -import androidIntegers from './templates/android/integers.template.js'; -import androidResources from './templates/android/resources.template.js'; -import androidStrings from './templates/android/strings.template.js'; -import composeObject from './templates/compose/object.kt.template.js'; -import cssFonts from './templates/css/fonts.css.template.js'; -import flutterClassDart from './templates/flutter/class.dart.template.js'; -import iosColorsH from './templates/ios/colors.h.template.js'; -import iosColorsM from './templates/ios/colors.m.template.js'; -import iosSingletonH from './templates/ios/singleton.h.template.js'; -import iosSingletonM from './templates/ios/singleton.m.template.js'; -import iosStaticH from './templates/ios/static.h.template.js'; -import iosStaticM from './templates/ios/static.m.template.js'; -import iosStringsH from './templates/ios/strings.h.template.js'; -import iosStringsM from './templates/ios/strings.m.template.js'; -import iosSwiftAny from './templates/ios-swift/any.swift.template.js'; -import scssMapDeep from './templates/scss/map-deep.template.js'; -import scssMapFlat from './templates/scss/map-flat.template.js'; +import androidColorsTemplate from './templates/android/colors.template.js'; +import androidDimensTemplate from './templates/android/dimens.template.js'; +import androidFontDimensTemplate from './templates/android/fontDimens.template.js'; +import androidIntegersTemplate from './templates/android/integers.template.js'; +import androidResourcesTemplate from './templates/android/resources.template.js'; +import androidStringsTemplate from './templates/android/strings.template.js'; +import composeObjectTemplate from './templates/compose/object.kt.template.js'; +import cssFontsTemplate from './templates/css/fonts.css.template.js'; +import flutterClassDartTemplate from './templates/flutter/class.dart.template.js'; +import iosColorsHTemplate from './templates/ios/colors.h.template.js'; +import iosColorsMTemplate from './templates/ios/colors.m.template.js'; +import iosSingletonHTemplate from './templates/ios/singleton.h.template.js'; +import iosSingletonMTemplate from './templates/ios/singleton.m.template.js'; +import iosStaticHTemplate from './templates/ios/static.h.template.js'; +import iosStaticMTemplate from './templates/ios/static.m.template.js'; +import iosStringsHTemplate from './templates/ios/strings.h.template.js'; +import iosStringsMTemplate from './templates/ios/strings.m.template.js'; +import iosSwiftAnyTemplate from './templates/ios-swift/any.swift.template.js'; +import scssMapDeepTemplate from './templates/scss/map-deep.template.js'; +import scssMapFlatTemplate from './templates/scss/map-flat.template.js'; import macrosTemplate from './templates/ios/macros.template.js'; import plistTemplate from './templates/ios/plist.template.js'; +import { + commentStyles, + fileHeaderCommentStyles, + formats as fileFormats, + propertyFormatNames, +} from '../enums/index.js'; /** * @typedef {import('../../types/Format.d.ts').Format} Format @@ -65,6 +71,56 @@ import plistTemplate from './templates/ios/plist.template.js'; * @typedef {import('../utils/stripMeta.js').StripMetaOptions} StripMetaOptions */ +const { none } = commentStyles; +const { long, short, xml } = fileHeaderCommentStyles; +const { css, sass, less, stylus } = propertyFormatNames; +const { + cssVariables, + cssFonts, + scssMapFlat, + scssMapDeep, + scssVariables, + scssIcons, + lessVariables, + lessIcons, + stylusVariables, + javascriptEs6, + javascriptEsm, + javascriptModule, + javascriptModuleFlat, + javascriptObject, + javascriptUmd, + typescriptEs6Declarations, + typescriptModuleDeclarations, + androidResources, + androidColors, + androidDimens, + androidFontDimens, + androidIntegers, + androidStrings, + composeObject, + iosMacros, + iosPlist, + iosSingletonM, + iosSingletonH, + iosStaticH, + iosStaticM, + iosColorsH, + iosColorsM, + iosStringsH, + iosStringsM, + iosSwiftClassSwift, + iosSwiftEnumSwift, + iosSwiftAnySwift, + json, + jsonAsset, + jsonNested, + jsonFlat, + sketchPalette, + sketchPaletteV2, + flutterClassDart, +} = fileFormats; + /** * @namespace Formats */ @@ -136,7 +192,7 @@ const formats = { * } * ``` */ - 'css/variables': async function ({ dictionary, options = {}, file }) { + [cssVariables]: async function ({ dictionary, options = {}, file }) { const selector = options.selector ? options.selector : `:root`; const { outputReferences, outputReferenceFallbacks, usesDtcg, formatting } = options; const header = await fileHeader({ @@ -148,7 +204,7 @@ const formats = { header + `${selector} {\n` + formattedVariables({ - format: 'css', + format: css, dictionary, outputReferences, outputReferenceFallbacks, @@ -174,16 +230,16 @@ const formats = { * ) * ``` */ - 'scss/map-flat': async function ({ dictionary, options, file }) { + [scssMapFlat]: async function ({ dictionary, options, file }) { const { allTokens } = dictionary; const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'long', + commentStyle: long, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return scssMapFlat({ allTokens, options, header }); + return scssMapFlatTemplate({ allTokens, options, header }); }, /** @@ -208,12 +264,12 @@ const formats = { * ) * ``` */ - 'scss/map-deep': async function ({ dictionary, options, file }) { + [scssMapDeep]: async function ({ dictionary, options, file }) { // Default the "themeable" option to true for backward compatibility. const { outputReferences, themeable = true, formatting, usesDtcg } = options; const header = await fileHeader({ file, - commentStyle: 'long', + commentStyle: long, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); @@ -221,7 +277,7 @@ const formats = { '\n' + header + formattedVariables({ - format: 'sass', + format: sass, dictionary, outputReferences, themeable, @@ -229,7 +285,7 @@ const formats = { usesDtcg, }) + '\n' + - scssMapDeep({ dictionary, options }) + scssMapDeepTemplate({ dictionary, options }) ); }, @@ -246,18 +302,18 @@ const formats = { * $color-background-alt: #eeeeee !default; * ``` */ - 'scss/variables': async function ({ dictionary, options, file }) { + [scssVariables]: async function ({ dictionary, options, file }) { const { outputReferences, themeable = false, formatting, usesDtcg } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); return ( header + formattedVariables({ - format: 'sass', + format: sass, dictionary, outputReferences, themeable, @@ -279,11 +335,11 @@ const formats = { * .icon.email:before { content:$content-icon-email; } * ``` */ - 'scss/icons': async function ({ dictionary, options, file, platform }) { + [scssIcons]: async function ({ dictionary, options, file, platform }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); @@ -301,17 +357,23 @@ const formats = { * \@color-background-alt: #eeeeee; * ``` */ - 'less/variables': async function ({ dictionary, options, file }) { + [lessVariables]: async function ({ dictionary, options, file }) { const { outputReferences, formatting, usesDtcg } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); return ( header + - formattedVariables({ format: 'less', dictionary, outputReferences, formatting, usesDtcg }) + + formattedVariables({ + format: less, + dictionary, + outputReferences, + formatting, + usesDtcg, + }) + '\n' ); }, @@ -327,11 +389,11 @@ const formats = { * .icon.email:before { content:\@content-icon-email; } * ``` */ - 'less/icons': async function ({ dictionary, options, file, platform }) { + [lessIcons]: async function ({ dictionary, options, file, platform }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); @@ -349,18 +411,24 @@ const formats = { * $color-background-alt= #eeeeee; * ``` */ - 'stylus/variables': async function ({ dictionary, options, file, platform }) { + [stylusVariables]: async function ({ dictionary, options, file, platform }) { const { formatting, usesDtcg } = options; const outputReferences = !!platform.options?.outputReferences; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); return ( header + - formattedVariables({ format: 'stylus', dictionary, outputReferences, formatting, usesDtcg }) + + formattedVariables({ + format: stylus, + dictionary, + outputReferences, + formatting, + usesDtcg, + }) + '\n' ); }, @@ -383,7 +451,7 @@ const formats = { * } * ``` */ - 'javascript/module': async function ({ dictionary, file, options }) { + [javascriptModule]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, @@ -407,7 +475,7 @@ const formats = { *} *``` */ - 'javascript/module-flat': async function ({ dictionary, file, options }) { + [javascriptModuleFlat]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, @@ -449,7 +517,7 @@ const formats = { * } * ``` */ - 'javascript/object': async function ({ dictionary, file, options }) { + [javascriptObject]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, @@ -496,7 +564,7 @@ const formats = { * })) * ``` */ - 'javascript/umd': async function ({ dictionary, file, options }) { + [javascriptUmd]: async function ({ dictionary, file, options }) { const name = file.options?.name || '_styleDictionary'; const { formatting } = options; const header = await fileHeader({ @@ -558,7 +626,7 @@ const formats = { * export const ColorBackgroundAlt = '#fcfcfcfc'; * ``` */ - 'javascript/es6': async function ({ dictionary, file, options }) { + [javascriptEs6]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, @@ -599,7 +667,7 @@ const formats = { * } * ``` */ - 'javascript/esm': async function ({ dictionary, file, options }) { + [javascriptEsm]: async function ({ dictionary, file, options }) { const { formatting, minify = false } = options; let { tokens } = dictionary; tokens = stripMetaProps( @@ -655,7 +723,7 @@ const formats = { * export const ColorBackgroundAlt : string; * ``` */ - 'typescript/es6-declarations': async function ({ dictionary, file, options }) { + [typescriptEs6Declarations]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, @@ -734,7 +802,7 @@ const formats = { * }); * ``` */ - 'typescript/module-declarations': async function ({ dictionary, file, options }) { + [typescriptModuleDeclarations]: async function ({ dictionary, file, options }) { const { moduleName = `tokens` } = options; /** * @param {Tokens} obj @@ -812,15 +880,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * 14sp * ``` */ - 'android/resources': async function ({ dictionary, file, options }) { + [androidResources]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return androidResources({ dictionary, file, header, options }); + return androidResourcesTemplate({ dictionary, file, header, options }); }, /** @@ -830,7 +898,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * instead of this format: * * ```javascript - * format: 'android/resources', + * format: formats.androidResources, * filter: { * attributes: { category: 'color' } * } @@ -847,15 +915,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * #ffe19d9c * ``` */ - 'android/colors': async function ({ dictionary, options, file }) { + [androidColors]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return androidColors({ dictionary, options, header }); + return androidColorsTemplate({ dictionary, options, header }); }, /** @@ -865,7 +933,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * instead of this format: * * ```javascript - * format: 'android/resources', + * format: formats.androidResources, * filter: { * attributes: { category: 'size' } * } @@ -882,15 +950,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * 15.00dp * ``` */ - 'android/dimens': async function ({ dictionary, options, file }) { + [androidDimens]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return androidDimens({ dictionary, options, header }); + return androidDimensTemplate({ dictionary, options, header }); }, /** @@ -900,7 +968,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * instead of this format: * * ```javascript - * format: 'android/resources', + * format: formats.androidResources, * filter: { * attributes: { category: 'size' } * } @@ -917,15 +985,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * 15.00sp * ``` */ - 'android/fontDimens': async function ({ dictionary, options, file }) { + [androidFontDimens]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return androidFontDimens({ dictionary, options, header }); + return androidFontDimensTemplate({ dictionary, options, header }); }, /** @@ -936,7 +1004,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * instead of this format: * * ```javascript - * format: 'android/resources', + * format: formats.androidResources, * filter: { * attributes: { category: 'time' } * } @@ -954,15 +1022,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * 4000 * ``` */ - 'android/integers': async function ({ dictionary, options, file }) { + [androidIntegers]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return androidIntegers({ dictionary, options, header }); + return androidIntegersTemplate({ dictionary, options, header }); }, /** @@ -973,7 +1041,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * instead of this format: * * ```javascript - * format: 'android/resources', + * format: formats.androidResources, * filter: { * attributes: { category: 'content' } * } @@ -990,15 +1058,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * * ``` */ - 'android/strings': async function ({ dictionary, options, file }) { + [androidStrings]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return androidStrings({ dictionary, options, header }); + return androidStringsTemplate({ dictionary, options, header }); }, // Compose templates @@ -1025,7 +1093,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'compose/object': async function ({ dictionary, options, file }) { + [composeObject]: async function ({ dictionary, options, file }) { const { allTokens, tokens, unfilteredTokens } = dictionary; const { outputReferences, formatting, usesDtcg } = options; const formatProperty = createPropertyFormatter({ @@ -1033,7 +1101,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul dictionary, formatting: { suffix: '', - commentStyle: 'none', // We will add the comment in the format template + commentStyle: /** @type {'short' | 'long' | 'none'} */ (none), // We will add the comment in the format template ...formatting, }, usesDtcg, @@ -1049,11 +1117,11 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul options = setComposeObjectProperties(options); const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return composeObject({ allTokens: sortedTokens, options, formatProperty, header }); + return composeObjectTemplate({ allTokens: sortedTokens, options, formatProperty, header }); }, // iOS templates @@ -1072,11 +1140,11 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * #define SizeFontTiny 176.00f * ``` */ - 'ios/macros': async function ({ dictionary, options, file }) { + [iosMacros]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); @@ -1090,11 +1158,11 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Fix this template and add example and usage */ - 'ios/plist': async function ({ dictionary, options, file }) { + [iosPlist]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'xml', + commentStyle: xml, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); @@ -1108,15 +1176,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/singleton.m': async function ({ dictionary, options, file }) { + [iosSingletonM]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosSingletonM({ dictionary, options, file, header }); + return iosSingletonMTemplate({ dictionary, options, file, header }); }, /** @@ -1126,15 +1194,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/singleton.h': async function ({ file, options }) { + [iosSingletonH]: async function ({ file, options }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosSingletonH({ file, options, header }); + return iosSingletonHTemplate({ file, options, header }); }, /** @@ -1144,15 +1212,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/static.h': async function ({ dictionary, file, options }) { + [iosStaticH]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosStaticH({ dictionary, file, options, header }); + return iosStaticHTemplate({ dictionary, file, options, header }); }, /** @@ -1162,15 +1230,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/static.m': async function ({ dictionary, options, file }) { + [iosStaticM]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosStaticM({ dictionary, options, file, header }); + return iosStaticMTemplate({ dictionary, options, file, header }); }, /** @@ -1180,15 +1248,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind memberx * @todo Add example and usage */ - 'ios/colors.h': async function ({ dictionary, options, file }) { + [iosColorsH]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosColorsH({ dictionary, file, options, header }); + return iosColorsHTemplate({ dictionary, file, options, header }); }, /** @@ -1198,15 +1266,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/colors.m': async function ({ dictionary, options, file }) { + [iosColorsM]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosColorsM({ dictionary, options, file, header }); + return iosColorsMTemplate({ dictionary, options, file, header }); }, /** @@ -1216,15 +1284,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/strings.h': async function ({ dictionary, file, options }) { + [iosStringsH]: async function ({ dictionary, file, options }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosStringsH({ dictionary, file, options, header }); + return iosStringsHTemplate({ dictionary, file, options, header }); }, /** @@ -1234,15 +1302,15 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'ios/strings.m': async function ({ dictionary, options, file }) { + [iosStringsM]: async function ({ dictionary, options, file }) { const { formatting } = options; const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosStringsM({ dictionary, options, file, header }); + return iosStringsMTemplate({ dictionary, options, file, header }); }, /** @@ -1264,7 +1332,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'ios-swift/class.swift': async function ({ dictionary, options, file, platform }) { + [iosSwiftClassSwift]: async function ({ dictionary, options, file, platform }) { const { allTokens, tokens, unfilteredTokens } = dictionary; const { outputReferences, formatting, usesDtcg } = options; options = setSwiftFileProperties(options, 'class', platform.transformGroup); @@ -1286,11 +1354,11 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul } const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosSwiftAny({ allTokens: sortedTokens, file, options, formatProperty, header }); + return iosSwiftAnyTemplate({ allTokens: sortedTokens, file, options, formatProperty, header }); }, /** @@ -1312,7 +1380,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'ios-swift/enum.swift': async function ({ dictionary, options, file, platform }) { + [iosSwiftEnumSwift]: async function ({ dictionary, options, file, platform }) { const { allTokens, tokens, unfilteredTokens } = dictionary; const { outputReferences, formatting, usesDtcg } = options; options = setSwiftFileProperties(options, 'enum', platform.transformGroup); @@ -1334,11 +1402,11 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul } const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosSwiftAny({ allTokens: sortedTokens, file, options, formatProperty, header }); + return iosSwiftAnyTemplate({ allTokens: sortedTokens, file, options, formatProperty, header }); }, /** @@ -1371,7 +1439,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'ios-swift/any.swift': async function ({ dictionary, options, file, platform }) { + [iosSwiftAnySwift]: async function ({ dictionary, options, file, platform }) { const { allTokens, tokens, unfilteredTokens } = dictionary; const { outputReferences, formatting, usesDtcg } = options; options = setSwiftFileProperties(options, options.objectType, platform.transformGroup); @@ -1393,11 +1461,11 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul } const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return iosSwiftAny({ allTokens: sortedTokens, file, options, formatProperty, header }); + return iosSwiftAnyTemplate({ allTokens: sortedTokens, file, options, formatProperty, header }); }, // Css templates @@ -1409,7 +1477,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * @kind member * @todo Add example and usage */ - 'css/fonts.css': ({ dictionary }) => cssFonts(dictionary.tokens), + [cssFonts]: ({ dictionary }) => cssFontsTemplate(dictionary.tokens), // Web templates @@ -1431,7 +1499,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - json: function ({ dictionary, options }) { + [json]: function ({ dictionary, options }) { let { tokens } = dictionary; tokens = stripMetaProps( tokens, @@ -1458,7 +1526,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'json/asset': function ({ dictionary }) { + [jsonAsset]: function ({ dictionary }) { return JSON.stringify({ asset: dictionary.tokens.asset }, null, 2); }, @@ -1477,7 +1545,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'json/nested': function ({ dictionary, options }) { + [jsonNested]: function ({ dictionary, options }) { return JSON.stringify(minifyDictionary(dictionary.tokens, options.usesDtcg), null, 2) + '\n'; }, @@ -1493,7 +1561,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'json/flat': function ({ dictionary, options }) { + [jsonFlat]: function ({ dictionary, options }) { return ( '{\n' + dictionary.allTokens @@ -1526,7 +1594,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'sketch/palette': function ({ dictionary, options }) { + [sketchPalette]: function ({ dictionary, options }) { const to_ret = { compatibleVersion: '1.0', pluginVersion: '1.1', @@ -1563,7 +1631,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * } * ``` */ - 'sketch/palette/v2': function ({ dictionary, options }) { + [sketchPaletteV2]: function ({ dictionary, options }) { const to_ret = { compatibleVersion: '2.0', pluginVersion: '2.2', @@ -1602,7 +1670,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul * static const contentFontFamily1 = "NewJune"; * ``` */ - 'flutter/class.dart': async function ({ dictionary, options, file }) { + [flutterClassDart]: async function ({ dictionary, options, file }) { const { allTokens, tokens, unfilteredTokens } = dictionary; const { outputReferences, formatting, usesDtcg } = options; const formatProperty = createPropertyFormatter({ @@ -1620,18 +1688,24 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul } const header = await fileHeader({ file, - commentStyle: 'short', + commentStyle: short, formatting: getFormattingCloneWithoutPrefix(formatting), options, }); - return flutterClassDart({ allTokens: sortedTokens, file, options, formatProperty, header }); + return flutterClassDartTemplate({ + allTokens: sortedTokens, + file, + options, + formatProperty, + header, + }); }, }; // Mark which formats are nested -formats['json/nested'].nested = true; -formats['javascript/module'].nested = true; -formats['javascript/object'].nested = true; -formats['javascript/esm'].nested = true; +formats[jsonNested].nested = true; +formats[javascriptModule].nested = true; +formats[javascriptObject].nested = true; +formats[javascriptEsm].nested = true; export default formats; diff --git a/lib/common/templates/scss/map-flat.template.js b/lib/common/templates/scss/map-flat.template.js index 23dc6c5f0..9ac551bde 100644 --- a/lib/common/templates/scss/map-flat.template.js +++ b/lib/common/templates/scss/map-flat.template.js @@ -1,4 +1,5 @@ import { addComment } from '../../formatHelpers/createPropertyFormatter.js'; +import { commentStyles, commentPositions } from '../../../enums/index.js'; /** * @typedef {import('../../../../types/DesignToken.d.ts').TransformedToken} TransformedToken @@ -18,8 +19,8 @@ export default ({ allTokens, options, header }) => { const f = { ..._f, indentation: _f.indentation ?? ' ', - commentStyle: _f.commentStyle ?? 'short', - commentPosition: _f.commentPosition ?? 'above', + commentStyle: _f.commentStyle ?? commentStyles.short, + commentPosition: _f.commentPosition ?? commentPositions.above, }; return ` ${header}$${options.mapName ?? 'tokens'}: (\n${allTokens @@ -27,7 +28,7 @@ ${header}$${options.mapName ?? 'tokens'}: (\n${allTokens const tokenString = `${f.indentation}'${token.name}': ${ options.usesDtcg ? token.$value : token.value }${i !== arr.length - 1 ? ',' : ''}`; - if (token.comment && f.commentStyle !== 'none') { + if (token.comment && f.commentStyle !== commentStyles.none) { return addComment(tokenString, token.comment, f); } return tokenString; diff --git a/lib/common/transformGroups.js b/lib/common/transformGroups.js index 1e471cae9..68e5235eb 100644 --- a/lib/common/transformGroups.js +++ b/lib/common/transformGroups.js @@ -11,6 +11,52 @@ * and limitations under the License. */ +import { transformGroups, transforms } from '../enums/index.js'; + +const { + attributeCti, + attributeColor, + nameHuman, + nameCamel, + nameKebab, + nameSnake, + namePascal, + colorHex, + colorHex8android, + colorComposeColor, + colorUIColor, + colorUIColorSwift, + colorCss, + sizeObject, + sizeRemToSp, + sizeRemToDp, + sizePx, + sizeRem, + sizeRemToPt, + sizeComposeRemToSp, + sizeComposeRemToDp, + sizeComposeEm, + sizeSwiftRemToCGFloat, + htmlIcon, + contentObjCLiteral, + contentSwiftLiteral, + timeSeconds, + fontFamilyCss, + cubicBezierCss, + strokeStyleCssShorthand, + borderCssShorthand, + typographyCssShorthand, + transitionCssShorthand, + shadowCssShorthand, + assetUrl, + assetObjCLiteral, + assetSwiftLiteral, + colorHex8flutter, + contentFlutterLiteral, + assetFlutterLiteral, + sizeFlutterRemToDouble, +} = transforms; + /** * @namespace TransformGroups */ @@ -29,7 +75,7 @@ export default { * * @memberof TransformGroups */ - web: ['attribute/cti', 'name/kebab', 'size/px', 'color/css'], + [transformGroups.web]: [attributeCti, nameKebab, sizePx, colorCss], /** * Transforms: @@ -41,7 +87,7 @@ export default { * * @memberof TransformGroups */ - js: ['attribute/cti', 'name/pascal', 'size/rem', 'color/hex'], + [transformGroups.js]: [attributeCti, namePascal, sizeRem, colorHex], /** * Transforms: @@ -63,22 +109,22 @@ export default { * * @memberof TransformGroups */ - scss: [ - 'attribute/cti', - 'name/kebab', - 'time/seconds', - 'html/icon', - 'size/rem', - 'color/css', - 'asset/url', - 'fontFamily/css', - 'cubicBezier/css', + [transformGroups.scss]: [ + attributeCti, + nameKebab, + timeSeconds, + htmlIcon, + sizeRem, + colorCss, + assetUrl, + fontFamilyCss, + cubicBezierCss, // object-value tokens - 'strokeStyle/css/shorthand', - 'border/css/shorthand', - 'typography/css/shorthand', - 'transition/css/shorthand', - 'shadow/css/shorthand', + strokeStyleCssShorthand, + borderCssShorthand, + typographyCssShorthand, + transitionCssShorthand, + shadowCssShorthand, ], /** @@ -101,22 +147,22 @@ export default { * * @memberof TransformGroups */ - css: [ - 'attribute/cti', - 'name/kebab', - 'time/seconds', - 'html/icon', - 'size/rem', - 'color/css', - 'asset/url', - 'fontFamily/css', - 'cubicBezier/css', + [transformGroups.css]: [ + attributeCti, + nameKebab, + timeSeconds, + htmlIcon, + sizeRem, + colorCss, + assetUrl, + fontFamilyCss, + cubicBezierCss, // object-value tokens - 'strokeStyle/css/shorthand', - 'border/css/shorthand', - 'typography/css/shorthand', - 'transition/css/shorthand', - 'shadow/css/shorthand', + strokeStyleCssShorthand, + borderCssShorthand, + typographyCssShorthand, + transitionCssShorthand, + shadowCssShorthand, ], /** @@ -139,22 +185,22 @@ export default { * * @memberof TransformGroups */ - less: [ - 'attribute/cti', - 'name/kebab', - 'time/seconds', - 'html/icon', - 'size/rem', - 'color/hex', - 'asset/url', - 'fontFamily/css', - 'cubicBezier/css', + [transformGroups.less]: [ + attributeCti, + nameKebab, + timeSeconds, + htmlIcon, + sizeRem, + colorHex, + assetUrl, + fontFamilyCss, + cubicBezierCss, // object-value tokens - 'strokeStyle/css/shorthand', - 'border/css/shorthand', - 'typography/css/shorthand', - 'transition/css/shorthand', - 'shadow/css/shorthand', + strokeStyleCssShorthand, + borderCssShorthand, + typographyCssShorthand, + transitionCssShorthand, + shadowCssShorthand, ], /** @@ -166,7 +212,7 @@ export default { * * @memberof TransformGroups */ - html: ['attribute/cti', 'attribute/color', 'name/human'], + [transformGroups.html]: [attributeCti, attributeColor, nameHuman], /** * Transforms: * @@ -178,7 +224,7 @@ export default { * * @memberof TransformGroups */ - android: ['attribute/cti', 'name/snake', 'color/hex8android', 'size/remToSp', 'size/remToDp'], + [transformGroups.android]: [attributeCti, nameSnake, colorHex8android, sizeRemToSp, sizeRemToDp], /** * Transforms: * @@ -191,13 +237,13 @@ export default { * * @memberof TransformGroups */ - compose: [ - 'attribute/cti', - 'name/camel', - 'color/composeColor', - 'size/compose/em', - 'size/compose/remToSp', - 'size/compose/remToDp', + [transformGroups.compose]: [ + attributeCti, + nameCamel, + colorComposeColor, + sizeComposeEm, + sizeComposeRemToSp, + sizeComposeRemToDp, ], /** * Transforms: @@ -211,13 +257,13 @@ export default { * * @memberof TransformGroups */ - ios: [ - 'attribute/cti', - 'name/pascal', - 'color/UIColor', - 'content/objC/literal', - 'asset/objC/literal', - 'size/remToPt', + [transformGroups.ios]: [ + attributeCti, + namePascal, + colorUIColor, + contentObjCLiteral, + assetObjCLiteral, + sizeRemToPt, ], /** * Transforms: @@ -231,13 +277,13 @@ export default { * * @memberof TransformGroups */ - 'ios-swift': [ - 'attribute/cti', - 'name/camel', - 'color/UIColorSwift', - 'content/swift/literal', - 'asset/swift/literal', - 'size/swift/remToCGFloat', + [transformGroups.iosSwift]: [ + attributeCti, + nameCamel, + colorUIColorSwift, + contentSwiftLiteral, + assetSwiftLiteral, + sizeSwiftRemToCGFloat, ], /** * Transforms: @@ -253,13 +299,13 @@ export default { * * @memberof TransformGroups */ - 'ios-swift-separate': [ - 'attribute/cti', - 'name/camel', - 'color/UIColorSwift', - 'content/swift/literal', - 'asset/swift/literal', - 'size/swift/remToCGFloat', + [transformGroups.iosSwiftSeparate]: [ + attributeCti, + nameCamel, + colorUIColorSwift, + contentSwiftLiteral, + assetSwiftLiteral, + sizeSwiftRemToCGFloat, ], /** * Transforms: @@ -268,7 +314,7 @@ export default { * * @memberof TransformGroups */ - assets: ['attribute/cti'], + [transformGroups.assets]: [attributeCti], /** * Transforms: * @@ -281,13 +327,13 @@ export default { * * @memberof TransformGroups */ - flutter: [ - 'attribute/cti', - 'name/camel', - 'color/hex8flutter', - 'size/flutter/remToDouble', - 'content/flutter/literal', - 'asset/flutter/literal', + [transformGroups.flutter]: [ + attributeCti, + nameCamel, + colorHex8flutter, + sizeFlutterRemToDouble, + contentFlutterLiteral, + assetFlutterLiteral, ], /** * Transforms: @@ -303,13 +349,13 @@ export default { * * @memberof TransformGroups */ - 'flutter-separate': [ - 'attribute/cti', - 'name/camel', - 'color/hex8flutter', - 'size/flutter/remToDouble', - 'content/flutter/literal', - 'asset/flutter/literal', + [transformGroups.flutterSeparate]: [ + attributeCti, + nameCamel, + colorHex8flutter, + sizeFlutterRemToDouble, + contentFlutterLiteral, + assetFlutterLiteral, ], /** @@ -321,5 +367,5 @@ export default { * * @memberof TransformGroups */ - 'react-native': ['name/camel', 'color/css', 'size/object'], + [transformGroups.reactNative]: [nameCamel, colorCss, sizeObject], }; diff --git a/lib/common/transforms.js b/lib/common/transforms.js index 5ba5df9e8..4bb0fa34f 100644 --- a/lib/common/transforms.js +++ b/lib/common/transforms.js @@ -16,6 +16,7 @@ import { join } from 'path-unified'; import { snakeCase, kebabCase, camelCase } from 'change-case'; import convertToBase64 from '../utils/convertToBase64.js'; import GroupMessages from '../utils/groupMessages.js'; +import { transforms, transformTypes } from '../enums/index.js'; /** * @typedef {import('../../types/Transform.d.ts').Transform} Transform @@ -25,6 +26,7 @@ import GroupMessages from '../utils/groupMessages.js'; */ const UNKNOWN_CSS_FONT_PROPS_WARNINGS = GroupMessages.GROUP.UnknownCSSFontProperties; +const { value, name, attribute } = transformTypes; /** * @param {string} str @@ -222,8 +224,8 @@ export default { * * @memberof Transforms */ - 'attribute/cti': { - type: 'attribute', + [transforms.attributeCti]: { + type: attribute, transform: function (token) { const attrNames = ['category', 'type', 'item', 'subitem', 'state']; const originalAttrs = token.attributes || {}; @@ -254,8 +256,8 @@ export default { * * @memberof Transforms */ - 'attribute/color': { - type: 'attribute', + [transforms.attributeColor]: { + type: attribute, filter: isColor, transform: function (token, _, options) { const color = Color(options.usesDtcg ? token.$value : token.value); @@ -279,8 +281,8 @@ export default { * * @memberof Transforms */ - 'name/human': { - type: 'name', + [transforms.nameHuman]: { + type: name, transform: function (token) { return [token.attributes?.item, token.attributes?.subitem].join(' '); }, @@ -298,8 +300,8 @@ export default { * * @memberof Transforms */ - 'name/camel': { - type: 'name', + [transforms.nameCamel]: { + type: name, transform: function (token, config) { return camelCase([config.prefix].concat(token.path).join(' '), camelOpts); }, @@ -317,8 +319,8 @@ export default { * * @memberof Transforms */ - 'name/kebab': { - type: 'name', + [transforms.nameKebab]: { + type: name, transform: function (token, config) { return kebabCase([config.prefix].concat(token.path).join(' ')); }, @@ -336,8 +338,8 @@ export default { * * @memberof Transforms */ - 'name/snake': { - type: 'name', + [transforms.nameSnake]: { + type: name, transform: function (token, config) { return snakeCase([config.prefix].concat(token.path).join(' ')); }, @@ -355,8 +357,8 @@ export default { * * @memberof Transforms */ - 'name/constant': { - type: 'name', + [transforms.nameConstant]: { + type: name, transform: function (token, config) { return snakeCase([config.prefix].concat(token.path).join(' ')).toUpperCase(); }, @@ -374,8 +376,8 @@ export default { * * @memberof Transforms */ - 'name/pascal': { - type: 'name', + [transforms.namePascal]: { + type: name, transform: function (token, config) { /** @param {string} str */ const upperFirst = function (str) { @@ -396,8 +398,8 @@ export default { * * @memberof Transforms */ - 'color/rgb': { - type: 'value', + [transforms.colorRgb]: { + type: value, filter: isColor, transform: function (token, _, options) { return Color(options.usesDtcg ? token.$value : token.value).toRgbString(); @@ -416,8 +418,8 @@ export default { * * @memberof Transforms */ - 'color/hsl': { - type: 'value', + [transforms.colorHsl]: { + type: value, filter: isColor, transform: function (token, _, options) { return Color(options.usesDtcg ? token.$value : token.value).toHslString(); @@ -436,8 +438,8 @@ export default { * * @memberof Transforms */ - 'color/hsl-4': { - type: 'value', + [transforms.colorHsl4]: { + type: value, filter: isColor, transform: function (token, _, options) { const color = Color(options.usesDtcg ? token.$value : token.value); @@ -462,8 +464,8 @@ export default { * * @memberof Transforms */ - 'color/hex': { - type: 'value', + [transforms.colorHex]: { + type: value, filter: isColor, transform: function (token, _, options) { return Color(options.usesDtcg ? token.$value : token.value).toHexString(); @@ -481,8 +483,8 @@ export default { * * @memberof Transforms */ - 'color/hex8': { - type: 'value', + [transforms.colorHex8]: { + type: value, filter: isColor, transform: function (token, _, options) { return Color(options.usesDtcg ? token.$value : token.value).toHex8String(); @@ -500,8 +502,8 @@ export default { * * @memberof Transforms */ - 'color/hex8android': { - type: 'value', + [transforms.colorHex8android]: { + type: value, filter: isColor, transform: function (token, _, options) { const str = Color(options.usesDtcg ? token.$value : token.value).toHex8(); @@ -520,8 +522,8 @@ export default { * * @memberof Transforms */ - 'color/composeColor': { - type: 'value', + [transforms.colorComposeColor]: { + type: value, filter: isColor, transform: function (token, _, options) { const str = Color(options.usesDtcg ? token.$value : token.value).toHex8(); @@ -540,8 +542,8 @@ export default { * * @memberof Transforms */ - 'color/UIColor': { - type: 'value', + [transforms.colorUIColor]: { + type: value, filter: isColor, transform: function (token, _, options) { const rgb = Color(options.usesDtcg ? token.$value : token.value).toRgb(); @@ -573,8 +575,8 @@ export default { * * @memberof Transforms */ - 'color/UIColorSwift': { - type: 'value', + [transforms.colorUIColorSwift]: { + type: value, filter: isColor, transform: function (token, _, options) { const { r, g, b, a } = Color(options.usesDtcg ? token.$value : token.value).toRgb(); @@ -596,8 +598,8 @@ export default { * * @memberof Transforms */ - 'color/ColorSwiftUI': { - type: 'value', + [transforms.colorColorSwiftUI]: { + type: value, filter: isColor, transform: function (token, _, options) { const { r, g, b, a } = Color(options.usesDtcg ? token.$value : token.value).toRgb(); @@ -620,8 +622,8 @@ export default { * * @memberof Transforms */ - 'color/css': { - type: 'value', + [transforms.colorCss]: { + type: value, filter: isColor, transform: function (token, _, options) { const color = Color(options.usesDtcg ? token.$value : token.value); @@ -651,8 +653,8 @@ export default { * ``` * @memberof Transforms */ - 'color/sketch': { - type: 'value', + [transforms.colorSketch]: { + type: value, filter: isColor, transform: function (token, _, options) { let color = Color(options.usesDtcg ? token.$value : token.value).toRgb(); @@ -676,8 +678,8 @@ export default { * * @memberof Transforms */ - 'size/sp': { - type: 'value', + [transforms.sizeSp]: { + type: value, filter: isFontSize, transform: function (token, _, options) { const nonParsedVal = options.usesDtcg ? token.$value : token.value; @@ -698,8 +700,8 @@ export default { * * @memberof Transforms */ - 'size/dp': { - type: 'value', + [transforms.sizeDp]: { + type: value, filter: isDimension, transform: function (token, _, options) { const nonParsedVal = options.usesDtcg ? token.$value : token.value; @@ -725,8 +727,8 @@ export default { * * @memberof Transforms */ - 'size/object': { - type: 'value', + [transforms.sizeObject]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -753,8 +755,8 @@ export default { * * @memberof Transforms */ - 'size/remToSp': { - type: 'value', + [transforms.sizeRemToSp]: { + type: value, filter: isFontSize, transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -776,8 +778,8 @@ export default { * * @memberof Transforms */ - 'size/remToDp': { - type: 'value', + [transforms.sizeRemToDp]: { + type: value, filter: isDimension, transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -799,8 +801,8 @@ export default { * * @memberof Transforms */ - 'size/px': { - type: 'value', + [transforms.sizePx]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, _, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -821,8 +823,8 @@ export default { * * @memberof Transforms */ - 'size/rem': { - type: 'value', + [transforms.sizeRem]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, _, options) { const nonParsed = options.usesDtcg ? token.$value : token.value; @@ -848,8 +850,8 @@ export default { * * @memberof Transforms */ - 'size/remToPt': { - type: 'value', + [transforms.sizeRemToPt]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -871,8 +873,8 @@ export default { * * @memberof Transforms */ - 'size/compose/remToSp': { - type: 'value', + [transforms.sizeComposeRemToSp]: { + type: value, filter: isFontSize, transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -894,8 +896,8 @@ export default { * * @memberof Transforms */ - 'size/compose/remToDp': { - type: 'value', + [transforms.sizeComposeRemToDp]: { + type: value, filter: isDimension, transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -917,8 +919,8 @@ export default { * * @memberof Transforms */ - 'size/compose/em': { - type: 'value', + [transforms.sizeComposeEm]: { + type: value, filter: isFontSize, transform: function (token, _, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -938,8 +940,8 @@ export default { * * @memberof Transforms */ - 'size/swift/remToCGFloat': { - type: 'value', + [transforms.sizeSwiftRemToCGFloat]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -961,8 +963,8 @@ export default { * * @memberof Transforms */ - 'size/remToPx': { - type: 'value', + [transforms.sizeRemToPx]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, config, options) { const value = options.usesDtcg ? token.$value : token.value; @@ -985,8 +987,8 @@ export default { * * @memberof Transforms */ - 'size/pxToRem': { - type: 'value', + [transforms.sizePxToRem]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: (token, config, options) => { const value = options.usesDtcg ? token.$value : token.value; @@ -1016,8 +1018,8 @@ export default { * * @memberof Transforms */ - 'html/icon': { - type: 'value', + [transforms.htmlIcon]: { + type: value, filter: function (token, options) { return (options.usesDtcg ? token.$type : token.type) === 'html'; }, @@ -1045,8 +1047,8 @@ export default { * * @memberof Transforms */ - 'content/quote': { - type: 'value', + [transforms.contentQuote]: { + type: value, filter: isContent, transform: function (token, _, options) { return wrapValueWith("'", token, options); @@ -1064,8 +1066,8 @@ export default { * * @memberof Transforms */ - 'content/objC/literal': { - type: 'value', + [transforms.contentObjCLiteral]: { + type: value, filter: isContent, transform: function (token, _, options) { return '@' + wrapValueWithDoubleQuote(token, options); @@ -1083,8 +1085,8 @@ export default { * * @memberof Transforms */ - 'content/swift/literal': { - type: 'value', + [transforms.contentSwiftLiteral]: { + type: value, filter: isContent, transform: (token, _, options) => wrapValueWithDoubleQuote(token, options), }, @@ -1100,8 +1102,8 @@ export default { * * @memberof Transforms */ - 'time/seconds': { - type: 'value', + [transforms.timeSeconds]: { + type: value, filter: function (token, options) { return (options.usesDtcg ? token.$type : token.type) === 'time'; }, @@ -1123,8 +1125,8 @@ export default { * * @memberof Transforms */ - 'fontFamily/css': { - type: 'value', + [transforms.fontFamilyCss]: { + type: value, // typography properties can be references, while fontFamily prop might not transitive: true, filter: (token, options) => { @@ -1149,8 +1151,8 @@ export default { * * @memberof Transforms */ - 'cubicBezier/css': { - type: 'value', + [transforms.cubicBezierCss]: { + type: value, // transition properties can be references, while timingFunction might not be transitive: true, filter: (token, options) => { @@ -1175,8 +1177,8 @@ export default { * * @memberof Transforms */ - 'strokeStyle/css/shorthand': { - type: 'value', + [transforms.strokeStyleCssShorthand]: { + type: value, // border properties can be references, while style property might not be transitive: true, filter: (token, options) => (options.usesDtcg ? token.$type : token.type) === 'strokeStyle', @@ -1202,8 +1204,8 @@ export default { * * @memberof Transforms */ - 'border/css/shorthand': { - type: 'value', + [transforms.borderCssShorthand]: { + type: value, // border properties can be references transitive: true, filter: (token, options) => (options.usesDtcg ? token.$type : token.type) === 'border', @@ -1242,8 +1244,8 @@ export default { * * @memberof Transforms */ - 'typography/css/shorthand': { - type: 'value', + [transforms.typographyCssShorthand]: { + type: value, // typography properties can be references transitive: true, filter: (token, options) => (options.usesDtcg ? token.$type : token.type) === 'typography', @@ -1298,8 +1300,8 @@ export default { * * @memberof Transforms */ - 'transition/css/shorthand': { - type: 'value', + [transforms.transitionCssShorthand]: { + type: value, // transition properties can be references transitive: true, filter: (token, options) => (options.usesDtcg ? token.$type : token.type) === 'transition', @@ -1327,8 +1329,8 @@ export default { * * @memberof Transforms */ - 'shadow/css/shorthand': { - type: 'value', + [transforms.shadowCssShorthand]: { + type: value, // shadow properties can be references transitive: true, filter: (token, options) => (options.usesDtcg ? token.$type : token.type) === 'shadow', @@ -1369,8 +1371,8 @@ export default { * * @memberof Transforms */ - 'asset/url': { - type: 'value', + [transforms.assetUrl]: { + type: value, filter: isAsset, transform: function (token, _, options) { return `url("${(options.usesDtcg ? token.$value : token.value).replace(/"/g, `\\"`)}")`; @@ -1388,8 +1390,8 @@ export default { * * @memberof Transforms */ - 'asset/base64': { - type: 'value', + [transforms.assetBase64]: { + type: value, filter: isAsset, transform: function (token, _, options, vol) { return convertToBase64(options.usesDtcg ? token.$value : token.value, vol); @@ -1407,8 +1409,8 @@ export default { * * @memberof Transforms */ - 'asset/path': { - type: 'value', + [transforms.assetPath]: { + type: value, filter: isAsset, transform: function (token, _, options) { return join(process?.cwd() ?? '/', options.usesDtcg ? token.$value : token.value); @@ -1425,8 +1427,8 @@ export default { * * @memberof Transforms */ - 'asset/objC/literal': { - type: 'value', + [transforms.assetObjCLiteral]: { + type: value, filter: isAsset, transform: function (token, _, options) { return '@' + wrapValueWithDoubleQuote(token, options); @@ -1443,8 +1445,8 @@ export default { * * @memberof Transforms */ - 'asset/swift/literal': { - type: 'value', + [transforms.assetSwiftLiteral]: { + type: value, filter: isAsset, transform: (token, _, options) => wrapValueWithDoubleQuote(token, options), }, @@ -1459,8 +1461,8 @@ export default { * @memberof Transforms * */ - 'color/hex8flutter': { - type: 'value', + [transforms.colorHex8flutter]: { + type: value, filter: isColor, transform: function (token, _, options) { const str = Color(options.usesDtcg ? token.$value : token.value) @@ -1480,8 +1482,8 @@ export default { * * @memberof Transforms */ - 'content/flutter/literal': { - type: 'value', + [transforms.contentFlutterLiteral]: { + type: value, filter: isContent, transform: (token, _, options) => wrapValueWithDoubleQuote(token, options), }, @@ -1496,8 +1498,8 @@ export default { * * @memberof Transforms */ - 'asset/flutter/literal': { - type: 'value', + [transforms.assetFlutterLiteral]: { + type: value, filter: isAsset, transform: (token, _, options) => wrapValueWithDoubleQuote(token, options), }, @@ -1512,8 +1514,8 @@ export default { * * @memberof Transforms */ - 'size/flutter/remToDouble': { - type: 'value', + [transforms.sizeFlutterRemToDouble]: { + type: value, filter: (token, options) => isDimension(token, options) || isFontSize(token, options), transform: function (token, config, options) { const baseFont = getBasePxFontSize(config); diff --git a/lib/enums/actions.js b/lib/enums/actions.js new file mode 100644 index 000000000..535f4ccac --- /dev/null +++ b/lib/enums/actions.js @@ -0,0 +1,4 @@ +export const actions = { + androidCopyImages: /** @type {'android/copyImages'} */ ('android/copyImages'), + copyAssets: /** @type {'copy_assets'} */ ('copy_assets'), +}; diff --git a/lib/enums/commentPositions.js b/lib/enums/commentPositions.js new file mode 100644 index 000000000..4cbd63b7b --- /dev/null +++ b/lib/enums/commentPositions.js @@ -0,0 +1,4 @@ +export const commentPositions = { + above: /** @type {'above'} */ ('above'), + inline: /** @type {'inline'} */ ('inline'), +}; diff --git a/lib/enums/commentStyles.js b/lib/enums/commentStyles.js new file mode 100644 index 000000000..498b79f4f --- /dev/null +++ b/lib/enums/commentStyles.js @@ -0,0 +1,5 @@ +export const commentStyles = { + short: /** @type {'short'} */ ('short'), + long: /** @type {'long'} */ ('long'), + none: /** @type {'none'} */ ('none'), +}; diff --git a/lib/enums/fileHeaderCommentStyles.js b/lib/enums/fileHeaderCommentStyles.js new file mode 100644 index 000000000..ee2a03e05 --- /dev/null +++ b/lib/enums/fileHeaderCommentStyles.js @@ -0,0 +1,5 @@ +export const fileHeaderCommentStyles = { + short: /** @type {'short'} */ ('short'), + long: /** @type {'long'} */ ('long'), + xml: /** @type {'xml'} */ ('xml'), +}; diff --git a/lib/enums/formats.js b/lib/enums/formats.js new file mode 100644 index 000000000..4d81bd499 --- /dev/null +++ b/lib/enums/formats.js @@ -0,0 +1,50 @@ +export const formats = { + androidColors: /** @type {'android/colors'} */ ('android/colors'), + androidDimens: /** @type {'android/dimens'} */ ('android/dimens'), + androidFontDimens: /** @type {'android/fontDimens'} */ ('android/fontDimens'), + androidIntegers: /** @type {'android/integers'} */ ('android/integers'), + androidResources: /** @type {'android/resources'} */ ('android/resources'), + androidStrings: /** @type {'android/strings'} */ ('android/strings'), + composeObject: /** @type {'compose/object'} */ ('compose/object'), + cssVariables: /** @type {'css/variables'} */ ('css/variables'), + cssFonts: /** @type {'css/fonts.css'} */ ('css/fonts.css'), + flutterClassDart: /** @type {'flutter/class.dart'} */ ('flutter/class.dart'), + iosColorsH: /** @type {'ios/colors.h'} */ ('ios/colors.h'), + iosColorsM: /** @type {'ios/colors.m'} */ ('ios/colors.m'), + iosMacros: /** @type {'ios/macros'} */ ('ios/macros'), + iosPlist: /** @type {'ios/plist'} */ ('ios/plist'), + iosSingletonH: /** @type {'ios/singleton.h'} */ ('ios/singleton.h'), + iosSingletonM: /** @type {'ios/singleton.m'} */ ('ios/singleton.m'), + iosStaticH: /** @type {'ios/static.h'} */ ('ios/static.h'), + iosStaticM: /** @type {'ios/static.m'} */ ('ios/static.m'), + iosStringsH: /** @type {'ios/strings.h'} */ ('ios/strings.h'), + iosStringsM: /** @type {'ios/strings.m'} */ ('ios/strings.m'), + iosSwiftAnySwift: /** @type {'ios-swift/any.swift'} */ ('ios-swift/any.swift'), + iosSwiftClassSwift: /** @type {'ios-swift/class.swift'} */ ('ios-swift/class.swift'), + iosSwiftEnumSwift: /** @type {'ios-swift/enum.swift'} */ ('ios-swift/enum.swift'), + javascriptEs6: /** @type {'javascript/es6'} */ ('javascript/es6'), + javascriptEsm: /** @type {'javascript/esm'} */ ('javascript/esm'), + javascriptModule: /** @type {'javascript/module'} */ ('javascript/module'), + javascriptModuleFlat: /** @type {'javascript/module-flat'} */ ('javascript/module-flat'), + javascriptObject: /** @type {'javascript/object'} */ ('javascript/object'), + javascriptUmd: /** @type {'javascript/umd'} */ ('javascript/umd'), + json: /** @type {'json'} */ ('json'), + jsonAsset: /** @type {'json/asset'} */ ('json/asset'), + jsonNested: /** @type {'json/nested'} */ ('json/nested'), + jsonFlat: /** @type {'json/flat'} */ ('json/flat'), + sketchPalette: /** @type {'sketchPalette'} */ ('sketchPalette'), + sketchPaletteV2: /** @type {'sketch/palette/v2'} */ ('sketch/palette/v2'), + lessIcons: /** @type {'less/icons'} */ ('less/icons'), + lessVariables: /** @type {'less/variables'} */ ('less/variables'), + scssIcons: /** @type {'scss/icons'} */ ('scss/icons'), + scssMapDeep: /** @type {'scss/map-deep'} */ ('scss/map-deep'), + scssMapFlat: /** @type {'scss/map-flat'} */ ('scss/map-flat'), + scssVariables: /** @type {'scss/variables'} */ ('scss/variables'), + stylusVariables: /** @type {'stylus/variables'} */ ('stylus/variables'), + typescriptEs6Declarations: /** @type {'typescript/es6-declarations'} */ ( + 'typescript/es6-declarations' + ), + typescriptModuleDeclarations: /** @type {'typescript/module-declarations'} */ ( + 'typescript/module-declarations' + ), +}; diff --git a/lib/enums/index.js b/lib/enums/index.js new file mode 100644 index 000000000..773f8e632 --- /dev/null +++ b/lib/enums/index.js @@ -0,0 +1,12 @@ +export { actions } from './actions.js'; +export { logWarningLevels } from './logWarningLevels.js'; +export { logVerbosityLevels } from './logVerbosityLevels.js'; +export { logBrokenReferenceLevels } from './logBrokenReferenceLevels.js'; +export { commentStyles } from './commentStyles.js'; +export { commentPositions } from './commentPositions.js'; +export { fileHeaderCommentStyles } from './fileHeaderCommentStyles.js'; +export { formats } from './formats.js'; +export { transformGroups } from './transformGroups.js'; +export { transforms } from './transforms.js'; +export { transformTypes } from './transformTypes.js'; +export { propertyFormatNames } from './propertyFormatNames.js'; diff --git a/lib/enums/logBrokenReferenceLevels.js b/lib/enums/logBrokenReferenceLevels.js new file mode 100644 index 000000000..e2dae84c6 --- /dev/null +++ b/lib/enums/logBrokenReferenceLevels.js @@ -0,0 +1,4 @@ +export const logBrokenReferenceLevels = { + throw: /** @type {'throw'} */ ('throw'), + console: /** @type {'console'} */ ('console'), +}; diff --git a/lib/enums/logVerbosityLevels.js b/lib/enums/logVerbosityLevels.js new file mode 100644 index 000000000..98b5ea83c --- /dev/null +++ b/lib/enums/logVerbosityLevels.js @@ -0,0 +1,5 @@ +export const logVerbosityLevels = { + default: /** @type {'default'} */ ('default'), + silent: /** @type {'silent'} */ ('silent'), + verbose: /** @type {'verbose'} */ ('verbose'), +}; diff --git a/lib/enums/logWarningLevels.js b/lib/enums/logWarningLevels.js new file mode 100644 index 000000000..fa4764e77 --- /dev/null +++ b/lib/enums/logWarningLevels.js @@ -0,0 +1,5 @@ +export const logWarningLevels = { + warn: /** @type {'warn'} */ ('warn'), + error: /** @type {'error'} */ ('error'), + disabled: /** @type {'disabled'} */ ('disabled'), +}; diff --git a/lib/enums/propertyFormatNames.js b/lib/enums/propertyFormatNames.js new file mode 100644 index 000000000..e533b2ed5 --- /dev/null +++ b/lib/enums/propertyFormatNames.js @@ -0,0 +1,6 @@ +export const propertyFormatNames = { + css: /** @type {'css'} */ ('css'), + sass: /** @type {'sass'} */ ('sass'), + less: /** @type {'less'} */ ('less'), + stylus: /** @type {'stylus'} */ ('stylus'), +}; diff --git a/lib/enums/transformGroups.js b/lib/enums/transformGroups.js new file mode 100644 index 000000000..c9802fc65 --- /dev/null +++ b/lib/enums/transformGroups.js @@ -0,0 +1,17 @@ +export const transformGroups = { + web: /** @type {'web'} */ ('web'), + js: /** @type {'js'} */ ('js'), + scss: /** @type {'scss'} */ ('scss'), + css: /** @type {'css'} */ ('css'), + less: /** @type {'less'} */ ('less'), + html: /** @type {'html'} */ ('html'), + android: /** @type {'android'} */ ('android'), + compose: /** @type {'compose'} */ ('compose'), + ios: /** @type {'ios'} */ ('ios'), + iosSwift: /** @type {'ios-swift'} */ ('ios-swift'), + iosSwiftSeparate: /** @type {'ios-swift-separate'} */ ('ios-swift-separate'), + assets: /** @type {'assets'} */ ('assets'), + flutter: /** @type {'flutter'} */ ('flutter'), + flutterSeparate: /** @type {'flutter-separate'} */ ('flutter-separate'), + reactNative: /** @type {'react-native'} */ ('react-native'), +}; diff --git a/lib/enums/transformTypes.js b/lib/enums/transformTypes.js new file mode 100644 index 000000000..8c5e6f9ec --- /dev/null +++ b/lib/enums/transformTypes.js @@ -0,0 +1,5 @@ +export const transformTypes = { + attribute: /** @type {'attribute'} */ ('attribute'), + name: /** @type {'name'} */ ('name'), + value: /** @type {'value'} */ ('value'), +}; diff --git a/lib/enums/transforms.js b/lib/enums/transforms.js new file mode 100644 index 000000000..263370bb2 --- /dev/null +++ b/lib/enums/transforms.js @@ -0,0 +1,57 @@ +export const transforms = { + attributeCti: /** @type {'attribute/cti'} */ ('attribute/cti'), + attributeColor: /** @type {'attribute/color'} */ ('attribute/color'), + nameHuman: /** @type {'name/human'} */ ('name/human'), + nameCamel: /** @type {'name/camel'} */ ('name/camel'), + nameKebab: /** @type {'name/kebab'} */ ('name/kebab'), + nameSnake: /** @type {'name/snake'} */ ('name/snake'), + nameConstant: /** @type {'name/constant'} */ ('name/constant'), + namePascal: /** @type {'name/pascal'} */ ('name/pascal'), + colorRgb: /** @type {'color/rgb'} */ ('color/rgb'), + colorHsl: /** @type {'color/hsl'} */ ('color/hsl'), + colorHsl4: /** @type {'color/hsl-4'} */ ('color/hsl-4'), + colorHex: /** @type {'color/hex'} */ ('color/hex'), + colorHex8: /** @type {'color/hex8'} */ ('color/hex8'), + colorHex8android: /** @type {'color/hex8android'} */ ('color/hex8android'), + colorComposeColor: /** @type {'color/composeColor'} */ ('color/composeColor'), + colorUIColor: /** @type {'color/UIColor'} */ ('color/UIColor'), + colorUIColorSwift: /** @type {'color/UIColorSwift'} */ ('color/UIColorSwift'), + colorColorSwiftUI: /** @type {'color/ColorSwiftUI'} */ ('color/ColorSwiftUI'), + colorCss: /** @type {'color/css'} */ ('color/css'), + colorSketch: /** @type {'color/sketch'} */ ('color/sketch'), + sizeSp: /** @type {'size/sp'} */ ('size/sp'), + sizeDp: /** @type {'size/dp'} */ ('size/dp'), + sizeObject: /** @type {'size/object'} */ ('size/object'), + sizeRemToSp: /** @type {'size/remToSp'} */ ('size/remToSp'), + sizeRemToDp: /** @type {'size/remToDp'} */ ('size/remToDp'), + sizePx: /** @type {'size/px'} */ ('size/px'), + sizeRem: /** @type {'size/rem'} */ ('size/rem'), + sizeRemToPt: /** @type {'size/remToPt'} */ ('size/remToPt'), + sizeComposeRemToSp: /** @type {'size/compose/remToSp'} */ ('size/compose/remToSp'), + sizeComposeRemToDp: /** @type {'size/compose/remToDp'} */ ('size/compose/remToDp'), + sizeComposeEm: /** @type {'size/compose/em'} */ ('size/compose/em'), + sizeSwiftRemToCGFloat: /** @type {'size/swift/remToCGFloat'} */ ('size/swift/remToCGFloat'), + sizeRemToPx: /** @type {'size/remToPx'} */ ('size/remToPx'), + sizePxToRem: /** @type {'size/pxToRem'} */ ('size/pxToRem'), + htmlIcon: /** @type {'html/icon'} */ ('html/icon'), + contentQuote: /** @type {'content/quote'} */ ('content/quote'), + contentObjCLiteral: /** @type {'content/objC/literal'} */ ('content/objC/literal'), + contentSwiftLiteral: /** @type {'content/swift/literal'} */ ('content/swift/literal'), + timeSeconds: /** @type {'time/seconds'} */ ('time/seconds'), + fontFamilyCss: /** @type {'fontFamily/css'} */ ('fontFamily/css'), + cubicBezierCss: /** @type {'cubicBezier/css'} */ ('cubicBezier/css'), + strokeStyleCssShorthand: /** @type {'strokeStyle/css/shorthand'} */ ('strokeStyle/css/shorthand'), + borderCssShorthand: /** @type {'border/css/shorthand'} */ ('border/css/shorthand'), + typographyCssShorthand: /** @type {'typography/css/shorthand'} */ ('typography/css/shorthand'), + transitionCssShorthand: /** @type {'transition/css/shorthand'} */ ('transition/css/shorthand'), + shadowCssShorthand: /** @type {'shadow/css/shorthand'} */ ('shadow/css/shorthand'), + assetUrl: /** @type {'asset/url'} */ ('asset/url'), + assetBase64: /** @type {'asset/base64'} */ ('asset/base64'), + assetPath: /** @type {'asset/path'} */ ('asset/path'), + assetObjCLiteral: /** @type {'asset/objC/literal'} */ ('asset/objC/literal'), + assetSwiftLiteral: /** @type {'asset/swift/literal'} */ ('asset/swift/literal'), + colorHex8flutter: /** @type {'color/hex8flutter'} */ ('color/hex8flutter'), + contentFlutterLiteral: /** @type {'content/flutter/literal'} */ ('content/flutter/literal'), + assetFlutterLiteral: /** @type {'asset/flutter/literal'} */ ('asset/flutter/literal'), + sizeFlutterRemToDouble: /** @type {'size/flutter/remToDouble'} */ ('size/flutter/remToDouble'), +}; diff --git a/lib/transform/config.js b/lib/transform/config.js index 44efa824d..ce9e14253 100644 --- a/lib/transform/config.js +++ b/lib/transform/config.js @@ -16,6 +16,7 @@ import deepExtend from '../utils/deepExtend.js'; import GroupMessages from '../utils/groupMessages.js'; import { deepmerge } from '../utils/deepmerge.js'; import chalk from 'chalk'; +import { logWarningLevels, logVerbosityLevels } from '../enums/index.js'; /** * @typedef {import('../StyleDictionary.js').default} StyleDictionary @@ -197,9 +198,9 @@ None of ${transform_warnings} match the name of a registered transform. /** @param {string} action */ function (action) { if (typeof dictionary.hooks.actions?.[action].undo !== 'function') { const message = `${action} action does not have a clean function!`; - if (to_ret.log?.warnings === 'error') { + if (to_ret.log?.warnings === logWarningLevels.error) { throw new Error(message); - } else if (to_ret.log?.verbosity !== 'silent') { + } else if (to_ret.log?.verbosity !== logVerbosityLevels.silent) { // eslint-disable-next-line no-console console.log(chalk.rgb(255, 140, 0).bold(message)); } diff --git a/lib/transform/token.js b/lib/transform/token.js index 09d71ffeb..48ee5c691 100644 --- a/lib/transform/token.js +++ b/lib/transform/token.js @@ -12,6 +12,7 @@ */ import usesReferences from '../utils/references/usesReferences.js'; +import { transformTypes } from '../enums/index.js'; /** * @typedef {import('../../types/Volume.d.ts').Volume} Volume @@ -22,6 +23,12 @@ import usesReferences from '../utils/references/usesReferences.js'; * @typedef {import('../../types/Transform.d.ts').NameTransform} NameTransform */ +const { + value: transformTypeValue, + name: transformTypeName, + attribute: transformTypeAttribute, +} = transformTypes; + /** * Applies all transforms to a token. This is a pure function, * it returns a new token object rather than mutating it inline. @@ -41,7 +48,7 @@ export default async function transformToken(token, config, options, vol) { const transform = transforms[i]; if (!transform.filter || transform.filter(to_ret, options)) { - if (transform.type === 'name') { + if (transform.type === transformTypeName) { to_ret.name = await /** @type {Omit} */ (transform).transform( to_ret, config, @@ -52,7 +59,7 @@ export default async function transformToken(token, config, options, vol) { // Don't try to transform the value if it is referencing another value // Only try to transform if the value is not a string or if it has '{}' if ( - transform.type === 'value' && + transform.type === transformTypeValue && !usesReferences(options.usesDtcg ? token.$value : token.value, config) ) { // Only transform non-referenced values (from original) @@ -72,7 +79,7 @@ export default async function transformToken(token, config, options, vol) { } } - if (transform.type === 'attribute') + if (transform.type === transformTypeAttribute) to_ret.attributes = Object.assign( {}, to_ret.attributes, diff --git a/package.json b/package.json index 5aef0f706..913d09c73 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "default": "./lib/fs.js" }, "./utils": "./lib/utils/index.js", + "./enums": "./lib/enums/index.js", "./types": "./types/index.d.ts" }, "bin": { diff --git a/types/Config.ts b/types/Config.ts index aa9557167..d8915d33b 100644 --- a/types/Config.ts +++ b/types/Config.ts @@ -19,6 +19,15 @@ import type { Preprocessor } from './Preprocessor.js'; import type { Transform } from './Transform.js'; import type { Format, OutputReferences } from './Format.js'; import type { Action } from './Action.js'; +import { + logBrokenReferenceLevels, + logWarningLevels, + logVerbosityLevels, +} from '../lib/enums/index.js'; + +type logWarningLevels = typeof logWarningLevels; +type logVerbosityLevels = typeof logVerbosityLevels; +type logBrokenReferenceLevels = typeof logBrokenReferenceLevels; export interface Hooks { parsers?: Record>; @@ -67,10 +76,10 @@ export interface ResolveReferencesOptionsInternal extends ResolveReferencesOptio } export interface LogConfig { - warnings?: 'warn' | 'error' | 'disabled'; - verbosity?: 'default' | 'silent' | 'verbose'; + warnings?: logWarningLevels[keyof logWarningLevels]; + verbosity?: logVerbosityLevels[keyof logVerbosityLevels]; errors?: { - brokenReferences?: 'throw' | 'console'; + brokenReferences?: logBrokenReferenceLevels[keyof logBrokenReferenceLevels]; }; } diff --git a/types/File.ts b/types/File.ts index a5ddca8e0..e97fef4d6 100644 --- a/types/File.ts +++ b/types/File.ts @@ -2,6 +2,10 @@ import type { TransformedToken } from './DesignToken.js'; import type { FormatFn } from './Format.js'; import type { LocalOptions, Config } from './Config.js'; import type { Filter } from './Filter.js'; +import { commentPositions, commentStyles } from '../lib/enums/index.js'; + +type commentStyles = typeof commentStyles; +type commentPositions = typeof commentPositions; // Generally, overriding these would break most formats and are meant // for the FormattedVariables/createPropertyFormatter helpers, @@ -16,8 +20,8 @@ export interface FormattingOptions extends FormattingOverrides { // to customize the output // Be careful with indentation if the output syntax is indentation-sensitive (e.g. python, yaml) export interface FormattingOverrides { - commentStyle?: 'short' | 'long' | 'none'; - commentPosition?: 'above' | 'inline'; + commentStyle?: commentStyles[keyof commentStyles]; + commentPosition?: commentPositions[keyof commentPositions]; indentation?: string; header?: string; footer?: string; diff --git a/types/Format.ts b/types/Format.ts index 270df5d49..d3e33c025 100644 --- a/types/Format.ts +++ b/types/Format.ts @@ -14,6 +14,8 @@ import type { Dictionary, TransformedToken } from './DesignToken.js'; import type { File } from './File.js'; import type { LocalOptions, Config, PlatformConfig } from './Config.js'; +import { formats } from '../lib/enums/index.js'; +type formats = typeof formats; export interface FormatFnArguments { /** @@ -43,7 +45,7 @@ export type FormatFn = ((args: FormatFnArguments) => unknown | Promise) }; export interface Format { - name: string; + name: string | formats[keyof formats]; format: FormatFn; } diff --git a/types/Transform.ts b/types/Transform.ts index 348ce9b3e..3b00fceb1 100644 --- a/types/Transform.ts +++ b/types/Transform.ts @@ -15,6 +15,7 @@ import type { Filter } from './Filter.js'; import type { TransformedToken } from './DesignToken.js'; import type { PlatformConfig, Config } from './Config.js'; import type { Volume } from './Volume.js'; +import { transformTypes } from '../lib/enums/index.js'; interface BaseTransform { name: string; @@ -29,8 +30,11 @@ interface BaseTransform { ) => Promise | Value; } -export type NameTransform = BaseTransform<'name', string>; -export type AttributeTransform = BaseTransform<'attribute', Record>; -export type ValueTransform = BaseTransform<'value', unknown | undefined>; +export type NameTransform = BaseTransform; +export type AttributeTransform = BaseTransform< + typeof transformTypes.attribute, + Record +>; +export type ValueTransform = BaseTransform; export type Transform = NameTransform | AttributeTransform | ValueTransform;