diff --git a/.changeset/little-mice-pump.md b/.changeset/little-mice-pump.md
new file mode 100644
index 000000000..e2d78ef53
--- /dev/null
+++ b/.changeset/little-mice-pump.md
@@ -0,0 +1,5 @@
+---
+'style-dictionary': patch
+---
+
+Pass SD options to fileheaders and filters, to make it easier to use and adjust according to config or options like usesDTCG.
diff --git a/.changeset/ten-numbers-lay.md b/.changeset/ten-numbers-lay.md
new file mode 100644
index 000000000..c09817320
--- /dev/null
+++ b/.changeset/ten-numbers-lay.md
@@ -0,0 +1,5 @@
+---
+'style-dictionary': patch
+---
+
+Add unfilteredAllTokens property in dictionary object for formats, which is an unfiltered version of allTokens property, or a flattened version of the unfilteredTokens property.
diff --git a/.eslintrc.json b/.eslintrc.json
index c897b1813..a5cb810b1 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -15,7 +15,6 @@
"rules": {
"no-unused-vars": 1,
"no-console": ["error", { "allow": ["warn", "error"] }],
- "mocha/no-skipped-tests": "warn",
"mocha/no-exclusive-tests": "error",
"no-var": "error"
},
diff --git a/__integration__/__snapshots__/customFormats.test.snap.js b/__integration__/__snapshots__/customFormats.test.snap.js
index c85748c65..060c21614 100644
--- a/__integration__/__snapshots__/customFormats.test.snap.js
+++ b/__integration__/__snapshots__/customFormats.test.snap.js
@@ -269,7 +269,93 @@ snapshots["integration custom formats inline custom with new args should match s
}
}
}
- }
+ },
+ "unfilteredAllTokens": [
+ {
+ "value": "0.5rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 0.5,
+ "type": "dimension"
+ },
+ "name": "SizePaddingSmall",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "small"
+ },
+ "path": [
+ "size",
+ "padding",
+ "small"
+ ]
+ },
+ {
+ "value": "1rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 1,
+ "type": "dimension"
+ },
+ "name": "SizePaddingMedium",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "medium"
+ },
+ "path": [
+ "size",
+ "padding",
+ "medium"
+ ]
+ },
+ {
+ "value": "1rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 1,
+ "type": "dimension"
+ },
+ "name": "SizePaddingLarge",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "large"
+ },
+ "path": [
+ "size",
+ "padding",
+ "large"
+ ]
+ },
+ {
+ "value": "1rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 1,
+ "type": "dimension"
+ },
+ "name": "SizePaddingXl",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "xl"
+ },
+ "path": [
+ "size",
+ "padding",
+ "xl"
+ ]
+ }
+ ]
},
"allTokens": [
{
@@ -497,9 +583,373 @@ snapshots["integration custom formats inline custom with new args should match s
"destination": "inlineCustomFormatWithNewArgs.json"
},
"options": {
+ "hooks": {
+ "parsers": {},
+ "preprocessors": {},
+ "transformGroups": {
+ "web": [
+ "attribute/cti",
+ "name/kebab",
+ "size/px",
+ "color/css"
+ ],
+ "js": [
+ "attribute/cti",
+ "name/pascal",
+ "size/rem",
+ "color/hex"
+ ],
+ "scss": [
+ "attribute/cti",
+ "name/kebab",
+ "time/seconds",
+ "html/icon",
+ "size/rem",
+ "color/css",
+ "asset/url",
+ "fontFamily/css",
+ "cubicBezier/css",
+ "strokeStyle/css/shorthand",
+ "border/css/shorthand",
+ "typography/css/shorthand",
+ "transition/css/shorthand",
+ "shadow/css/shorthand"
+ ],
+ "css": [
+ "attribute/cti",
+ "name/kebab",
+ "time/seconds",
+ "html/icon",
+ "size/rem",
+ "color/css",
+ "asset/url",
+ "fontFamily/css",
+ "cubicBezier/css",
+ "strokeStyle/css/shorthand",
+ "border/css/shorthand",
+ "typography/css/shorthand",
+ "transition/css/shorthand",
+ "shadow/css/shorthand"
+ ],
+ "less": [
+ "attribute/cti",
+ "name/kebab",
+ "time/seconds",
+ "html/icon",
+ "size/rem",
+ "color/hex",
+ "asset/url",
+ "fontFamily/css",
+ "cubicBezier/css",
+ "strokeStyle/css/shorthand",
+ "border/css/shorthand",
+ "typography/css/shorthand",
+ "transition/css/shorthand",
+ "shadow/css/shorthand"
+ ],
+ "html": [
+ "attribute/cti",
+ "attribute/color",
+ "name/human"
+ ],
+ "android": [
+ "attribute/cti",
+ "name/snake",
+ "color/hex8android",
+ "size/remToSp",
+ "size/remToDp"
+ ],
+ "compose": [
+ "attribute/cti",
+ "name/camel",
+ "color/composeColor",
+ "size/compose/em",
+ "size/compose/remToSp",
+ "size/compose/remToDp"
+ ],
+ "ios": [
+ "attribute/cti",
+ "name/pascal",
+ "color/UIColor",
+ "content/objC/literal",
+ "asset/objC/literal",
+ "size/remToPt"
+ ],
+ "ios-swift": [
+ "attribute/cti",
+ "name/camel",
+ "color/UIColorSwift",
+ "content/swift/literal",
+ "asset/swift/literal",
+ "size/swift/remToCGFloat"
+ ],
+ "ios-swift-separate": [
+ "attribute/cti",
+ "name/camel",
+ "color/UIColorSwift",
+ "content/swift/literal",
+ "asset/swift/literal",
+ "size/swift/remToCGFloat"
+ ],
+ "assets": [
+ "attribute/cti"
+ ],
+ "flutter": [
+ "attribute/cti",
+ "name/camel",
+ "color/hex8flutter",
+ "size/flutter/remToDouble",
+ "content/flutter/literal",
+ "asset/flutter/literal"
+ ],
+ "flutter-separate": [
+ "attribute/cti",
+ "name/camel",
+ "color/hex8flutter",
+ "size/flutter/remToDouble",
+ "content/flutter/literal",
+ "asset/flutter/literal"
+ ],
+ "react-native": [
+ "name/camel",
+ "color/css",
+ "size/object"
+ ]
+ },
+ "transforms": {
+ "attribute/cti": {
+ "type": "attribute"
+ },
+ "attribute/color": {
+ "type": "attribute"
+ },
+ "name/human": {
+ "type": "name"
+ },
+ "name/camel": {
+ "type": "name"
+ },
+ "name/kebab": {
+ "type": "name"
+ },
+ "name/snake": {
+ "type": "name"
+ },
+ "name/constant": {
+ "type": "name"
+ },
+ "name/pascal": {
+ "type": "name"
+ },
+ "color/rgb": {
+ "type": "value"
+ },
+ "color/hsl": {
+ "type": "value"
+ },
+ "color/hsl-4": {
+ "type": "value"
+ },
+ "color/hex": {
+ "type": "value"
+ },
+ "color/hex8": {
+ "type": "value"
+ },
+ "color/hex8android": {
+ "type": "value"
+ },
+ "color/composeColor": {
+ "type": "value"
+ },
+ "color/UIColor": {
+ "type": "value"
+ },
+ "color/UIColorSwift": {
+ "type": "value"
+ },
+ "color/ColorSwiftUI": {
+ "type": "value"
+ },
+ "color/css": {
+ "type": "value"
+ },
+ "color/sketch": {
+ "type": "value"
+ },
+ "size/sp": {
+ "type": "value"
+ },
+ "size/dp": {
+ "type": "value"
+ },
+ "size/object": {
+ "type": "value"
+ },
+ "size/remToSp": {
+ "type": "value"
+ },
+ "size/remToDp": {
+ "type": "value"
+ },
+ "size/px": {
+ "type": "value"
+ },
+ "size/rem": {
+ "type": "value"
+ },
+ "size/remToPt": {
+ "type": "value"
+ },
+ "size/compose/remToSp": {
+ "type": "value"
+ },
+ "size/compose/remToDp": {
+ "type": "value"
+ },
+ "size/compose/em": {
+ "type": "value"
+ },
+ "size/swift/remToCGFloat": {
+ "type": "value"
+ },
+ "size/remToPx": {
+ "type": "value"
+ },
+ "size/pxToRem": {
+ "type": "value"
+ },
+ "html/icon": {
+ "type": "value"
+ },
+ "content/quote": {
+ "type": "value"
+ },
+ "content/objC/literal": {
+ "type": "value"
+ },
+ "content/swift/literal": {
+ "type": "value"
+ },
+ "time/seconds": {
+ "type": "value"
+ },
+ "fontFamily/css": {
+ "type": "value"
+ },
+ "cubicBezier/css": {
+ "type": "value"
+ },
+ "strokeStyle/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "border/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "typography/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "transition/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "shadow/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "asset/url": {
+ "type": "value"
+ },
+ "asset/base64": {
+ "type": "value"
+ },
+ "asset/path": {
+ "type": "value"
+ },
+ "asset/objC/literal": {
+ "type": "value"
+ },
+ "asset/swift/literal": {
+ "type": "value"
+ },
+ "color/hex8flutter": {
+ "type": "value"
+ },
+ "content/flutter/literal": {
+ "type": "value"
+ },
+ "asset/flutter/literal": {
+ "type": "value"
+ },
+ "size/flutter/remToDouble": {
+ "type": "value"
+ }
+ },
+ "formats": {},
+ "fileHeaders": {},
+ "filters": {},
+ "actions": {
+ "android/copyImages": {},
+ "copy_assets": {}
+ }
+ },
+ "source": [
+ "__integration__/tokens/size/padding.json"
+ ],
+ "platforms": {
+ "inlineCustomFormats": {
+ "transformGroup": "js",
+ "buildPath": "__integration__/build/",
+ "options": {
+ "otherOption": "platform option"
+ },
+ "files": [
+ {
+ "destination": "inlineCustomFormatWithOldArgs.json",
+ "format": "inlineCustomFormatWithOldArgs",
+ "options": {
+ "showFileHeader": true,
+ "otherOption": "Test"
+ }
+ },
+ {
+ "destination": "inlineCustomFormatWithNewArgs.json",
+ "format": "inlineCustomFormatWithNewArgs",
+ "options": {
+ "showFileHeader": true,
+ "otherOption": "Test"
+ }
+ }
+ ]
+ },
+ "customFormats": {
+ "transformGroup": "js",
+ "buildPath": "__integration__/build/",
+ "options": {
+ "otherOption": "platform option"
+ },
+ "files": [
+ {
+ "destination": "registerCustomFormatWithNewArgs.json",
+ "format": "registerCustomFormatWithNewArgs",
+ "options": {
+ "showFileHeader": true,
+ "otherOption": "Test"
+ }
+ }
+ ]
+ }
+ },
+ "log": {
+ "warnings": "warn",
+ "verbosity": "default"
+ },
+ "usesDtcg": false,
"otherOption": "Test",
- "showFileHeader": true,
- "usesDtcg": false
+ "showFileHeader": true
}
}`;
/* end snapshot integration custom formats inline custom with new args should match snapshot */
@@ -772,7 +1222,93 @@ snapshots["integration custom formats register custom format with new args shoul
}
}
}
- }
+ },
+ "unfilteredAllTokens": [
+ {
+ "value": "0.5rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 0.5,
+ "type": "dimension"
+ },
+ "name": "SizePaddingSmall",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "small"
+ },
+ "path": [
+ "size",
+ "padding",
+ "small"
+ ]
+ },
+ {
+ "value": "1rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 1,
+ "type": "dimension"
+ },
+ "name": "SizePaddingMedium",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "medium"
+ },
+ "path": [
+ "size",
+ "padding",
+ "medium"
+ ]
+ },
+ {
+ "value": "1rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 1,
+ "type": "dimension"
+ },
+ "name": "SizePaddingLarge",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "large"
+ },
+ "path": [
+ "size",
+ "padding",
+ "large"
+ ]
+ },
+ {
+ "value": "1rem",
+ "type": "dimension",
+ "filePath": "__integration__/tokens/size/padding.json",
+ "isSource": true,
+ "original": {
+ "value": 1,
+ "type": "dimension"
+ },
+ "name": "SizePaddingXl",
+ "attributes": {
+ "category": "size",
+ "type": "padding",
+ "item": "xl"
+ },
+ "path": [
+ "size",
+ "padding",
+ "xl"
+ ]
+ }
+ ]
},
"allTokens": [
{
@@ -993,9 +1529,373 @@ snapshots["integration custom formats register custom format with new args shoul
"destination": "registerCustomFormatWithNewArgs.json"
},
"options": {
+ "hooks": {
+ "parsers": {},
+ "preprocessors": {},
+ "transformGroups": {
+ "web": [
+ "attribute/cti",
+ "name/kebab",
+ "size/px",
+ "color/css"
+ ],
+ "js": [
+ "attribute/cti",
+ "name/pascal",
+ "size/rem",
+ "color/hex"
+ ],
+ "scss": [
+ "attribute/cti",
+ "name/kebab",
+ "time/seconds",
+ "html/icon",
+ "size/rem",
+ "color/css",
+ "asset/url",
+ "fontFamily/css",
+ "cubicBezier/css",
+ "strokeStyle/css/shorthand",
+ "border/css/shorthand",
+ "typography/css/shorthand",
+ "transition/css/shorthand",
+ "shadow/css/shorthand"
+ ],
+ "css": [
+ "attribute/cti",
+ "name/kebab",
+ "time/seconds",
+ "html/icon",
+ "size/rem",
+ "color/css",
+ "asset/url",
+ "fontFamily/css",
+ "cubicBezier/css",
+ "strokeStyle/css/shorthand",
+ "border/css/shorthand",
+ "typography/css/shorthand",
+ "transition/css/shorthand",
+ "shadow/css/shorthand"
+ ],
+ "less": [
+ "attribute/cti",
+ "name/kebab",
+ "time/seconds",
+ "html/icon",
+ "size/rem",
+ "color/hex",
+ "asset/url",
+ "fontFamily/css",
+ "cubicBezier/css",
+ "strokeStyle/css/shorthand",
+ "border/css/shorthand",
+ "typography/css/shorthand",
+ "transition/css/shorthand",
+ "shadow/css/shorthand"
+ ],
+ "html": [
+ "attribute/cti",
+ "attribute/color",
+ "name/human"
+ ],
+ "android": [
+ "attribute/cti",
+ "name/snake",
+ "color/hex8android",
+ "size/remToSp",
+ "size/remToDp"
+ ],
+ "compose": [
+ "attribute/cti",
+ "name/camel",
+ "color/composeColor",
+ "size/compose/em",
+ "size/compose/remToSp",
+ "size/compose/remToDp"
+ ],
+ "ios": [
+ "attribute/cti",
+ "name/pascal",
+ "color/UIColor",
+ "content/objC/literal",
+ "asset/objC/literal",
+ "size/remToPt"
+ ],
+ "ios-swift": [
+ "attribute/cti",
+ "name/camel",
+ "color/UIColorSwift",
+ "content/swift/literal",
+ "asset/swift/literal",
+ "size/swift/remToCGFloat"
+ ],
+ "ios-swift-separate": [
+ "attribute/cti",
+ "name/camel",
+ "color/UIColorSwift",
+ "content/swift/literal",
+ "asset/swift/literal",
+ "size/swift/remToCGFloat"
+ ],
+ "assets": [
+ "attribute/cti"
+ ],
+ "flutter": [
+ "attribute/cti",
+ "name/camel",
+ "color/hex8flutter",
+ "size/flutter/remToDouble",
+ "content/flutter/literal",
+ "asset/flutter/literal"
+ ],
+ "flutter-separate": [
+ "attribute/cti",
+ "name/camel",
+ "color/hex8flutter",
+ "size/flutter/remToDouble",
+ "content/flutter/literal",
+ "asset/flutter/literal"
+ ],
+ "react-native": [
+ "name/camel",
+ "color/css",
+ "size/object"
+ ]
+ },
+ "transforms": {
+ "attribute/cti": {
+ "type": "attribute"
+ },
+ "attribute/color": {
+ "type": "attribute"
+ },
+ "name/human": {
+ "type": "name"
+ },
+ "name/camel": {
+ "type": "name"
+ },
+ "name/kebab": {
+ "type": "name"
+ },
+ "name/snake": {
+ "type": "name"
+ },
+ "name/constant": {
+ "type": "name"
+ },
+ "name/pascal": {
+ "type": "name"
+ },
+ "color/rgb": {
+ "type": "value"
+ },
+ "color/hsl": {
+ "type": "value"
+ },
+ "color/hsl-4": {
+ "type": "value"
+ },
+ "color/hex": {
+ "type": "value"
+ },
+ "color/hex8": {
+ "type": "value"
+ },
+ "color/hex8android": {
+ "type": "value"
+ },
+ "color/composeColor": {
+ "type": "value"
+ },
+ "color/UIColor": {
+ "type": "value"
+ },
+ "color/UIColorSwift": {
+ "type": "value"
+ },
+ "color/ColorSwiftUI": {
+ "type": "value"
+ },
+ "color/css": {
+ "type": "value"
+ },
+ "color/sketch": {
+ "type": "value"
+ },
+ "size/sp": {
+ "type": "value"
+ },
+ "size/dp": {
+ "type": "value"
+ },
+ "size/object": {
+ "type": "value"
+ },
+ "size/remToSp": {
+ "type": "value"
+ },
+ "size/remToDp": {
+ "type": "value"
+ },
+ "size/px": {
+ "type": "value"
+ },
+ "size/rem": {
+ "type": "value"
+ },
+ "size/remToPt": {
+ "type": "value"
+ },
+ "size/compose/remToSp": {
+ "type": "value"
+ },
+ "size/compose/remToDp": {
+ "type": "value"
+ },
+ "size/compose/em": {
+ "type": "value"
+ },
+ "size/swift/remToCGFloat": {
+ "type": "value"
+ },
+ "size/remToPx": {
+ "type": "value"
+ },
+ "size/pxToRem": {
+ "type": "value"
+ },
+ "html/icon": {
+ "type": "value"
+ },
+ "content/quote": {
+ "type": "value"
+ },
+ "content/objC/literal": {
+ "type": "value"
+ },
+ "content/swift/literal": {
+ "type": "value"
+ },
+ "time/seconds": {
+ "type": "value"
+ },
+ "fontFamily/css": {
+ "type": "value"
+ },
+ "cubicBezier/css": {
+ "type": "value"
+ },
+ "strokeStyle/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "border/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "typography/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "transition/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "shadow/css/shorthand": {
+ "type": "value",
+ "transitive": true
+ },
+ "asset/url": {
+ "type": "value"
+ },
+ "asset/base64": {
+ "type": "value"
+ },
+ "asset/path": {
+ "type": "value"
+ },
+ "asset/objC/literal": {
+ "type": "value"
+ },
+ "asset/swift/literal": {
+ "type": "value"
+ },
+ "color/hex8flutter": {
+ "type": "value"
+ },
+ "content/flutter/literal": {
+ "type": "value"
+ },
+ "asset/flutter/literal": {
+ "type": "value"
+ },
+ "size/flutter/remToDouble": {
+ "type": "value"
+ }
+ },
+ "formats": {},
+ "fileHeaders": {},
+ "filters": {},
+ "actions": {
+ "android/copyImages": {},
+ "copy_assets": {}
+ }
+ },
+ "source": [
+ "__integration__/tokens/size/padding.json"
+ ],
+ "platforms": {
+ "inlineCustomFormats": {
+ "transformGroup": "js",
+ "buildPath": "__integration__/build/",
+ "options": {
+ "otherOption": "platform option"
+ },
+ "files": [
+ {
+ "destination": "inlineCustomFormatWithOldArgs.json",
+ "format": "inlineCustomFormatWithOldArgs",
+ "options": {
+ "showFileHeader": true,
+ "otherOption": "Test"
+ }
+ },
+ {
+ "destination": "inlineCustomFormatWithNewArgs.json",
+ "format": "inlineCustomFormatWithNewArgs",
+ "options": {
+ "showFileHeader": true,
+ "otherOption": "Test"
+ }
+ }
+ ]
+ },
+ "customFormats": {
+ "transformGroup": "js",
+ "buildPath": "__integration__/build/",
+ "options": {
+ "otherOption": "platform option"
+ },
+ "files": [
+ {
+ "destination": "registerCustomFormatWithNewArgs.json",
+ "format": "registerCustomFormatWithNewArgs",
+ "options": {
+ "showFileHeader": true,
+ "otherOption": "Test"
+ }
+ }
+ ]
+ }
+ },
+ "log": {
+ "warnings": "warn",
+ "verbosity": "default"
+ },
+ "usesDtcg": false,
"otherOption": "Test",
- "showFileHeader": true,
- "usesDtcg": false
+ "showFileHeader": true
}
}`;
/* end snapshot integration custom formats register custom format with new args should match snapshot */
diff --git a/docs/src/content/docs/reference/Hooks/Formats/index.md b/docs/src/content/docs/reference/Hooks/Formats/index.md
index 3c4b07fa6..1d80f4fe5 100644
--- a/docs/src/content/docs/reference/Hooks/Formats/index.md
+++ b/docs/src/content/docs/reference/Hooks/Formats/index.md
@@ -269,16 +269,17 @@ You can create custom formats using the [`registerFormat`](/reference/api#regist
The format function that is called when Style Dictionary builds files.
-| Param | Type | Description |
-| ---------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------- |
-| `args` | `Object` | A single argument to support named parameters and destructuring. |
-| `args.dictionary` | `Dictionary` | Transformed Dictionary object containing allTokens, tokens and unfilteredTokens. |
-| `args.dictionary.allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. |
-| `args.dictionary.tokens` | `TransformedTokens` | All tokens, still in unflattened object format. |
-| `args.dictionary.unfilteredTokens` | `TransformedTokens` | All tokens, still in unflattened object format, including tokens that were filtered out by filters. |
-| `args.platform` | `Platform` | [Platform config](/reference/config#platform) |
-| `args.file` | `File` | [File config](/reference/config#file) |
-| `args.options` | `Object` | Merged object with SD [Config](/reference/config#properties) & [FormatOptions](#format-configuration) |
+| Param | Type | Description |
+| ------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------- |
+| `args` | `Object` | A single argument to support named parameters and destructuring. |
+| `args.dictionary` | `Dictionary` | Transformed Dictionary object containing allTokens, tokens and unfilteredTokens. |
+| `args.dictionary.allTokens` | `TransformedToken[]` | Flattened array of all tokens, easiest to loop over and export to a flat format. |
+| `args.dictionary.tokens` | `TransformedTokens` | All tokens, still in unflattened object format. |
+| `args.dictionary.unfilteredAllTokens` | `TransformedToken[]` | Flattened array of all tokens, including tokens that were filtered out by filters. |
+| `args.dictionary.unfilteredTokens` | `TransformedTokens` | All tokens, still in unflattened object format, including tokens that were filtered out by filters. |
+| `args.platform` | `Platform` | [Platform config](/reference/config#platform) |
+| `args.file` | `File` | [File config](/reference/config#file) |
+| `args.options` | `Object` | Merged object with SD [Config](/reference/config#properties) & [FormatOptions](#format-configuration) |
Example:
diff --git a/docs/src/content/docs/reference/Hooks/Transforms/index.md b/docs/src/content/docs/reference/Hooks/Transforms/index.md
index 96906fea6..8fa28aed8 100644
--- a/docs/src/content/docs/reference/Hooks/Transforms/index.md
+++ b/docs/src/content/docs/reference/Hooks/Transforms/index.md
@@ -60,7 +60,7 @@ StyleDictionary.registerTransform({
type: `value`,
transitive: true,
name: `myTransitiveTransform`,
- filter: (token) => {},
+ filter: (token, options) => {},
transform: (token) => {
// token.value will be resolved and transformed at this point
},
diff --git a/docs/src/content/docs/reference/Hooks/filters.md b/docs/src/content/docs/reference/Hooks/filters.md
index 11c20421a..c985a6d2b 100644
--- a/docs/src/content/docs/reference/Hooks/filters.md
+++ b/docs/src/content/docs/reference/Hooks/filters.md
@@ -16,13 +16,13 @@ Common use cases for filtering are:
A filter is an object with two props:
- `name`: the name of the filter
-- `filter`: a callback function that receives the `token` as argument and returns a boolean, `true` to include the token, `false` to exclude/filter it out. Can also be an async function.
+- `filter`: a callback function that receives the `token` as argument and returns a boolean, `true` to include the token, `false` to exclude/filter it out. Can also be an async function. Also has a second argument with the Style Dictionary options, which also contains the `tokens` object, `usesDTCG` option, etc.
```javascript title="my-filter.js"
const myFilter = {
name: 'my-filter',
// async is optional
- filter: async (token) => {
+ filter: async (token, options) => {
return !token.filePath.endsWith('core.json');
},
};
@@ -117,7 +117,7 @@ export default {
export default {
hooks: {
filters: {
- 'no-colors': (token) => {
+ 'no-colors': (token, options) => {
return token.type !== 'color';
},
},
diff --git a/examples/advanced/create-react-native-app/src/App.js b/examples/advanced/create-react-native-app/src/App.js
index 78a53bccc..a95e034df 100644
--- a/examples/advanced/create-react-native-app/src/App.js
+++ b/examples/advanced/create-react-native-app/src/App.js
@@ -8,6 +8,7 @@ export default function App() {
Testing! Testing!
All done!
+ {/* eslint-disable-next-line react/style-prop-object */}
);
diff --git a/lib/StyleDictionary.js b/lib/StyleDictionary.js
index 9909ea414..b8511044a 100644
--- a/lib/StyleDictionary.js
+++ b/lib/StyleDictionary.js
@@ -140,6 +140,8 @@ export default class StyleDictionary extends Register {
* @type {TransformedTokens}
*/
this.unfilteredTokens = {};
+ /** @type {TransformedToken[]} */
+ this.unfilteredAllTokens = [];
this.hasInitialized = new Promise((resolve) => {
this.hasInitializedResolve = resolve;
diff --git a/lib/buildFile.js b/lib/buildFile.js
index 6d766c057..711fa2ae6 100644
--- a/lib/buildFile.js
+++ b/lib/buildFile.js
@@ -15,6 +15,7 @@ import { dirname } from 'path-unified';
import chalk from 'chalk';
import { fs } from 'style-dictionary/fs';
import filterTokens from './filterTokens.js';
+import flattenTokens from './utils/flattenTokens.js';
import GroupMessages, { verbosityInfo } from './utils/groupMessages.js';
import createFormatArgs from './utils/createFormatArgs.js';
@@ -73,6 +74,7 @@ export default async function buildFile(file, platform = {}, dictionary, options
allTokens: filteredTokens.allTokens,
// keep the unfiltered tokens object for reference resolution
unfilteredTokens: dictionary.tokens,
+ unfilteredAllTokens: flattenTokens(dictionary.tokens, options.usesDtcg),
});
// if tokens object is empty, return without creating a file
diff --git a/lib/common/formatHelpers/fileHeader.js b/lib/common/formatHelpers/fileHeader.js
index a63da210b..52d8d0d57 100644
--- a/lib/common/formatHelpers/fileHeader.js
+++ b/lib/common/formatHelpers/fileHeader.js
@@ -15,6 +15,7 @@
* @typedef {import('../../../types/File.d.ts').File} File
* @typedef {import('../../../types/File.d.ts').FileHeader} FileHeader
* @typedef {import('../../../types/File.d.ts').FormattingOptions} Formatting
+ * @typedef {import('../../../types/Config.d.ts').Config} Config
*/
const lineSeparator = `\n`;
@@ -34,10 +35,11 @@ const defaultFormatting = {
* default file header.
* @memberof module:formatHelpers
* @name fileHeader
- * @param {Object} options
- * @param {File} [options.file] - The file object that is passed to the format.
- * @param {'short' | 'xml' | 'long'} [options.commentStyle] - The only options are 'short', 'xml' and 'long', which will use the // or \ or \/\* style comments respectively. Default fallback is 'long'.
- * @param {Formatting} [options.formatting] - Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer.
+ * @param {Object} opts
+ * @param {File} [opts.file] - The file object that is passed to the format.
+ * @param {'short' | 'xml' | 'long'} [opts.commentStyle] - The only options are 'short', 'xml' and 'long', which will use the // or \ or \/\* style comments respectively. Default fallback is 'long'.
+ * @param {Formatting} [opts.formatting] - Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer.
+ * @param {Config} [opts.options]
* @returns {Promise}
* @example
* ```js
@@ -51,7 +53,7 @@ const defaultFormatting = {
* });
* ```
*/
-export default async function fileHeader({ file, commentStyle, formatting = {} }) {
+export default async function fileHeader({ file, commentStyle, formatting = {}, options = {} }) {
// showFileHeader is true by default
let showFileHeader = true;
if (typeof file?.options?.showFileHeader !== 'undefined') {
@@ -91,7 +93,7 @@ export default async function fileHeader({ file, commentStyle, formatting = {} }
footer = `${lineSeparator}-->`;
}
- const headerContent = await fn(defaultHeader);
+ const headerContent = await fn(defaultHeader, options);
return `${header}${headerContent
.map(/** @param {string} line */ (line) => `${prefix}${line}`)
diff --git a/lib/common/formats.js b/lib/common/formats.js
index 0734654b1..4e496fb73 100644
--- a/lib/common/formats.js
+++ b/lib/common/formats.js
@@ -93,6 +93,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -131,6 +132,7 @@ const formats = {
file,
commentStyle: 'long',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return scssMapFlat({ allTokens, options, header });
},
@@ -164,6 +166,7 @@ const formats = {
file,
commentStyle: 'long',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
'\n' +
@@ -200,6 +203,7 @@ const formats = {
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -232,6 +236,7 @@ const formats = {
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return header + iconsWithPrefix('$', dictionary.allTokens, options, platform);
},
@@ -253,6 +258,7 @@ const formats = {
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -278,6 +284,7 @@ const formats = {
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return header + iconsWithPrefix('@', dictionary.allTokens, options, platform);
},
@@ -300,6 +307,7 @@ const formats = {
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -331,6 +339,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return header + 'module.exports = ' + JSON.stringify(dictionary.tokens, null, 2) + ';\n';
},
@@ -352,6 +361,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -393,6 +403,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -440,6 +451,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -500,6 +512,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -556,6 +569,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return (
header +
@@ -667,6 +681,7 @@ const formats = {
const header = await fileHeader({
file,
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
const output =
header +
@@ -711,6 +726,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return androidResources({ dictionary, file, header, options });
},
@@ -745,6 +761,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return androidColors({ dictionary, options, header });
},
@@ -779,6 +796,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return androidDimens({ dictionary, options, header });
},
@@ -813,6 +831,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return androidFontDimens({ dictionary, options, header });
},
@@ -849,6 +868,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return androidIntegers({ dictionary, options, header });
},
@@ -884,6 +904,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return androidStrings({ dictionary, options, header });
},
@@ -938,6 +959,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return composeObject({ allTokens: sortedTokens, options, formatProperty, header });
},
@@ -964,6 +986,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return macrosTemplate({ dictionary, options, file, header });
},
@@ -981,6 +1004,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'xml',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return plistTemplate({ dictionary, options, header });
},
@@ -998,6 +1022,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosSingletonM({ dictionary, options, file, header });
},
@@ -1015,6 +1040,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosSingletonH({ file, options, header });
},
@@ -1032,6 +1058,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosStaticH({ dictionary, file, options, header });
},
@@ -1049,6 +1076,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosStaticM({ dictionary, options, file, header });
},
@@ -1066,6 +1094,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosColorsH({ dictionary, file, options, header });
},
@@ -1083,6 +1112,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosColorsM({ dictionary, options, file, header });
},
@@ -1100,6 +1130,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosStringsH({ dictionary, file, options, header });
},
@@ -1117,6 +1148,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosStringsM({ dictionary, options, file, header });
},
@@ -1164,6 +1196,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosSwiftAny({ allTokens: sortedTokens, file, options, formatProperty, header });
},
@@ -1210,6 +1243,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosSwiftAny({ allTokens: sortedTokens, file, options, formatProperty, header });
},
@@ -1267,6 +1301,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return iosSwiftAny({ allTokens: sortedTokens, file, options, formatProperty, header });
},
@@ -1489,6 +1524,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
file,
commentStyle: 'short',
formatting: getFormattingCloneWithoutPrefix(formatting),
+ options,
});
return flutterClassDart({ allTokens: sortedTokens, file, options, formatProperty, header });
},
diff --git a/lib/filterTokens.js b/lib/filterTokens.js
index 73fc608aa..fea6a0f63 100644
--- a/lib/filterTokens.js
+++ b/lib/filterTokens.js
@@ -23,9 +23,10 @@ import isPlainObject from 'is-plain-obj';
/**
* @param {Token[]} arr
* @param {Filter['filter']} predicate
+ * @param {Config} options
*/
-async function asyncFilter(arr, predicate) {
- return Promise.all(arr.map(predicate)).then((results) =>
+async function asyncFilter(arr, predicate, options) {
+ return Promise.all(arr.map((token) => predicate(token, options))).then((results) =>
arr.filter((_, index) => results[index]),
);
}
@@ -55,7 +56,7 @@ async function filterTokenObject(tokens, filter, options) {
// the filter function and either include it in the final `acc` object or
// exclude it (by returning the `acc` object without it added).
} else if (typeof tokenValue !== 'undefined') {
- const filtered = await asyncFilter(/** @type {Token[]} */ ([token]), filter);
+ const filtered = await asyncFilter(/** @type {Token[]} */ ([token]), filter, options);
return filtered.length === 0 ? acc : { ...acc, [key]: token };
// If we got here we have an object that is not a property. We'll assume
// it's an object containing multiple tokens and recursively filter it
@@ -91,7 +92,7 @@ export default async function filterTokens(dictionary, filter, options = {}) {
if (typeof filter !== 'function') {
throw new Error('filter is not a function');
} else {
- const allTokens = await asyncFilter(dictionary.allTokens ?? [], filter);
+ const allTokens = await asyncFilter(dictionary.allTokens ?? [], filter, options);
const tokens = await filterTokenObject(dictionary.tokens, filter, options);
return {
diff --git a/lib/transform/token.js b/lib/transform/token.js
index fedab0442..09d71ffeb 100644
--- a/lib/transform/token.js
+++ b/lib/transform/token.js
@@ -40,7 +40,7 @@ export default async function transformToken(token, config, options, vol) {
for (let i = 0; i < transforms.length; i++) {
const transform = transforms[i];
- if (!transform.filter || transform.filter(to_ret)) {
+ if (!transform.filter || transform.filter(to_ret, options)) {
if (transform.type === 'name') {
to_ret.name = await /** @type {Omit} */ (transform).transform(
to_ret,
diff --git a/lib/utils/createFormatArgs.js b/lib/utils/createFormatArgs.js
index e68b6dff0..c837d2845 100644
--- a/lib/utils/createFormatArgs.js
+++ b/lib/utils/createFormatArgs.js
@@ -42,6 +42,7 @@ export default function createFormatArgs({ dictionary, platform, options, file }
platform,
file,
options: {
+ ...options,
...(file.options || {}),
usesDtcg: options?.usesDtcg ?? false,
},
diff --git a/types/DesignToken.d.ts b/types/DesignToken.d.ts
index 4a5b8c323..163b893be 100644
--- a/types/DesignToken.d.ts
+++ b/types/DesignToken.d.ts
@@ -65,4 +65,5 @@ export interface Dictionary {
tokens: TransformedTokens;
allTokens: TransformedToken[];
unfilteredTokens?: TransformedTokens;
+ unfilteredAllTokens?: TransformedToken[];
}
diff --git a/types/File.d.ts b/types/File.d.ts
index d974cdbc5..b87c49d32 100644
--- a/types/File.d.ts
+++ b/types/File.d.ts
@@ -1,6 +1,6 @@
import type { TransformedToken } from './DesignToken.d.ts';
import type { FormatFn } from './Format.d.ts';
-import type { LocalOptions } from './Config.d.ts';
+import type { LocalOptions, Config } from './Config.d.ts';
import type { Filter } from './Filter.d.ts';
export interface FormattingOptions {
@@ -16,7 +16,10 @@ export interface FormattingOptions {
fileHeaderTimestamp?: boolean;
}
-export type FileHeader = (defaultMessage: string[]) => Promise | string[];
+export type FileHeader = (
+ defaultMessage: string[],
+ options?: Config,
+) => Promise | string[];
export interface File {
destination: string;
diff --git a/types/Filter.d.ts b/types/Filter.d.ts
index 9d5cac918..4a6b6ef56 100644
--- a/types/Filter.d.ts
+++ b/types/Filter.d.ts
@@ -11,8 +11,9 @@
* and limitations under the License.
*/
import type { TransformedToken } from './DesignToken.d.ts';
+import type { Config } from './Config.d.ts';
export interface Filter {
name: string;
- filter: (token: TransformedToken) => boolean | Promise;
+ filter: (token: TransformedToken, options: Config) => boolean | Promise;
}