diff --git a/package-lock.json b/package-lock.json index a8d41dd07..675acea01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,6 @@ "css-tree": "2.3.1", "figma-api-exporter": "github:brave/figma-api-exporter#08ea66f0794fcb3fa0240692d9016a562b4fbcef", "jsdom": "21.1.2", - "lodash.camelcase": "4.3.0", "lodash.merge": "4.6.2", "postcss": "8.5.3", "postcss-js": "4.0.1", @@ -61,7 +60,7 @@ "sass": "1.86.0", "sass-loader": "13.3.3", "storybook": "8.6.12", - "style-dictionary": "3.9.2", + "style-dictionary": "4.3.3", "style-loader": "3.3.4", "svelte-check": "3.8.6", "svelte-loader": "3.2.4", @@ -631,6 +630,97 @@ "license": "MIT", "peer": true }, + "node_modules/@bundled-es-modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-Rk453EklPUPC3NRWc3VUNI/SSUjdBaFoaQvFRmNBNtMHVtOFD5AntiWg5kEE1hqcPqedYFDzxE3ZcMYPcA195w==", + "dev": true, + "license": "ISC", + "dependencies": { + "deepmerge": "^4.3.1" + } + }, + "node_modules/@bundled-es-modules/glob": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-740y5ofkzydsFao5EXJrGilcIL6EFEw/cmPf2uhTw9J6G1YOhiIFjNFCHdpgEiiH5VlU3G0SARSjlFlimRRSMA==", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "buffer": "^6.0.3", + "events": "^3.3.0", + "glob": "^10.4.2", + "patch-package": "^8.0.0", + "path": "^0.12.7", + "stream": "^0.0.3", + "string_decoder": "^1.3.0", + "url": "^0.11.3" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@bundled-es-modules/memfs": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/memfs/-/memfs-4.17.0.tgz", + "integrity": "sha512-ykdrkEmQr9BV804yd37ikXfNnvxrwYfY9Z2/EtMHFEFadEjsQXJ1zL9bVZrKNLDtm91UdUOEHso6Aweg93K6xQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "assert": "^2.1.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "memfs": "^4.17.0", + "path": "^0.12.7", + "stream": "^0.0.3", + "util": "^0.12.5" + } + }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -1784,6 +1874,63 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.2.0.tgz", + "integrity": "sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz", + "integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@material/material-color-utilities": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.3.0.tgz", @@ -3896,6 +4043,25 @@ "license": "Apache-2.0", "peer": true }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@zip.js/zip.js": { + "version": "2.7.60", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.60.tgz", + "integrity": "sha512-vA3rLyqdxBrVo1FWSsbyoecaqWTV+vgPRf0QKeM7kVDG0r+lHUqd7zQDv1TO9k4BcAoNzNDSNrrel24Mk6addA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "bun": ">=0.7.0", + "deno": ">=1.0.0", + "node": ">=16.5.0" + } + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -4140,6 +4306,20 @@ "dequal": "^2.0.3" } }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -4175,6 +4355,16 @@ "dev": true, "license": "MIT" }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -4345,6 +4535,27 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/better-opn": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", @@ -4470,6 +4681,31 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-crc32": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", @@ -4506,9 +4742,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4518,6 +4754,23 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -4528,17 +4781,6 @@ "node": ">=6" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -4580,18 +4822,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, "node_modules/chai": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", @@ -4625,25 +4855,11 @@ } }, "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", "dev": true, - "license": "MIT", - "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } + "license": "MIT" }, "node_modules/char-regex": { "version": "1.0.2", @@ -4899,13 +5115,13 @@ } }, "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 12" + "node": ">=18" } }, "node_modules/common-path-prefix": { @@ -4915,24 +5131,25 @@ "dev": true, "license": "ISC" }, + "node_modules/component-emitter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-2.0.0.tgz", + "integrity": "sha512-4m5s3Me2xxlVKG9PkZpQqHQR7bgpnN7joDMJ4yvVkVXngjoITG76IaZmzmywSeRTeTpc6N6r3H3+KyUurV8OYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -5302,6 +5519,24 @@ "node": ">=8" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -5510,24 +5745,13 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/dunder-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", - "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", + "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" }, @@ -5673,6 +5897,18 @@ "license": "MIT", "peer": true }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-toolkit": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.29.0.tgz", @@ -6086,7 +6322,6 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.8.x" } @@ -6315,6 +6550,16 @@ "node": ">=8" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -6407,18 +6652,19 @@ } }, "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "license": "MIT", "dependencies": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/fs.realpath": { @@ -6479,19 +6725,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.5.tgz", - "integrity": "sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "dunder-proto": "^1.0.0", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", - "hasown": "^2.0.2" + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6511,8 +6759,21 @@ "node": ">=8.0.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, @@ -6667,17 +6928,6 @@ "node": ">= 0.4" } }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -6762,6 +7012,16 @@ "node": ">=10.17.0" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -6788,6 +7048,27 @@ "postcss": "^8.1.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -7044,6 +7325,23 @@ "dev": true, "license": "MIT" }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -7053,6 +7351,19 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -7117,6 +7428,13 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -8333,6 +8651,26 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.2.1.tgz", + "integrity": "sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -8353,13 +8691,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -8373,6 +8704,16 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -8383,6 +8724,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -8488,13 +8839,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -8609,12 +8953,41 @@ "dev": true, "license": "MIT" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "license": "CC0-1.0" }, + "node_modules/memfs": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.17.0.tgz", + "integrity": "sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, "node_modules/memoizerific": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", @@ -8915,6 +9288,67 @@ "node": ">= 6" } }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8976,6 +9410,16 @@ "node": ">= 0.8.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -9041,17 +9485,6 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9116,15 +9549,86 @@ "tslib": "^2.0.3" } }, - "node_modules/path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "node_modules/patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", "dev": true, "license": "MIT", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" } }, "node_modules/path-exists": { @@ -9184,6 +9688,30 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, + "node_modules/path-unified": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/path-unified/-/path-unified-0.2.0.tgz", + "integrity": "sha512-MNKqvrKbbbb5p7XHXV6ZAsf/1f/yJQa13S/fcX0uua8ew58Tgc6jXV+16JyAbnR/clgCH+euKDxrF2STxMHdrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" + }, + "node_modules/path/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, "node_modules/pathval": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", @@ -9773,6 +10301,22 @@ "teleport": ">=0.2.0" } }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -10148,8 +10692,7 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -10279,18 +10822,6 @@ "semver": "bin/semver.js" } }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -10340,6 +10871,82 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -10366,17 +10973,6 @@ "node": ">=8" } }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/sorcery": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.1.tgz", @@ -10487,6 +11083,26 @@ } } }, + "node_modules/stream": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.3.tgz", + "integrity": "sha512-aMsbn7VKrl4A2T7QAQQbzgN7NVc70vgF5INQrBXqn4dCXN1zy3L9HGgLO5s7PExmdrzTJ8uR/27aviW8or8/+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^2.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -10604,74 +11220,45 @@ } }, "node_modules/style-dictionary": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/style-dictionary/-/style-dictionary-3.9.2.tgz", - "integrity": "sha512-M2pcQ6hyRtqHOh+NyT6T05R3pD/gwNpuhREBKvxC1En0vyywx+9Wy9nXWT1SZ9ePzv1vAo65ItnpA16tT9ZUCg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/style-dictionary/-/style-dictionary-4.3.3.tgz", + "integrity": "sha512-93ISASYmvGdKOvNHFaOZ+mVsCNQdoZzhSEq7JINE0BjMoE8zUzkwFyGDUBnfmXayHq/F4B4MCWmtjqjgHAYthw==", "dev": true, + "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "chalk": "^4.0.0", - "change-case": "^4.1.2", - "commander": "^8.3.0", - "fs-extra": "^10.0.0", - "glob": "^10.3.10", + "@bundled-es-modules/deepmerge": "^4.3.1", + "@bundled-es-modules/glob": "^10.4.2", + "@bundled-es-modules/memfs": "^4.9.4", + "@zip.js/zip.js": "^2.7.44", + "chalk": "^5.3.0", + "change-case": "^5.3.0", + "commander": "^12.1.0", + "is-plain-obj": "^4.1.0", "json5": "^2.2.2", - "jsonc-parser": "^3.0.0", - "lodash": "^4.17.15", - "tinycolor2": "^1.4.1" + "patch-package": "^8.0.0", + "path-unified": "^0.2.0", + "prettier": "^3.3.3", + "tinycolor2": "^1.6.0" }, "bin": { - "style-dictionary": "bin/style-dictionary" + "style-dictionary": "bin/style-dictionary.js" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, - "node_modules/style-dictionary/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/style-dictionary/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/style-dictionary/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/style-dictionary/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/style-loader": { @@ -11590,6 +12177,19 @@ "node": ">=0.8" } }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -11621,6 +12221,19 @@ "node": ">=14.0.0" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -11680,6 +12293,23 @@ "node": ">=14" } }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/ts-dedent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", @@ -11911,26 +12541,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -11941,6 +12551,20 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -11952,6 +12576,13 @@ "requires-port": "^1.0.0" } }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", diff --git a/package.json b/package.json index 38836dfd7..2c4794434 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "css-tree": "2.3.1", "figma-api-exporter": "github:brave/figma-api-exporter#08ea66f0794fcb3fa0240692d9016a562b4fbcef", "jsdom": "21.1.2", - "lodash.camelcase": "4.3.0", "lodash.merge": "4.6.2", "postcss": "8.5.3", "postcss-js": "4.0.1", @@ -54,7 +53,7 @@ "sass": "1.86.0", "sass-loader": "13.3.3", "storybook": "8.6.12", - "style-dictionary": "3.9.2", + "style-dictionary": "4.3.3", "style-loader": "3.3.4", "svelte-check": "3.8.6", "svelte-loader": "3.2.4", diff --git a/src/postcss/theme.js b/src/postcss/theme.js index d5e0a055c..20e86f3cb 100644 --- a/src/postcss/theme.js +++ b/src/postcss/theme.js @@ -37,8 +37,8 @@ const defaultOptions = { /** * @param {{ - * darkSelector: string, - * lightSelector: string, + * darkSelector?: string, + * lightSelector?: string, * wrapSelector?: (selector: string) => string, * }} options The options for configuring the selectors for darkmode. */ diff --git a/src/scripts/common.js b/src/scripts/common.js index 000ad8410..a1b751b08 100644 --- a/src/scripts/common.js +++ b/src/scripts/common.js @@ -6,7 +6,7 @@ import { fileURLToPath } from 'url' /** * Recursively walks all files in a folder * @param {string} dir The directory to walk - * @param {((name: string, path: string, entry: Dirent) => boolean)?} skip A function for filtering out entries + * @param {((name: string, path: string, entry: Dirent) => boolean)} [skip] A function for filtering out entries * @returns {Promise} */ export async function* walk(dir, skip) { diff --git a/src/tokens/config.ts b/src/tokens/config.ts index 7977cdbad..5cde93fe8 100644 --- a/src/tokens/config.ts +++ b/src/tokens/config.ts @@ -1,4 +1,4 @@ -import { Config } from 'style-dictionary' +import type { Config } from 'style-dictionary/types' import leoParser from './transformation/common/leoParser' function formatLayerPathPart( @@ -12,13 +12,23 @@ function formatLayerPathPart( export default function getConfig(layers: string[]) { return { + hooks: { + parsers: { + 'leo-parser': leoParser + } + }, + parsers: ['leo-parser'], source: layers.map((layer) => `src/tokens/${layer}*.json`), - parsers: [leoParser], platforms: { tailwind: { transformGroup: 'tailwind/css', buildPath: 'tokens/tailwind/', preset: formatLayerPathPart(layers), + options: { + formatting: { + fileHeaderTimestamp: true + } + }, files: [ { destination: `${formatLayerPathPart(layers, { @@ -61,16 +71,19 @@ export default function getConfig(layers: string[]) { css: { transformGroup: 'custom/css', buildPath: 'tokens/css/', + options: { + showFileHeader: true, + formatting: { + fileHeaderTimestamp: true + } + }, files: [ { destination: `variables${formatLayerPathPart(layers, { prefix: '-' })}.css`, format: 'custom/css', - filter: 'filterWeb', - options: { - showFileHeader: true - } + filter: 'filterWeb' }, { destination: `variables${formatLayerPathPart(layers, { @@ -84,6 +97,11 @@ export default function getConfig(layers: string[]) { 'json-flat': { transformGroup: 'js', buildPath: 'tokens/json/', + options: { + formatting: { + fileHeaderTimestamp: true + } + }, files: [ { destination: `styles${formatLayerPathPart(layers, { @@ -96,6 +114,11 @@ export default function getConfig(layers: string[]) { skia: { transformGroup: 'skia', buildPath: 'tokens/skia/', + options: { + formatting: { + fileHeaderTimestamp: true + } + }, files: [ { destination: 'nala_color_id.h', @@ -137,6 +160,11 @@ export default function getConfig(layers: string[]) { ios: { transformGroup: 'ios', buildPath: 'tokens/ios-swift/', + options: { + formatting: { + fileHeaderTimestamp: true + } + }, files: [ { destination: 'Gradients.swift', @@ -158,6 +186,11 @@ export default function getConfig(layers: string[]) { android: { transformGroup: 'android', buildPath: 'tokens/android/', + options: { + formatting: { + fileHeaderTimestamp: true + } + }, files: [ { destination: 'values/styles.xml', diff --git a/src/tokens/transformTokens.ts b/src/tokens/transformTokens.ts index 4f4cd1b76..96f735680 100644 --- a/src/tokens/transformTokens.ts +++ b/src/tokens/transformTokens.ts @@ -12,10 +12,10 @@ import './transformation/android' StyleDictionary.registerTransform({ name: 'size/percent', type: 'value', - matcher: (token) => { + filter: (token) => { return token.unit === 'percent' && token.value !== 0 }, - transformer: (token) => { + transform: (token) => { return `${token.value}%` } }) @@ -25,10 +25,11 @@ StyleDictionary.registerTransform({ * all of the relevant tokens together in one. */ for (const platform of ['android', 'ios', 'skia']) { - const StyleDictionaryExtended = StyleDictionary.extend( + const StyleDictionaryExtended = new StyleDictionary( getConfig(['universal', platform, 'browser']) ) - StyleDictionaryExtended.buildPlatform(platform) + await StyleDictionaryExtended.hasInitialized + await StyleDictionaryExtended.buildPlatform(platform) } /** @@ -48,9 +49,11 @@ const layers = [ 'web3' ] for (const layer of layers) { - const StyleDictionaryExtended = StyleDictionary.extend(getConfig([layer])) + const StyleDictionaryExtended = new StyleDictionary(getConfig([layer])) - StyleDictionaryExtended.buildPlatform('css') - StyleDictionaryExtended.buildPlatform('json-flat') - StyleDictionaryExtended.buildPlatform('tailwind') + await StyleDictionaryExtended.hasInitialized + + await StyleDictionaryExtended.buildPlatform('css') + await StyleDictionaryExtended.buildPlatform('json-flat') + await StyleDictionaryExtended.buildPlatform('tailwind') } diff --git a/src/tokens/transformation/android/colorName.js b/src/tokens/transformation/android/colorName.ts similarity index 59% rename from src/tokens/transformation/android/colorName.js rename to src/tokens/transformation/android/colorName.ts index 75e9a2557..b791b8673 100644 --- a/src/tokens/transformation/android/colorName.js +++ b/src/tokens/transformation/android/colorName.ts @@ -1,9 +1,12 @@ +import type { Transform } from 'style-dictionary/types' + export default { + name: 'android/transformColorName', type: 'name', - matcher: function (token) { + filter: function (token) { return token.type === 'color' }, - transformer: function (token) { + transform: function (token) { return token.name .replace('color_', '') .replace('light_', '') @@ -11,4 +14,4 @@ export default { .replace('legacy_light_', '') .replace('legacy_dark_', '') } -} +} as Transform diff --git a/src/tokens/transformation/android/filters/darkColor.js b/src/tokens/transformation/android/filters/darkColor.js deleted file mode 100644 index 76f186378..000000000 --- a/src/tokens/transformation/android/filters/darkColor.js +++ /dev/null @@ -1,3 +0,0 @@ -import { matchDarkThemeToken } from '../../common/tokenFilters.js' - -export default (token) => matchDarkThemeToken(token) diff --git a/src/tokens/transformation/android/filters/darkColor.ts b/src/tokens/transformation/android/filters/darkColor.ts new file mode 100644 index 000000000..0dc5f567d --- /dev/null +++ b/src/tokens/transformation/android/filters/darkColor.ts @@ -0,0 +1,7 @@ +import type { Filter } from 'style-dictionary/types' +import { matchDarkThemeToken } from '../../common/tokenFilters' + +export default { + name: 'android/filterDarkColor', + filter: (token) => matchDarkThemeToken(token) +} as Filter diff --git a/src/tokens/transformation/android/filters/fontStyle.js b/src/tokens/transformation/android/filters/fontStyle.js deleted file mode 100644 index 775067abc..000000000 --- a/src/tokens/transformation/android/filters/fontStyle.js +++ /dev/null @@ -1 +0,0 @@ -export default (token) => token.attributes.category === 'font' diff --git a/src/tokens/transformation/android/filters/fontStyle.ts b/src/tokens/transformation/android/filters/fontStyle.ts new file mode 100644 index 000000000..a1712d37f --- /dev/null +++ b/src/tokens/transformation/android/filters/fontStyle.ts @@ -0,0 +1,6 @@ +import type { Filter } from 'style-dictionary/types' + +export default { + name: 'android/filterFontStyle', + filter: (token) => token.attributes.category === 'font' +} as Filter diff --git a/src/tokens/transformation/android/filters/lightColor.js b/src/tokens/transformation/android/filters/lightColor.js deleted file mode 100644 index bfd218184..000000000 --- a/src/tokens/transformation/android/filters/lightColor.js +++ /dev/null @@ -1,5 +0,0 @@ -import { matchLightThemeToken } from '../../common/tokenFilters' - -export default (token) => - // We are adding primitive colors in light colors as values/colors.xml would be the default color file and we don't have dark version of primitive colors. - matchLightThemeToken(token) || token.name.startsWith('primitive') diff --git a/src/tokens/transformation/android/filters/lightColor.ts b/src/tokens/transformation/android/filters/lightColor.ts new file mode 100644 index 000000000..7d569f764 --- /dev/null +++ b/src/tokens/transformation/android/filters/lightColor.ts @@ -0,0 +1,9 @@ +import type { Filter } from 'style-dictionary/types' +import { matchLightThemeToken } from '../../common/tokenFilters' + +export default { + name: 'android/filterLightColor', + filter: (token) => + // We are adding primitive colors in light colors as values/colors.xml would be the default color file and we don't have dark version of primitive colors. + matchLightThemeToken(token) || token.name.startsWith('primitive') +} as Filter diff --git a/src/tokens/transformation/android/fontSizeToSp.js b/src/tokens/transformation/android/fontSizeToSp.js deleted file mode 100644 index 4778674e9..000000000 --- a/src/tokens/transformation/android/fontSizeToSp.js +++ /dev/null @@ -1,9 +0,0 @@ -export default { - type: 'value', - matcher: function (token) { - return token.type === 'custom-fontStyle' - }, - transformer: function (token) { - return `${token.value.fontSize}sp` - } -} diff --git a/src/tokens/transformation/android/fontSizeToSp.ts b/src/tokens/transformation/android/fontSizeToSp.ts new file mode 100644 index 000000000..3fafb070a --- /dev/null +++ b/src/tokens/transformation/android/fontSizeToSp.ts @@ -0,0 +1,12 @@ +import type { Transform } from 'style-dictionary/types' + +export default { + name: 'android/transformFontSizeToSp', + type: 'value', + filter: function (token) { + return token.type === 'custom-fontStyle' + }, + transform: function (token) { + return `${token.value.fontSize}sp` + } +} as Transform diff --git a/src/tokens/transformation/android/formats/colorStyle.js b/src/tokens/transformation/android/formats/colorStyle.js deleted file mode 100644 index 8bb3a442c..000000000 --- a/src/tokens/transformation/android/formats/colorStyle.js +++ /dev/null @@ -1,21 +0,0 @@ -import StyleDictionary from 'style-dictionary' -import { TinyColor } from '@ctrl/tinycolor' -const { fileHeader } = StyleDictionary.formatHelpers - -export default ({ dictionary, platform, options = {}, file }) => { - const colorStyles = dictionary.allTokens - .filter((compositeToken) => compositeToken.type === 'color') - .map((compositeToken) => { - const colorCode = new TinyColor( - compositeToken.original.value - ).toHexString() - return `${colorCode}` - }) - return ` - -${fileHeader({ file, commentStyle: 'xml' })} - - ${colorStyles.join('\n')} - -` -} diff --git a/src/tokens/transformation/android/formats/colorStyle.ts b/src/tokens/transformation/android/formats/colorStyle.ts new file mode 100644 index 000000000..154502cd4 --- /dev/null +++ b/src/tokens/transformation/android/formats/colorStyle.ts @@ -0,0 +1,24 @@ +import { TinyColor } from '@ctrl/tinycolor' +import type { Format } from 'style-dictionary/types' +import { fileHeader } from 'style-dictionary/utils' + +export default { + name: 'android/formatColorStyle', + format: ({ dictionary, platform, options = {}, file }) => { + const colorStyles = dictionary.allTokens + .filter((compositeToken) => compositeToken.type === 'color') + .map((compositeToken) => { + const colorCode = new TinyColor( + compositeToken.original.value + ).toHexString() + return `${colorCode}` + }) + return ` + + ${fileHeader({ file, commentStyle: 'xml' })} + + ${colorStyles.join('\n')} + + ` + } +} as Format diff --git a/src/tokens/transformation/android/formats/dimenStyle.js b/src/tokens/transformation/android/formats/dimenStyle.js deleted file mode 100644 index decc5aebc..000000000 --- a/src/tokens/transformation/android/formats/dimenStyle.js +++ /dev/null @@ -1,18 +0,0 @@ -import StyleDictionary from 'style-dictionary' -const { fileHeader } = StyleDictionary.formatHelpers - -export default ({ dictionary, platform, options = {}, file }) => { - const fontStyles = dictionary.allTokens - .filter((compositeToken) => compositeToken.type === 'custom-fontStyle') - .map((compositeToken) => { - const dimenName = compositeToken.name.replace('font_android_', '') - return ` ${compositeToken.value}` - }) - return ` - -${fileHeader({ file, commentStyle: 'xml' })} - - ${fontStyles.join('\n')} - -` -} diff --git a/src/tokens/transformation/android/formats/dimenStyle.ts b/src/tokens/transformation/android/formats/dimenStyle.ts new file mode 100644 index 000000000..b8f579738 --- /dev/null +++ b/src/tokens/transformation/android/formats/dimenStyle.ts @@ -0,0 +1,21 @@ +import type { Format } from 'style-dictionary/types' +import { fileHeader } from 'style-dictionary/utils' + +export default { + name: 'android/formatDimenStyle', + format: ({ dictionary, platform, options = {}, file }) => { + const fontStyles = dictionary.allTokens + .filter((compositeToken) => compositeToken.type === 'custom-fontStyle') + .map((compositeToken) => { + const dimenName = compositeToken.name.replace('font_android_', '') + return ` ${compositeToken.value}` + }) + return ` + +${fileHeader({ file, commentStyle: 'xml' })} + + ${fontStyles.join('\n')} + +` + } +} as Format diff --git a/src/tokens/transformation/android/formats/fontStyle.js b/src/tokens/transformation/android/formats/fontStyle.js deleted file mode 100644 index 89b8fb5c2..000000000 --- a/src/tokens/transformation/android/formats/fontStyle.js +++ /dev/null @@ -1,48 +0,0 @@ -import StyleDictionary from 'style-dictionary' -import { pascalCase, snakeCase } from 'change-case' -const { fileHeader } = StyleDictionary.formatHelpers - -const letterSpacingToFloat = (letterSpacing, fontSize) => - 1 + letterSpacing / fontSize - -const printDescription = (description) => - description && description !== '' && description !== null - ? ` \n` - : '' - -export default ({ dictionary, platform, options = {}, file }) => { - const fontStyles = dictionary.allTokens - .filter((compositeToken) => compositeToken.type === 'custom-fontStyle') - // create style - .map((compositeToken) => { - return ( - ` \n' - ) - }) - return ` - -${fileHeader({ file, commentStyle: 'xml' })} - - ${fontStyles.join('\n')} - -` -} diff --git a/src/tokens/transformation/android/formats/fontStyle.ts b/src/tokens/transformation/android/formats/fontStyle.ts new file mode 100644 index 000000000..267f90d2b --- /dev/null +++ b/src/tokens/transformation/android/formats/fontStyle.ts @@ -0,0 +1,51 @@ +import { pascalCase, snakeCase } from 'change-case' +import type { Format } from 'style-dictionary/types' +import { fileHeader } from 'style-dictionary/utils' + +const letterSpacingToFloat = (letterSpacing, fontSize) => + 1 + letterSpacing / fontSize + +const printDescription = (description) => + description && description !== '' && description !== null + ? ` \n` + : '' + +export default { + name: 'android/formatFontStyle', + format: ({ dictionary, platform, options = {}, file }) => { + const fontStyles = dictionary.allTokens + .filter((compositeToken) => compositeToken.type === 'custom-fontStyle') + // create style + .map((compositeToken) => { + return ( + ` \n' + ) + }) + return ` + +${fileHeader({ file, commentStyle: 'xml' })} + + ${fontStyles.join('\n')} + +` + } +} as Format diff --git a/src/tokens/transformation/android/index.js b/src/tokens/transformation/android/index.js deleted file mode 100644 index d5042daf2..000000000 --- a/src/tokens/transformation/android/index.js +++ /dev/null @@ -1,61 +0,0 @@ -import StyleDictionary from 'style-dictionary' -import colorName from './colorName' -import fontSizeToSp from './fontSizeToSp' -import fontStyleFormatter from './formats/fontStyle' -import colorStyleFormatter from './formats/colorStyle' -import dimenStyleFormatter from './formats/dimenStyle' -import fontStyleFilter from './filters/fontStyle' -import darkColorFilter from './filters/darkColor' -import lightColorFilter from './filters/lightColor' - -// Transforms -StyleDictionary.registerTransform({ - name: 'android/transformColorName', - ...colorName -}) - -StyleDictionary.registerTransform({ - name: 'android/transformFontSizeToSp', - ...fontSizeToSp -}) - -// Formats -StyleDictionary.registerFormat({ - name: 'android/formatFontStyle', - formatter: fontStyleFormatter -}) - -StyleDictionary.registerFormat({ - name: 'android/formatColorStyle', - formatter: colorStyleFormatter -}) - -StyleDictionary.registerFormat({ - name: 'android/formatDimenStyle', - formatter: dimenStyleFormatter -}) - -// Filters -StyleDictionary.registerFilter({ - name: 'android/filterFontStyle', - matcher: fontStyleFilter -}) - -StyleDictionary.registerFilter({ - name: 'android/filterDarkColor', - matcher: darkColorFilter -}) - -StyleDictionary.registerFilter({ - name: 'android/filterLightColor', - matcher: lightColorFilter -}) - -// TransformGroup -StyleDictionary.registerTransformGroup({ - name: 'android', - transforms: StyleDictionary.transformGroup.android.concat([ - 'android/transformColorName', - 'android/transformFontSizeToSp' - ]) -}) diff --git a/src/tokens/transformation/android/index.ts b/src/tokens/transformation/android/index.ts new file mode 100644 index 000000000..e5e86f4bb --- /dev/null +++ b/src/tokens/transformation/android/index.ts @@ -0,0 +1,32 @@ +import StyleDictionary from 'style-dictionary' +import colorName from './colorName' +import fontSizeToSp from './fontSizeToSp' +import fontStyleFormatter from './formats/fontStyle' +import colorStyleFormatter from './formats/colorStyle' +import dimenStyleFormatter from './formats/dimenStyle' +import fontStyleFilter from './filters/fontStyle' +import darkColorFilter from './filters/darkColor' +import lightColorFilter from './filters/lightColor' + +// Transforms +StyleDictionary.registerTransform(colorName) +StyleDictionary.registerTransform(fontSizeToSp) + +// Formats +StyleDictionary.registerFormat(fontStyleFormatter) +StyleDictionary.registerFormat(colorStyleFormatter) +StyleDictionary.registerFormat(dimenStyleFormatter) + +// Filters +StyleDictionary.registerFilter(fontStyleFilter) +StyleDictionary.registerFilter(darkColorFilter) +StyleDictionary.registerFilter(lightColorFilter) + +// TransformGroup +StyleDictionary.registerTransformGroup({ + name: 'android', + transforms: StyleDictionary.hooks.transformGroups.android.concat([ + 'android/transformColorName', + 'android/transformFontSizeToSp' + ]) +}) diff --git a/src/tokens/transformation/common/camelCaseHelper.js b/src/tokens/transformation/common/camelCaseHelper.js deleted file mode 100644 index 2c1e2959d..000000000 --- a/src/tokens/transformation/common/camelCaseHelper.js +++ /dev/null @@ -1,3 +0,0 @@ -import { camelCase, camelCaseTransformMerge } from 'change-case' - -export default (name) => camelCase(name, { transform: camelCaseTransformMerge }) diff --git a/src/tokens/transformation/common/camelCaseHelper.ts b/src/tokens/transformation/common/camelCaseHelper.ts new file mode 100644 index 000000000..796829ccf --- /dev/null +++ b/src/tokens/transformation/common/camelCaseHelper.ts @@ -0,0 +1,3 @@ +import { camelCase } from 'change-case' + +export default (name) => camelCase(name) diff --git a/src/tokens/transformation/common/copyFileOrFolder.js b/src/tokens/transformation/common/copyFileOrFolder.ts similarity index 100% rename from src/tokens/transformation/common/copyFileOrFolder.js rename to src/tokens/transformation/common/copyFileOrFolder.ts diff --git a/src/tokens/transformation/common/flattenMaterialTheme.ts b/src/tokens/transformation/common/flattenMaterialTheme.ts index 72b632570..3bad634a5 100644 --- a/src/tokens/transformation/common/flattenMaterialTheme.ts +++ b/src/tokens/transformation/common/flattenMaterialTheme.ts @@ -1,4 +1,4 @@ -import { TransformedTokens } from 'style-dictionary' +import type { RawTokens } from './leoParser' const dynamicName = 'dynamic' const defaultsName = 'static' @@ -16,7 +16,7 @@ const defaultsName = 'static' * the primitive colors. * @param contents The contents of the tokens JSON */ -export default function (contents: TransformedTokens) { +export default function (contents: RawTokens) { const defaults = { ...contents[defaultsName] } delete contents[dynamicName] diff --git a/src/tokens/transformation/common/leoParser.ts b/src/tokens/transformation/common/leoParser.ts index d3fc83654..3c6b01c00 100644 --- a/src/tokens/transformation/common/leoParser.ts +++ b/src/tokens/transformation/common/leoParser.ts @@ -5,26 +5,36 @@ import { applyToTokens, removeKeyFromObject } from '../../utils' import universalVariables from '../../universal.variables.json' import { TinyColor } from '@ctrl/tinycolor' -import { DesignToken, DesignTokens, Parser } from 'style-dictionary' +import type { Parser } from 'style-dictionary/types' import flattenMaterialTheme from './flattenMaterialTheme' +export interface RawToken { + type: string + value: any + extensions?: any +} + +export interface RawTokens { + [key: string]: RawTokens | RawToken +} + /** * Transforms an effect to use variable references, rather than a hardcoded * color. Unfortunately we need to do this because style-dictionary won't * export variable references in effects. * At the moment, we just whitelist a few color groups. - * @param {*} layerVariables - * @returns {Array} */ -function getEffectColorsFromLayer(layerVariables: DesignTokens) { +function getEffectColorsFromLayer(layerVariables: RawTokens) { const allowedGroups = ['elevation', 'primary', 'secondary'] return allowedGroups .map((g) => ( - Object.entries(layerVariables.color?.light?.[g] || {}) as [ - string, - DesignToken - ][] + Object.entries( + (layerVariables?.color && + !('value' in layerVariables.color) && + layerVariables.color?.light?.[g]) || + {} + ) as [string, RawToken][] ).map(([key, value]) => [ `${g}.${key}`, new TinyColor(value.value).toHex8String() @@ -35,10 +45,10 @@ function getEffectColorsFromLayer(layerVariables: DesignTokens) { export default { pattern: /\.json$/, - parse: ({ filePath, contents: stringContents }) => { + parser: ({ filePath, contents: stringContents }) => { let layerVariables = {} try { - layerVariables = require(`${filePath.split('.')[0]}.variables.json`) + layerVariables = require(`${filePath?.split('.')[0]}.variables.json`) } catch {} // Replace emojies, e.g. '🌚 dark' :-) @@ -48,12 +58,16 @@ export default { '' ) .replaceAll(/-{2,}/g, '') - const contents = JSON.parse(stringContents) as DesignTokens + const contents = JSON.parse(stringContents) as RawTokens // Remove gradient|extended|gradient key repetition (do this before we remove 'extended' // since we would end up with the path gradient|gradient and `removeKeyFromObject` would // end up deleting everything under gradient). - if (contents.gradient?.gradient) + if ( + contents?.gradient && + !('value' in contents.gradient) && + contents.gradient?.gradient + ) contents.gradient = contents.gradient.gradient // Get variable references for effects, rather than hardcoded colors @@ -133,7 +147,7 @@ export default { } } - for (const [item, itemValue] of items as [string, DesignToken][]) { + for (const [item, itemValue] of items as [string, RawToken][]) { // Combine items where figma splits a single-value to multiple values // NOTE: ideal scenario here would be to programmatically determine if values should be grouped or not, instead of manually managing a list. if (['gradient'].includes(type) && itemValue && !itemValue.type) { @@ -153,7 +167,7 @@ export default { } } as Parser -function groupValues(tokenValue: DesignToken) { +function groupValues(tokenValue: RawToken) { // Make sure we filter out null items, or we won't set the type properly. const subitems = Object.values(tokenValue).filter((si) => si) tokenValue = { diff --git a/src/tokens/transformation/common/tokenFilters.js b/src/tokens/transformation/common/tokenFilters.ts similarity index 100% rename from src/tokens/transformation/common/tokenFilters.js rename to src/tokens/transformation/common/tokenFilters.ts diff --git a/src/tokens/transformation/ios/colorsets.js b/src/tokens/transformation/ios/colorsets.ts similarity index 88% rename from src/tokens/transformation/ios/colorsets.js rename to src/tokens/transformation/ios/colorsets.ts index 48e8b0f9b..232818bbe 100644 --- a/src/tokens/transformation/ios/colorsets.js +++ b/src/tokens/transformation/ios/colorsets.ts @@ -1,6 +1,7 @@ import { TinyColor } from '@ctrl/tinycolor' -import fs from 'fs-extra' import { snakeCase } from 'change-case' +import fs from 'fs-extra' +import type { Action } from 'style-dictionary/types' const contents = { info: { @@ -27,12 +28,30 @@ const ratioRgb = (color) => { } } +type Color = { + idiom: string + color: { + 'color-space': string + components: { + red: string + green: string + blue: string + alpha: string + } + } + appearances?: Array<{ + appearance: string + value: string + }> +} + /** * This action will iterate over all the colors in the Style Dictionary * and for each one write a colorset with light and (optional) dark * mode versions. */ export default { + name: 'ios/colorSets', // This is going to run once per theme. do: (dictionary, platform) => { const assetPath = `${platform.buildPath}/Colors.xcassets` @@ -65,7 +84,7 @@ export default { ? fs.readJsonSync(`${colorsetPath}/Contents.json`) : { ...contents, colors: [] } - const color = { + const color: Color = { idiom: 'universal', color: { 'color-space': 'srgb', @@ -93,4 +112,4 @@ export default { undo: function (dictionary, platform) { // no undo } -} +} as Action diff --git a/src/tokens/transformation/ios/fontStyleTemplate.js b/src/tokens/transformation/ios/fontStyleTemplate.js deleted file mode 100644 index 1a872e55c..000000000 --- a/src/tokens/transformation/ios/fontStyleTemplate.js +++ /dev/null @@ -1,33 +0,0 @@ -const dateNow = () => { - return new Date().toLocaleDateString('de-DE', { - year: 'numeric', - month: '2-digit', - day: '2-digit' - }) -} - -export default (style) => ` -// -// ${style.filename} -// -// Created by Design Token Generator on ${dateNow()}. -// - -import UIKit - -public class ${style.class} { - - enum Fonts { - ${style.font.join('\n ')} - } - - enum LineHeight { - ${style.lineheight.join('\n ')} - } - - enum Leading { - ${style.leading.join('\n ')} - } - -} -` diff --git a/src/tokens/transformation/ios/fontStyles.js b/src/tokens/transformation/ios/fontStyles.js deleted file mode 100644 index 11ca46436..000000000 --- a/src/tokens/transformation/ios/fontStyles.js +++ /dev/null @@ -1,69 +0,0 @@ -import fs from 'fs-extra' -import camelCase from '../common/camelCaseHelper' -import fontStyleTemplate from './fontStyleTemplate' - -const fontFile = ({ fontFamily, fontWeight }, fontOpts) => { - return fontOpts && fontOpts[`${fontFamily}.${fontWeight}`] - ? fontOpts[`${fontFamily}.${fontWeight}`] - : fontFamily -} - -/** - * This action will iterate over all the colors in the Style Dictionary - * and for each one write a colorset with light and (optional) dark - * mode versions. - */ -export default { - // This is going to run once per theme. - do: (dictionary, platform) => { - const assetPath = `${platform.buildPath}` - fs.ensureDirSync(assetPath) - - const fontStyles = { - filename: 'StyleDictionary+Generated.swift', - class: 'StyleDictionary', - font: [], - lineheight: [], - leading: [] - } - // cycle through all tokens - dictionary.allTokens - // filter out custom styles - .filter((token) => token.type === 'custom-fontStyle') - // remove all underline styles (they can not be used like this in iOS) - .filter((token) => token.original.value.textDecoration !== 'underline') - // split int 2 parts: font & fontSize, lineheight, leading - .forEach(({ original: { value }, path }) => { - // chaning name & removeing "font" from name for better DX - const name = camelCase(path.slice(1).join(' ')) - // lineheight - fontStyles.lineheight.push( - `public static let ${name} = ${( - value.lineHeight / value.fontSize - ).toFixed(2)}` - ) - // leading - fontStyles.leading.push( - `public static let ${name} = ${( - 1 + - value.letterSpacing / value.fontSize - ).toFixed(2)}` - ) - // font style - fontStyles.font.push( - `public static let ${name} = UIFontMetrics.default.scaledFont(for: UIFont(name: "${fontFile( - value, - platform.options.fontFamilies - )}", size: ${value.fontSize})!)` - ) - }) - // write .swift file with definitions for defaults - fs.writeFileSync( - `${assetPath}/${fontStyles.filename}`, - fontStyleTemplate(fontStyles) - ) - }, - undo: function (dictionary, platform) { - // no undo - } -} diff --git a/src/tokens/transformation/ios/index.js b/src/tokens/transformation/ios/index.ts similarity index 67% rename from src/tokens/transformation/ios/index.js rename to src/tokens/transformation/ios/index.ts index df765a219..3ddef0640 100644 --- a/src/tokens/transformation/ios/index.js +++ b/src/tokens/transformation/ios/index.ts @@ -1,22 +1,12 @@ -import StyleDictionary from 'style-dictionary' -import _template from 'lodash/template' +import { camelCase, snakeCase } from 'change-case' import fs from 'fs' -import changeCase from 'change-case' -import colorsets from './colorsets.js' -import fontStyles from './fontStyles.js' - -export default { - transform: {}, - format: {}, - action: { - 'ios/colorSets': colorsets, - 'ios/fontStyles': fontStyles - } -} +import _template from 'lodash/template' +import StyleDictionary from 'style-dictionary' +import colorsets from './colorsets' StyleDictionary.registerFormat({ name: 'ios/gradients', - formatter: ({ dictionary, options, file }) => { + format: ({ dictionary, options, file }) => { const template = _template( fs.readFileSync( new URL('./templates/Gradients.swift.template', import.meta.url) @@ -31,7 +21,7 @@ StyleDictionary.registerFormat({ token.value.gradientType === 'linear' ) .map((token) => { - token.name = changeCase.camelCase(token.path.pop()) + token.name = camelCase(token.path.pop() || '') return token }) } @@ -42,7 +32,7 @@ StyleDictionary.registerFormat({ StyleDictionary.registerFormat({ name: 'ios/colorSetAccessors', - formatter: ({ dictionary, options, file }) => { + format: ({ dictionary, options, file }) => { const template = _template( fs.readFileSync( new URL('./templates/ColorSetAccessors.swift.template', import.meta.url) @@ -57,21 +47,17 @@ StyleDictionary.registerFormat({ // The system already provides these and will conflict with the names return } - const name = changeCase.snakeCase( + const name = snakeCase( token.path .filter( (path) => path !== 'dark' && path !== 'light' && path !== 'color' ) .join(' ') ) - colors[name] = changeCase.camelCase(name).replace('_', '') // Xcode 15 accessors generate without underscores + colors[name] = camelCase(name).replace('_', '') // Xcode 15 accessors generate without underscores }) return template({ colors, options, file }) } }) -StyleDictionary.registerAction({ - name: 'ios/colorSets', - do: colorsets.do, - undo: colorsets.undo -}) +StyleDictionary.registerAction(colorsets) diff --git a/src/tokens/transformation/skia/colorToSkiaString.ts b/src/tokens/transformation/skia/colorToSkiaString.ts index 0a9b9af0a..47ba87f75 100644 --- a/src/tokens/transformation/skia/colorToSkiaString.ts +++ b/src/tokens/transformation/skia/colorToSkiaString.ts @@ -1,12 +1,13 @@ import { TinyColor } from '@ctrl/tinycolor' -import { Transform } from 'style-dictionary' -import { transformName } from './name' +import type { Transform } from 'style-dictionary/types' import referenceToName from '../common/referenceToName' +import { transformName } from './name' export default { + name: 'color/hex8ToSkiaString', type: 'value', - matcher: ({ type }) => type === 'color', - transformer: ({ value, referencedVariable }) => { + filter: ({ type }) => type === 'color', + transform: ({ value, referencedVariable }) => { if (referencedVariable) { return transformName({ name: referenceToName(referencedVariable) @@ -15,7 +16,7 @@ export default { const { r, g, b, a } = new TinyColor(value).toRgb() const parts = [a !== 1 && Math.round(a * 255), r, g, b] - .filter((c) => c !== false) + .filter((c: number | boolean) => c !== false) .map((c) => '0x' + Number(c).toString(16).padStart(2, '0').toUpperCase()) const func = parts.length === 3 ? 'SkColorSetRGB' : 'SkColorSetARGB' diff --git a/src/tokens/transformation/skia/index.ts b/src/tokens/transformation/skia/index.ts index 2ac6c5a14..6b5d90ced 100644 --- a/src/tokens/transformation/skia/index.ts +++ b/src/tokens/transformation/skia/index.ts @@ -1,7 +1,8 @@ import fs from 'fs' import _template from 'lodash/template' import path from 'path' -import StyleDictionary, { Dictionary, TransformedToken } from 'style-dictionary' +import StyleDictionary from 'style-dictionary' +import type { Dictionary, TransformedToken } from 'style-dictionary/types' import { fileURLToPath } from 'url' import colorToSkiaString from './colorToSkiaString' import { transformName } from './name' @@ -9,14 +10,11 @@ import { transformName } from './name' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) -StyleDictionary.registerTransform({ - name: 'color/hex8ToSkiaString', - ...colorToSkiaString -}) +StyleDictionary.registerTransform(colorToSkiaString) StyleDictionary.registerTransformGroup({ name: 'skia', - transforms: StyleDictionary.transformGroup.css.concat([ + transforms: StyleDictionary.hooks.transformGroups.css.concat([ 'color/hex8ToSkiaString' ]) }) @@ -131,7 +129,7 @@ const templates = [ for (const templateName of templates) { StyleDictionary.registerFormat({ name: `skia/${templateName}`, - formatter: ({ dictionary, options, file }) => { + format: ({ dictionary, options, file }) => { const template = _template( fs.readFileSync( dirname + `/templates/${templateName}.template`, @@ -162,7 +160,7 @@ for (const templateName of templates) { StyleDictionary.registerFormat({ name: 'skia/spacing.h', - formatter: ({ dictionary, options, file }) => { + format: ({ dictionary, options, file }) => { const template = _template( fs.readFileSync(dirname + '/templates/spacing.h.template', 'utf-8') ) @@ -178,7 +176,7 @@ StyleDictionary.registerFormat({ StyleDictionary.registerFormat({ name: 'skia/radius.h', - formatter: ({ dictionary, options, file }) => { + format: ({ dictionary, options, file }) => { const template = _template( fs.readFileSync(dirname + '/templates/radius.h.template', 'utf-8') ) diff --git a/src/tokens/transformation/tailwind/colorToRgbPartial.ts b/src/tokens/transformation/tailwind/colorToRgbPartial.ts index 849b06c5a..ccd501a4e 100644 --- a/src/tokens/transformation/tailwind/colorToRgbPartial.ts +++ b/src/tokens/transformation/tailwind/colorToRgbPartial.ts @@ -1,12 +1,13 @@ import { TinyColor } from '@ctrl/tinycolor' -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' export default { + name: 'color/hex8ToRgbPartial', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'color' }, - transformer: function ({ value, ...token }) { + transform: function ({ value, ...token }) { const fullColorValue = ['elevation'] if (token.name.match(new RegExp(`(${fullColorValue.join('|')})`))) { return new TinyColor(value).toRgbString() diff --git a/src/tokens/transformation/tailwind/convertCssToJs.js b/src/tokens/transformation/tailwind/convertCssToJs.ts similarity index 77% rename from src/tokens/transformation/tailwind/convertCssToJs.js rename to src/tokens/transformation/tailwind/convertCssToJs.ts index c18751f3a..c7a130170 100644 --- a/src/tokens/transformation/tailwind/convertCssToJs.js +++ b/src/tokens/transformation/tailwind/convertCssToJs.ts @@ -1,7 +1,8 @@ +import { readFileSync, unlinkSync, writeFileSync } from 'fs' import { join } from 'path' -import { unlink, readFileSync, writeFileSync } from 'fs' -import postcssJs from 'postcss-js' import postcss from 'postcss' +import postcssJs from 'postcss-js' +import type { Action } from 'style-dictionary/types' const cssFiles = ['variables.css'] @@ -9,6 +10,7 @@ const genPluginFilePath = (file, config) => join(config.buildPath, config.preset, 'plugins', `_${file}.ts`) export default { + name: 'tailwind/convert_css_to_js', do: function (dictionary, config) { cssFiles.forEach((file) => { const css = readFileSync( @@ -26,7 +28,7 @@ export default { }, undo: function (dictionary, config) { cssFiles.forEach((file) => { - unlink(genPluginFilePath(file, config)) + unlinkSync(genPluginFilePath(file, config)) }) } -} +} as Action diff --git a/src/tokens/transformation/tailwind/copyStaticFiles.js b/src/tokens/transformation/tailwind/copyStaticFiles.ts similarity index 74% rename from src/tokens/transformation/tailwind/copyStaticFiles.js rename to src/tokens/transformation/tailwind/copyStaticFiles.ts index ce770604e..b20356afc 100644 --- a/src/tokens/transformation/tailwind/copyStaticFiles.js +++ b/src/tokens/transformation/tailwind/copyStaticFiles.ts @@ -1,5 +1,6 @@ -import { cpSync, readdirSync, rmdir, statSync, unlink } from 'fs' +import { cpSync, readdirSync, rmdirSync, statSync, unlinkSync } from 'fs' import path from 'path' +import type { Action } from 'style-dictionary/types' import { fileURLToPath } from 'url' const filename = fileURLToPath(import.meta.url) @@ -9,6 +10,7 @@ const staticFilesPath = path.join(dirname, './static') const staticFiles = readdirSync(staticFilesPath) export default { + name: 'tailwind/copy_static_files', do: function (dictionary, config) { const targetDir = path.join(config.buildPath, config.preset) cpSync(staticFilesPath, targetDir, { recursive: true }) @@ -18,10 +20,10 @@ export default { const target = path.join(config.buildPath, config.preset, file) if (statSync(target).isDirectory()) { - rmdir(target) + rmdirSync(target) } else { - unlink(target) + unlinkSync(target) } }) } -} +} as Action diff --git a/src/tokens/transformation/tailwind/extractComponentStyles.js b/src/tokens/transformation/tailwind/extractComponentStyles.ts similarity index 95% rename from src/tokens/transformation/tailwind/extractComponentStyles.js rename to src/tokens/transformation/tailwind/extractComponentStyles.ts index 70c752968..863494f79 100644 --- a/src/tokens/transformation/tailwind/extractComponentStyles.js +++ b/src/tokens/transformation/tailwind/extractComponentStyles.ts @@ -3,6 +3,7 @@ import path from 'path' import postcss from 'postcss' import postcssJs from 'postcss-js' import sortMediaQueries from 'postcss-sort-media-queries' +import type { Action } from 'style-dictionary/types' import preprocess from 'svelte-preprocess' import * as svelte from 'svelte/compiler' import { fileURLToPath } from 'url' @@ -24,7 +25,7 @@ module.exports = plugin(function ({ ${fnName}, theme }) { ${fnName}(${JSON.stringify(contents, null, 2)}); });` ) - } catch (e) { + } catch (e: any) { if (e.code === 'ENOENT') { await mkdir(dir, { recursive: true }) await writePlugin(contents, name, dir) @@ -35,6 +36,7 @@ ${fnName}(${JSON.stringify(contents, null, 2)}); } export default { + name: 'tailwind/extract_component_styles', do: async function (dictionary, config) { for await (const file of await walk( path.join(dirname, '../../../components') @@ -88,4 +90,4 @@ export default { } }, undo: function () {} -} +} as Action diff --git a/src/tokens/transformation/tailwind/formatCssVars.ts b/src/tokens/transformation/tailwind/formatCssVars.ts index 368547c4d..0b449fb6d 100644 --- a/src/tokens/transformation/tailwind/formatCssVars.ts +++ b/src/tokens/transformation/tailwind/formatCssVars.ts @@ -1,64 +1,66 @@ -import formattedVariables from '../web/formattedVariables' -import fileHeader from '../web/fileHeader' - +import type { Format } from 'style-dictionary/types' +import { fileHeader } from 'style-dictionary/utils' +import { varDefFormat } from '../../utils' import { filteredTokens, matchDarkThemeToken, matchLightThemeToken } from '../common/tokenFilters' -import { varDefFormat } from '../../utils' -import { Formatter } from 'style-dictionary' +import formattedVariables from '../web/formattedVariables' -export default (({ dictionary, options, file }) => { - const opts = options ?? {} - const { outputReferences } = opts - const groupedTokens = { - light: filteredTokens(dictionary, (token) => matchLightThemeToken(token)), - dark: filteredTokens(dictionary, (token) => matchDarkThemeToken(token)), - rest: filteredTokens( - dictionary, - (token) => - ['color', 'custom-shadow'].includes(token.type) && - !matchDarkThemeToken(token) && - !matchLightThemeToken(token) - ) - } +export default { + name: 'tailwind/css', + format: async ({ dictionary, options, file }) => { + // Note that we're assuming a boolean, and forcing the value to be a boolean rather than a function + const outputReferences = !!options.outputReferences + const groupedTokens = { + light: filteredTokens(dictionary, (token) => matchLightThemeToken(token)), + dark: filteredTokens(dictionary, (token) => matchDarkThemeToken(token)), + rest: filteredTokens( + dictionary, + (token) => + ['color', 'custom-shadow'].includes(token.type) && + !matchDarkThemeToken(token) && + !matchLightThemeToken(token) + ) + } - const defaultVars = formattedVariables({ - format: 'tailwind', - dictionary: groupedTokens.rest, - outputReferences: !!outputReferences, - formatting: 'tailwind' - }) + const defaultVars = formattedVariables({ + format: 'tailwind', + dictionary: groupedTokens.rest, + outputReferences: !!outputReferences, + formatting: 'tailwind' + }) - const lightVars = formattedVariables({ - format: 'tailwind', - dictionary: groupedTokens.light, - outputReferences - }).replace(/-light-/gm, '-') + const lightVars = formattedVariables({ + format: 'tailwind', + dictionary: groupedTokens.light, + outputReferences + }).replace(/-light-/gm, '-') - const darkVars = formattedVariables({ - format: 'tailwind', - dictionary: groupedTokens.dark, - outputReferences - }).replace(/-dark-/gm, '-') + const darkVars = formattedVariables({ + format: 'tailwind', + dictionary: groupedTokens.dark, + outputReferences + }).replace(/-dark-/gm, '-') - // prettier-ignore - return ( - fileHeader({ file }) + - [ - defaultVars && varDefFormat`:root {${defaultVars}}`, - lightVars && varDefFormat`@media (prefers-color-scheme: light) { + // prettier-ignore + return ( + await fileHeader({ file, ...options }) + + [ + defaultVars && varDefFormat`:root {${defaultVars}}`, + lightVars && varDefFormat`@media (prefers-color-scheme: light) { :root {${lightVars} } }`, - darkVars && varDefFormat`@media (prefers-color-scheme: dark) { + darkVars && varDefFormat`@media (prefers-color-scheme: dark) { :root {${darkVars} } }`, - lightVars && varDefFormat`[data-theme="light"] {${lightVars}}`, - lightVars && varDefFormat`[data-theme="dark"] {${darkVars}}`, - ] - .filter((v) => !!v) - .join('\n\n') + - '\n' - ) -}) as Formatter + lightVars && varDefFormat`[data-theme="light"] {${lightVars}}`, + lightVars && varDefFormat`[data-theme="dark"] {${darkVars}}`, + ] + .filter((v) => !!v) + .join('\n\n') + + '\n' + ) + } +} as Format diff --git a/src/tokens/transformation/tailwind/formatFonts.ts b/src/tokens/transformation/tailwind/formatFonts.ts index 5c3d9b1ff..aba526f01 100644 --- a/src/tokens/transformation/tailwind/formatFonts.ts +++ b/src/tokens/transformation/tailwind/formatFonts.ts @@ -1,27 +1,29 @@ -import { Formatter } from 'style-dictionary' +import type { Format } from 'style-dictionary/types' -export default (({ dictionary }) => { - const fontClasses = new Map() +export default { + name: 'tailwind/fonts', + format: ({ dictionary }) => { + const fontClasses = new Map() - // Format all other tokens - dictionary.allTokens.forEach(({ type, name, ...t }) => { - const attributes = t.attributes! - let fontClass = `.text-${attributes.type}-${attributes.item}` + // Format all other tokens + dictionary.allTokens.forEach(({ type, name, ...t }) => { + const attributes = t.attributes! + let fontClass = `.text-${attributes.type}-${attributes.item}` - if (attributes.subitem) { - fontClass += `-${attributes.subitem}` - } + if (attributes.subitem) { + fontClass += `-${attributes.subitem}` + } - // Ensure we don't lose modifiers like "default", "regular", "semibold", etc. - if (attributes.state) { - fontClass += `-${attributes.state}` - } + // Ensure we don't lose modifiers like "default", "regular", "semibold", etc. + if (attributes.state) { + fontClass += `-${attributes.state}` + } - fontClasses.set(fontClass, t.value) - }) + fontClasses.set(fontClass, t.value) + }) - // Note: replace strips out 'light-mode' and 'dark-mode' inside media queries - return `const plugin = require("tailwindcss/plugin") + // Note: replace strips out 'light-mode' and 'dark-mode' inside media queries + return `const plugin = require("tailwindcss/plugin") const defaultTheme = require('tailwindcss/defaultTheme') module.exports = plugin(function ({ addComponents }) { addComponents(${JSON.stringify(Object.fromEntries(fontClasses))}); @@ -33,4 +35,5 @@ module.exports = plugin(function ({ addComponents }) { }, } })` -}) as Formatter + } +} as Format diff --git a/src/tokens/transformation/tailwind/formatTokens.ts b/src/tokens/transformation/tailwind/formatTokens.ts index dcf081248..624a673a5 100644 --- a/src/tokens/transformation/tailwind/formatTokens.ts +++ b/src/tokens/transformation/tailwind/formatTokens.ts @@ -1,5 +1,5 @@ import merge from 'lodash.merge' -import { Formatter } from 'style-dictionary' +import type { Format } from 'style-dictionary/types' const themes = ['light', 'dark'] @@ -125,57 +125,60 @@ function createDynamicColorTokens(tokens) { return createColorTokensFromGroup(tokens, false) } -export default (({ dictionary }) => { - const colorTokens = createDynamicColorTokens(dictionary.allTokens) - - const borderRadii = new Map([['none', '0']]) - const spacing = new Map([[0, 0]]) // Initialize with option for 0 spacing - const gradients = new Map() - const boxShadows = new Map([['none', 'none']]) - const dropShadows = new Map([ - ['none', '0 0 #0000'] - ]) - - // Format all other tokens - dictionary.allTokens.forEach(({ type, name, ...t }) => { - const attributes = t.attributes! - if (attributes.category === 'radius') { - if (attributes.type === 'full') { - borderRadii.set(attributes.type, '9999px') - } else { - borderRadii.set(attributes.type!, t.value) +export default { + name: 'tailwind/tokens', + format: ({ dictionary }) => { + const colorTokens = createDynamicColorTokens(dictionary.allTokens) + + const borderRadii = new Map([['none', '0']]) + const spacing = new Map([[0, 0]]) // Initialize with option for 0 spacing + const gradients = new Map() + const boxShadows = new Map([['none', 'none']]) + const dropShadows = new Map([ + ['none', '0 0 #0000'] + ]) + + // Format all other tokens + dictionary.allTokens.forEach(({ type, name, ...t }) => { + const attributes = t.attributes! + if (attributes.category === 'radius') { + if (attributes.type === 'full') { + borderRadii.set(attributes.type, '9999px') + } else { + borderRadii.set(attributes.type as string, t.value) + } + } else if (attributes.category === 'spacing') { + spacing.set(attributes.type as string, t.value) + } else if (type === 'custom-gradient') { + const [, ...pathParts] = t.path + gradients.set(pathParts.join('-'), t.value) + } else if (type === 'custom-shadow') { + const [, ...pathParts] = t.path + const shadowName = kebabCase( + pathParts + .filter((v) => !['elevation', 'light', 'dark'].includes(v)) + .join('-') + ) + boxShadows.set(shadowName, formatBoxShadowVar(name, false)) + dropShadows.set( + shadowName, + formatDropShadowVars(name, t.value.dropShadow?.length ?? 0, true) + ) } - } else if (attributes.category === 'spacing') { - spacing.set(attributes.type!, t.value) - } else if (type === 'custom-gradient') { - const [, ...pathParts] = t.path - gradients.set(pathParts.join('-'), t.value) - } else if (type === 'custom-shadow') { - const [, ...pathParts] = t.path - const shadowName = kebabCase( - pathParts - .filter((v) => !['elevation', 'light', 'dark'].includes(v)) - .join('-') - ) - boxShadows.set(shadowName, formatBoxShadowVar(name, false)) - dropShadows.set( - shadowName, - formatDropShadowVars(name, t.value.dropShadow?.length ?? 0, true) - ) - } - }) - - // Note: replace strips out 'light-mode' and 'dark-mode' inside media queries - return `module.exports = ${JSON.stringify( - { - colors: colorTokens, - spacing: Object.fromEntries(spacing), - borderRadius: Object.fromEntries(borderRadii), - boxShadow: Object.fromEntries(boxShadows), - dropShadow: Object.fromEntries(dropShadows), - gradients: Object.fromEntries(gradients) - }, - null, - ' '.repeat(2) - )}` -}) as Formatter + }) + + // Note: replace strips out 'light-mode' and 'dark-mode' inside media queries + return `module.exports = ${JSON.stringify( + { + colors: colorTokens, + spacing: Object.fromEntries(spacing), + borderRadius: Object.fromEntries(borderRadii), + boxShadow: Object.fromEntries(boxShadows), + dropShadow: Object.fromEntries(dropShadows), + gradients: Object.fromEntries(gradients) + }, + null, + ' '.repeat(2) + )}` + } +} as Format diff --git a/src/tokens/transformation/tailwind/index.ts b/src/tokens/transformation/tailwind/index.ts index d0237c83f..e8b5badae 100644 --- a/src/tokens/transformation/tailwind/index.ts +++ b/src/tokens/transformation/tailwind/index.ts @@ -20,53 +20,22 @@ import convertCssToJs from './convertCssToJs' import extractComponentStyles from './extractComponentStyles' // Filters -StyleDictionary.registerFilter({ - name: 'tw/filterTokens', - matcher: twFilterTokens -}) - -StyleDictionary.registerFilter({ - name: 'tw/filterFonts', - matcher: twFilterFonts -}) +StyleDictionary.registerFilter(twFilterTokens) +StyleDictionary.registerFilter(twFilterFonts) // Transforms -StyleDictionary.registerTransform({ - name: 'size/px', - ...sizePx -}) -StyleDictionary.registerTransform({ - name: 'tw/shadow', - ...twShadows -}) -StyleDictionary.registerTransform({ - name: 'web/radius', - ...webRadius -}) -StyleDictionary.registerTransform({ - name: 'web/size', - ...webSize -}) -StyleDictionary.registerTransform({ - name: 'web/padding', - ...webPadding -}) -StyleDictionary.registerTransform({ - name: 'tw/font', - ...twFont -}) -StyleDictionary.registerTransform({ - name: 'web/gradient', - ...webGradient -}) -StyleDictionary.registerTransform({ - name: 'color/hex8ToRgbPartial', - ...colorToRgbPartial -}) +StyleDictionary.registerTransform(sizePx) +StyleDictionary.registerTransform(twShadows) +StyleDictionary.registerTransform(webRadius) +StyleDictionary.registerTransform(webSize) +StyleDictionary.registerTransform(webPadding) +StyleDictionary.registerTransform(twFont) +StyleDictionary.registerTransform(webGradient) +StyleDictionary.registerTransform(colorToRgbPartial) StyleDictionary.registerTransformGroup({ name: 'tailwind/css', - transforms: StyleDictionary.transformGroup.css.concat([ + transforms: StyleDictionary.hooks.transformGroups.css.concat([ 'size/px', 'tw/shadow', 'web/radius', @@ -79,36 +48,11 @@ StyleDictionary.registerTransformGroup({ }) // Formats -StyleDictionary.registerFormat({ - name: 'tailwind/css', - formatter: formatCssVars -}) - -StyleDictionary.registerFormat({ - name: 'tailwind/tokens', - formatter: formatTokens -}) - -StyleDictionary.registerFormat({ - name: 'tailwind/fonts', - formatter: formatFonts -}) +StyleDictionary.registerFormat(formatCssVars) +StyleDictionary.registerFormat(formatTokens) +StyleDictionary.registerFormat(formatFonts) // Actions -StyleDictionary.registerAction({ - name: 'tailwind/copy_static_files', - do: copyStaticFiles.do, - undo: copyStaticFiles.undo -}) - -StyleDictionary.registerAction({ - name: 'tailwind/convert_css_to_js', - do: convertCssToJs.do, - undo: convertCssToJs.undo -}) - -StyleDictionary.registerAction({ - name: 'tailwind/extract_component_styles', - do: extractComponentStyles.do, - undo: extractComponentStyles.undo -}) +StyleDictionary.registerAction(copyStaticFiles) +StyleDictionary.registerAction(convertCssToJs) +StyleDictionary.registerAction(extractComponentStyles) diff --git a/src/tokens/transformation/tailwind/twFilterFonts.ts b/src/tokens/transformation/tailwind/twFilterFonts.ts index d3d151fa8..5f54899fd 100644 --- a/src/tokens/transformation/tailwind/twFilterFonts.ts +++ b/src/tokens/transformation/tailwind/twFilterFonts.ts @@ -1,5 +1,8 @@ -import { TransformedToken } from 'style-dictionary' +import type { Filter, TransformedToken } from 'style-dictionary/types' const acceptedTypes = ['font', 'custom-fontStyle'] -export default (token: TransformedToken) => acceptedTypes.includes(token.type) +export default { + name: 'tw/filterFonts', + filter: (token: TransformedToken) => acceptedTypes.includes(token.type) +} as Filter diff --git a/src/tokens/transformation/tailwind/twFilterTokens.ts b/src/tokens/transformation/tailwind/twFilterTokens.ts index 1f23b8b6a..5dbf4c18e 100644 --- a/src/tokens/transformation/tailwind/twFilterTokens.ts +++ b/src/tokens/transformation/tailwind/twFilterTokens.ts @@ -1,4 +1,4 @@ -import { TransformedToken } from 'style-dictionary' +import type { Filter, TransformedToken } from 'style-dictionary/types' const acceptedTypes = [ 'color', @@ -10,4 +10,7 @@ const acceptedTypes = [ 'number' ] -export default (token: TransformedToken) => acceptedTypes.includes(token.type) +export default { + name: 'tw/filterTokens', + filter: (token: TransformedToken) => acceptedTypes.includes(token.type) +} as Filter diff --git a/src/tokens/transformation/tailwind/twFont.ts b/src/tokens/transformation/tailwind/twFont.ts index 45165fe53..195f17c1b 100644 --- a/src/tokens/transformation/tailwind/twFont.ts +++ b/src/tokens/transformation/tailwind/twFont.ts @@ -1,11 +1,12 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' export default { + name: 'tw/font', type: 'value', - matcher(token) { + filter(token) { return token.type === 'custom-fontStyle' }, - transformer({ value: font }) { + transform({ value: font }) { return { fontSize: `${font.fontSize}px`, lineHeight: `${font.lineHeight}px`, diff --git a/src/tokens/transformation/tailwind/twShadows.ts b/src/tokens/transformation/tailwind/twShadows.ts index 07b64dbfb..f6e9d332a 100644 --- a/src/tokens/transformation/tailwind/twShadows.ts +++ b/src/tokens/transformation/tailwind/twShadows.ts @@ -1,12 +1,13 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' import { formatColor } from '../web/webColorRef' export default { + name: 'tw/shadow', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'custom-shadow' && token.value !== 0 }, - transformer: function ({ value }) { + transform: function ({ value }) { value = Array.isArray(value) ? value : [value] return { boxShadow: value.map((v) => formatBoxShadow(v)).join(', '), diff --git a/src/tokens/transformation/web/color.ts b/src/tokens/transformation/web/color.ts index 35b665475..7fe1d4d1a 100644 --- a/src/tokens/transformation/web/color.ts +++ b/src/tokens/transformation/web/color.ts @@ -1,13 +1,13 @@ +import type { Transform } from 'style-dictionary/types' import { TinyColor } from '@ctrl/tinycolor' import referenceToName from '../common/referenceToName' -import { Transform } from 'style-dictionary' - export default { + name: 'web/color', type: 'value', - matcher(token) { + filter(token) { return token.type === 'color' }, - transformer({ value, referencedVariable }) { + transform({ value, referencedVariable }) { if (referencedVariable) { return `var(--leo-${referenceToName(referencedVariable)})` } diff --git a/src/tokens/transformation/web/createPropertyFormatter.js b/src/tokens/transformation/web/createPropertyFormatter.ts similarity index 95% rename from src/tokens/transformation/web/createPropertyFormatter.js rename to src/tokens/transformation/web/createPropertyFormatter.ts index cda6406a7..a2b0311dd 100644 --- a/src/tokens/transformation/web/createPropertyFormatter.js +++ b/src/tokens/transformation/web/createPropertyFormatter.ts @@ -1,3 +1,4 @@ +import { usesReferences, getReferences } from 'style-dictionary/utils' /* * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * @@ -133,11 +134,14 @@ export default function createPropertyFormatter({ * This will see if there are references and if there are, replace * the resolved value with the reference's name. */ - if (outputReferences && dictionary.usesReference(prop.original.value)) { + if ( + outputReferences && + usesReferences(prop.original.value, dictionary.tokens) + ) { // Formats that use this function expect `value` to be a string // or else you will get '[object Object]' in the output if (typeof value === 'string') { - const refs = dictionary.getReferences(prop.original.value) + const refs = getReferences(prop.original.value, dictionary.tokens) refs.forEach((ref) => { // value should be a string that contains the resolved reference // because Style Dictionary resolved this in the resolution step. diff --git a/src/tokens/transformation/web/fileHeader.js b/src/tokens/transformation/web/fileHeader.js deleted file mode 100644 index 91ea0ebc6..000000000 --- a/src/tokens/transformation/web/fileHeader.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with - * the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -// no-op default -const defaultFileHeader = (arr) => arr - -const lineSeparator = '\n' -const defaultFormatting = { - lineSeparator, - prefix: ' * ', - header: `/**${lineSeparator}`, - footer: `${lineSeparator} */${lineSeparator}${lineSeparator}` -} - -/** - * - * This is for creating the comment at the top of generated files with the generated at date. - * It will use the custom file header if defined on the configuration, or use the - * default file header. - * @memberof module:formatHelpers - * @param {Object?} options - * @param {import('style-dictionary').File} options.file - The file object that is passed to the formatter. - * @param {String} options.commentStyle - The only options are 'short' and 'xml', which will use the // or \ style comments respectively. Anything else will use \/\* style comments. - * @param {Object} options.formatting - Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer. - * @returns {String} - * @example - * ```js - * StyleDictionary.registerFormat({ - * name: 'myCustomFormat', - * formatter: function({ dictionary, file }) { - * return fileHeader({file, 'short') + - * dictionary.allTokens.map(token => `${token.name} = ${token.value}`) - * .join('\n'); - * } - * }); - * ``` - */ -export default function fileHeader({ - file = {}, - commentStyle, - formatting = {} -}) { - // showFileHeader is true by default - let showFileHeader = true - if (file.options && typeof file.options.showFileHeader !== 'undefined') { - showFileHeader = file.options.showFileHeader - } - - // Return empty string if the showFileHeader is false - if (!showFileHeader) return '' - - let fn = defaultFileHeader - if (file.options && typeof file.options.fileHeader === 'function') { - fn = file.options.fileHeader - } - - // default header - const defaultHeader = [ - 'Do not edit directly', - `Generated on ${new Date().toString()}` - ] - - let { prefix, lineSeparator, header, footer } = Object.assign( - {}, - defaultFormatting, - formatting - ) - - if (commentStyle === 'short') { - prefix = '// ' - header = `${lineSeparator}` - footer = `${lineSeparator}${lineSeparator}` - } else if (commentStyle === 'xml') { - prefix = ' ' - header = `` - } - - return `${header}${fn(defaultHeader) - .map((line) => `${prefix}${line}`) - .join(lineSeparator)}${footer}` -} diff --git a/src/tokens/transformation/web/filterWeb.js b/src/tokens/transformation/web/filterWeb.ts similarity index 52% rename from src/tokens/transformation/web/filterWeb.js rename to src/tokens/transformation/web/filterWeb.ts index 7305be508..a93c5f154 100644 --- a/src/tokens/transformation/web/filterWeb.js +++ b/src/tokens/transformation/web/filterWeb.ts @@ -1,3 +1,5 @@ +import type { Filter } from 'style-dictionary/types' + const acceptedTypes = [ 'color', 'dimension', @@ -10,4 +12,7 @@ const acceptedTypes = [ 'number' ] -export default (token) => acceptedTypes.includes(token.type) +export default { + name: 'filterWeb', + filter: (token) => acceptedTypes.includes(token.type) +} as Filter diff --git a/src/tokens/transformation/web/formatCss.js b/src/tokens/transformation/web/formatCss.js deleted file mode 100644 index 7ff2c5f99..000000000 --- a/src/tokens/transformation/web/formatCss.js +++ /dev/null @@ -1,63 +0,0 @@ -import formattedVariables from './formattedVariables' -import fileHeader from './fileHeader' -import { - filteredTokens, - matchDarkThemeToken, - matchLightThemeToken -} from '../common/tokenFilters' -import { varDefFormat } from '../../utils' - -export default ({ dictionary, options, file }) => { - const opts = options ?? {} - // const { outputReferences } = opts - const outputReferences = true - const groupedTokens = { - // if you export the prefixes use token.path[0] instead of [1] - light: filteredTokens(dictionary, (token) => matchLightThemeToken(token)), - dark: filteredTokens(dictionary, (token) => matchDarkThemeToken(token)), - - // Note: We don't export the dark & light versions of the tokens separately - // - developers can refer to the primitive tokens instead. - rest: filteredTokens( - dictionary, - (token) => !matchDarkThemeToken(token) && !matchLightThemeToken(token) - ) - } - - const defaultVars = formattedVariables({ - format: 'css', - dictionary: groupedTokens.rest, - outputReferences - }) - - const lightVars = formattedVariables({ - format: 'css', - dictionary: groupedTokens.light, - outputReferences - }).replace(/-light-/gm, '-') - - const darkVars = formattedVariables({ - format: 'css', - dictionary: groupedTokens.dark, - outputReferences - }).replace(/-dark-/gm, '-') - - // prettier-ignore - return ( - fileHeader({ file }) + - [ - defaultVars && varDefFormat`:root {${defaultVars}}`, - lightVars && varDefFormat`@media (prefers-color-scheme: light) { - :root {${lightVars} } -}`, - darkVars && varDefFormat`@media (prefers-color-scheme: dark) { - :root {${darkVars} } -}`, - lightVars && varDefFormat`[data-theme="light"] {${lightVars}}`, - lightVars && varDefFormat`[data-theme="dark"] {${darkVars}}`, - ] - .filter((v) => !!v) - .join('\n\n') + - '\n' - ) -} diff --git a/src/tokens/transformation/web/formatCss.ts b/src/tokens/transformation/web/formatCss.ts new file mode 100644 index 000000000..2026623e4 --- /dev/null +++ b/src/tokens/transformation/web/formatCss.ts @@ -0,0 +1,65 @@ +import type { Format } from 'style-dictionary/types' +import { fileHeader } from 'style-dictionary/utils' +import { varDefFormat } from '../../utils' +import { + filteredTokens, + matchDarkThemeToken, + matchLightThemeToken +} from '../common/tokenFilters' +import formattedVariables from './formattedVariables' + +export default { + name: 'custom/css', + format: async ({ dictionary, options, file }) => { + const outputReferences = true + const groupedTokens = { + // if you export the prefixes use token.path[0] instead of [1] + light: filteredTokens(dictionary, (token) => matchLightThemeToken(token)), + dark: filteredTokens(dictionary, (token) => matchDarkThemeToken(token)), + + // Note: We don't export the dark & light versions of the tokens separately + // - developers can refer to the primitive tokens instead. + rest: filteredTokens( + dictionary, + (token) => !matchDarkThemeToken(token) && !matchLightThemeToken(token) + ) + } + + const defaultVars = formattedVariables({ + format: 'css', + dictionary: groupedTokens.rest, + outputReferences + }) + + const lightVars = formattedVariables({ + format: 'css', + dictionary: groupedTokens.light, + outputReferences + }).replace(/-light-/gm, '-') + + const darkVars = formattedVariables({ + format: 'css', + dictionary: groupedTokens.dark, + outputReferences + }).replace(/-dark-/gm, '-') + + // prettier-ignore + return ( + await fileHeader({ file, ...options }) + + [ + defaultVars && varDefFormat`:root {${defaultVars}}`, + lightVars && varDefFormat`@media (prefers-color-scheme: light) { + :root {${lightVars} } +}`, + darkVars && varDefFormat`@media (prefers-color-scheme: dark) { + :root {${darkVars} } +}`, + lightVars && varDefFormat`[data-theme="light"] {${lightVars}}`, + lightVars && varDefFormat`[data-theme="dark"] {${darkVars}}`, + ] + .filter((v) => !!v) + .join('\n\n') + + '\n' + ) + } +} as Format diff --git a/src/tokens/transformation/web/formatCssAsJs.js b/src/tokens/transformation/web/formatCssAsJs.ts similarity index 72% rename from src/tokens/transformation/web/formatCssAsJs.js rename to src/tokens/transformation/web/formatCssAsJs.ts index 4c50ec73a..d5ada4260 100644 --- a/src/tokens/transformation/web/formatCssAsJs.js +++ b/src/tokens/transformation/web/formatCssAsJs.ts @@ -1,7 +1,8 @@ -import camelCase from 'lodash.camelcase' -import fileHeader from '../web/fileHeader' -import { createPropertyNameFormatter } from './createPropertyFormatter' import { TinyColor } from '@ctrl/tinycolor' +import { camelCase } from 'change-case' +import type { Format } from 'style-dictionary/types' +import { fileHeader } from 'style-dictionary/utils' +import { createPropertyNameFormatter } from './createPropertyFormatter' const { formatName } = createPropertyNameFormatter('css', { indentation: '' }) const THEMED_COLOR_GROUP_PARENT_KEYS = ['color', 'legacy', 'elevation'] @@ -55,7 +56,7 @@ function getLiteral(token) { return token.value } -function formattedVariables(properties) { +function formattedVariables(tokens) { const result = { // The nonsensical 'toString' property exists to force the category // objects to not be interpreted by styled-components as a CSSObject @@ -65,8 +66,8 @@ function formattedVariables(properties) { // https://github.com/brave/leo/pull/187#issuecomment-1410907561 [FAKE_PROPERTY_NAME]: [''] } - for (const key in properties) { - let value = properties[key] + for (const key in tokens) { + let value = tokens[key] if (!isToken(value)) { // If we are a collection of colors, which we have dark and light versions // we only want to export the themeless version @@ -103,31 +104,34 @@ function formattedVariables(properties) { return result } -export default function formatCssAsJs({ dictionary, file }) { - let fileContents = fileHeader({ file }) + '\n' +export default { + name: 'custom/cssJS', + format: async ({ dictionary, file, options }) => { + let fileContents = (await fileHeader({ file, ...options })) + '\n' - const themeObject = formattedVariables(dictionary.properties) + const themeObject = formattedVariables(dictionary.tokens) - // Separate out each main property, to allow for tree shaking and easy type-to-complete - // imports in code editors. - for (const property in themeObject) { - if (property === FAKE_PROPERTY_NAME) { - continue + // Separate out each main property, to allow for tree shaking and easy type-to-complete + // imports in code editors. + for (const property in themeObject) { + if (property === FAKE_PROPERTY_NAME) { + continue + } + fileContents += + `export const ${property} = ` + + JSON.stringify(themeObject[property], null, 2) + + ' as const \n' } - fileContents += - `export const ${property} = ` + - JSON.stringify(themeObject[property], null, 2) + - ' as const \n' - } - // Add a comment above variables with the literal value of the variable. - const variableRegex = /\n(\s+)(".*":) "(var\([a-z0-9-]+\))"/gm - return fileContents.replace( - variableRegex, - (substring, spacing, name, variable) => { - return ` -${spacing}/** ${literals[variable]} */ -${spacing}${name} "${variable}"` - } - ) -} + // Add a comment above variables with the literal value of the variable. + const variableRegex = /\n(\s+)(".*":) "(var\([a-z0-9-]+\))"/gm + return fileContents.replace( + variableRegex, + (substring, spacing, name, variable) => { + return ` + ${spacing}/** ${literals[variable]} */ + ${spacing}${name} "${variable}"` + } + ) + } +} as Format diff --git a/src/tokens/transformation/web/formattedVariables.js b/src/tokens/transformation/web/formattedVariables.ts similarity index 100% rename from src/tokens/transformation/web/formattedVariables.js rename to src/tokens/transformation/web/formattedVariables.ts diff --git a/src/tokens/transformation/web/index.ts b/src/tokens/transformation/web/index.ts index 4218bf059..f162be1cf 100644 --- a/src/tokens/transformation/web/index.ts +++ b/src/tokens/transformation/web/index.ts @@ -14,48 +14,21 @@ import formatCss from './formatCss' import formatCssAsJs from './formatCssAsJs' // Filters -StyleDictionary.registerFilter({ - name: 'filterWeb', - matcher: filterWeb -}) +StyleDictionary.registerFilter(filterWeb) // Transforms -StyleDictionary.registerTransform({ - name: 'size/px', - ...sizePx -}) -StyleDictionary.registerTransform({ - name: 'web/shadow', - ...webShadows -}) -StyleDictionary.registerTransform({ - name: 'web/radius', - ...webRadius -}) -StyleDictionary.registerTransform({ - name: 'web/size', - ...webSize -}) -StyleDictionary.registerTransform({ - name: 'web/padding', - ...webPadding -}) -StyleDictionary.registerTransform({ - name: 'web/font', - ...webFont -}) -StyleDictionary.registerTransform({ - name: 'web/gradient', - ...webGradient -}) -StyleDictionary.registerTransform({ - name: 'web/color', - ...webColor -}) +StyleDictionary.registerTransform(sizePx) +StyleDictionary.registerTransform(webShadows) +StyleDictionary.registerTransform(webRadius) +StyleDictionary.registerTransform(webSize) +StyleDictionary.registerTransform(webPadding) +StyleDictionary.registerTransform(webFont) +StyleDictionary.registerTransform(webGradient) +StyleDictionary.registerTransform(webColor) StyleDictionary.registerTransformGroup({ name: 'custom/css', - transforms: StyleDictionary.transformGroup.css.concat([ + transforms: StyleDictionary.hooks.transformGroups.css.concat([ 'size/px', 'web/shadow', 'web/radius', @@ -68,12 +41,5 @@ StyleDictionary.registerTransformGroup({ }) // Formats -StyleDictionary.registerFormat({ - name: 'custom/css', - formatter: formatCss -}) - -StyleDictionary.registerFormat({ - name: 'custom/cssJS', - formatter: formatCssAsJs -}) +StyleDictionary.registerFormat(formatCss) +StyleDictionary.registerFormat(formatCssAsJs) diff --git a/src/tokens/transformation/web/sizePx.ts b/src/tokens/transformation/web/sizePx.ts index f79db9a26..8f856177c 100644 --- a/src/tokens/transformation/web/sizePx.ts +++ b/src/tokens/transformation/web/sizePx.ts @@ -1,11 +1,12 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' export default { + name: 'size/px', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'dimension' && token.value !== 0 }, - transformer: function (token) { + transform: function (token) { return `${token.value}px` } } as Transform diff --git a/src/tokens/transformation/web/sortByReference.js b/src/tokens/transformation/web/sortByReference.ts similarity index 85% rename from src/tokens/transformation/web/sortByReference.js rename to src/tokens/transformation/web/sortByReference.ts index 6ffa7217f..44774f5ef 100644 --- a/src/tokens/transformation/web/sortByReference.js +++ b/src/tokens/transformation/web/sortByReference.ts @@ -1,3 +1,4 @@ +import { usesReferences, getReferences } from 'style-dictionary/utils' /* * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * @@ -32,11 +33,11 @@ export default function sortByReference(dictionary) { // If token a uses a reference and token b doesn't, b might come before a // read on.. - if (a.original && dictionary.usesReference(a.original.value)) { + if (a.original && usesReferences(a.original.value, dictionary.tokens)) { // Both a and b have references, we need to see if the reference each other - if (b.original && dictionary.usesReference(b.original.value)) { - const aRefs = dictionary.getReferences(a.original.value) - const bRefs = dictionary.getReferences(b.original.value) + if (b.original && usesReferences(b.original.value, dictionary.tokens)) { + const aRefs = getReferences(a.original.value, dictionary.tokens) + const bRefs = getReferences(b.original.value, dictionary.tokens) aRefs.forEach((aRef) => { // a references b, we want b to come first diff --git a/src/tokens/transformation/web/webColorRef.js b/src/tokens/transformation/web/webColorRef.ts similarity index 100% rename from src/tokens/transformation/web/webColorRef.js rename to src/tokens/transformation/web/webColorRef.ts diff --git a/src/tokens/transformation/web/webFont.ts b/src/tokens/transformation/web/webFont.ts index 88e899fe5..ddbeaadb1 100644 --- a/src/tokens/transformation/web/webFont.ts +++ b/src/tokens/transformation/web/webFont.ts @@ -1,4 +1,4 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' const notDefault = (value, defaultValue) => value !== defaultValue ? value : '' @@ -12,11 +12,12 @@ const fontFamily = ( : fontFamily export default { + name: 'web/font', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'custom-fontStyle' }, - transformer: function ({ value: font }, platform) { + transform: function ({ value: font }, platform) { // font: font-style font-variant font-weight font-size/line-height font-family; return `${notDefault(font.fontStretch, 'normal')} ${notDefault( font.fontStyle, diff --git a/src/tokens/transformation/web/webGradient.ts b/src/tokens/transformation/web/webGradient.ts index 4c7f477e3..f16c9ba4e 100644 --- a/src/tokens/transformation/web/webGradient.ts +++ b/src/tokens/transformation/web/webGradient.ts @@ -1,12 +1,12 @@ import { TinyColor } from '@ctrl/tinycolor' -import { Transform } from 'style-dictionary' - +import type { Transform } from 'style-dictionary/types' export default { + name: 'web/gradient', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'custom-gradient' }, - transformer: function ({ value }) { + transform: function ({ value }) { value = Array.isArray(value) ? value : [value] return value.map((v) => formatGradient(v)).join(', ') } diff --git a/src/tokens/transformation/web/webPadding.ts b/src/tokens/transformation/web/webPadding.ts index ae195afe2..6e8d88ef7 100644 --- a/src/tokens/transformation/web/webPadding.ts +++ b/src/tokens/transformation/web/webPadding.ts @@ -1,11 +1,12 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' export default { + name: 'web/padding', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'custom-spacing' }, - transformer: ({ value: { top, left, bottom, right } }) => { + transform: ({ value: { top, left, bottom, right } }) => { if ([bottom, left, right].every((v) => v === top)) { return `${top}px` } diff --git a/src/tokens/transformation/web/webRadius.ts b/src/tokens/transformation/web/webRadius.ts index 65e4d1e58..f0648b191 100644 --- a/src/tokens/transformation/web/webRadius.ts +++ b/src/tokens/transformation/web/webRadius.ts @@ -1,11 +1,12 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' export default { + name: 'web/radius', type: 'value', - matcher: function (token) { + filter: function (token) { return token.type === 'custom-radius' }, - transformer: function ({ value }) { + transform: function ({ value }) { if ( [value.topRight, value.bottomLeft, value.bottomRight].every( (v) => v === value.topLeft diff --git a/src/tokens/transformation/web/webShadows.ts b/src/tokens/transformation/web/webShadows.ts index dd630b7d1..a630ab41d 100644 --- a/src/tokens/transformation/web/webShadows.ts +++ b/src/tokens/transformation/web/webShadows.ts @@ -1,12 +1,13 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' import { formatColor } from './webColorRef' export default { + name: 'web/shadow', type: 'value', - matcher(token) { + filter(token) { return token.type === 'custom-shadow' && token.value !== 0 }, - transformer({ value }) { + transform({ value }) { value = Array.isArray(value) ? value : [value] return value.map((v) => formatShadow(v)).join(', ') } diff --git a/src/tokens/transformation/web/webSize.ts b/src/tokens/transformation/web/webSize.ts index f86c9521a..d1093f846 100644 --- a/src/tokens/transformation/web/webSize.ts +++ b/src/tokens/transformation/web/webSize.ts @@ -1,11 +1,12 @@ -import { Transform } from 'style-dictionary' +import type { Transform } from 'style-dictionary/types' export default { + name: 'web/size', type: 'value', - matcher({ type }) { + filter({ type }) { return type === 'number' }, - transformer({ value, name }) { + transform({ value, name }) { // Font weight doesn't have a unit - unfortunately we have no better // way of determining whether this is a font-weight than checking the name. const unit = name.endsWith('font-weight') ? '' : 'px' diff --git a/src/tokens/utils.js b/src/tokens/utils.ts similarity index 100% rename from src/tokens/utils.js rename to src/tokens/utils.ts diff --git a/tsconfig.json b/tsconfig.json index f0773ea22..3480a513f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,10 @@ { "extends": "@tsconfig/svelte/tsconfig.json", - "include": ["src/components/**/*", "src/svelteDirectives/**/*"], + "include": [ + "src/components/**/*", + "src/svelteDirectives/**/*", + "src/tokens/**/*" + ], "exclude": ["node_modules/*", "__sapper__/*", "public/*"], "compilerOptions": { "strictNullChecks": false,