sd.config.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* eslint-disable @typescript-eslint/no-var-requires */
  2. const { template, camelCase } = require('lodash')
  3. const variablesTemplate = template(`import { css } from '@emotion/react'
  4. export const variables = css\`
  5. :root {
  6. <%= cssVariables %>
  7. }\`
  8. export const theme = {
  9. <%= themeVariables %>
  10. }
  11. export const cVar = (key: keyof typeof theme, returnValue?: boolean) => {
  12. if (returnValue) return theme[key].value
  13. return theme[key].variable
  14. }
  15. `)
  16. module.exports = {
  17. source: [`./src/styles/tokens/**/*.json`],
  18. parsers: [
  19. {
  20. pattern: /\.json$/,
  21. parse: ({ contents }) => {
  22. // style dictionary requires adding ".value" suffix to all referenced value, e.g. "value": "{core.neutral.default.900}" should be e.g. "value": "{core.neutral.default.900.value}"
  23. // this parser should fix it, although it just a workaround
  24. // we could remove this when they do something about it https://github.com/amzn/style-dictionary/issues/721
  25. const parsed = contents.replace(/}"|\.value}"/g, `.value}"`)
  26. return JSON.parse(parsed)
  27. },
  28. },
  29. ],
  30. transform: {
  31. removeDefaultFromName: {
  32. type: 'name',
  33. transformer: (token) => token.name.replace(/-default|-regular/g, ''),
  34. },
  35. easingTransform: {
  36. type: 'value',
  37. matcher: (token) => token.attributes.type === 'easing',
  38. // [1, 2, 3, 4] will become 1, 2, 3, 4
  39. transformer: (token) => `cubic-bezier(${token.value.toString().replace(/\[|\]/g, '')})`,
  40. },
  41. transitionTransform: {
  42. type: 'value',
  43. transitive: true,
  44. matcher: (token) => token.attributes.type === 'transition',
  45. transformer: (token) => `${token.value.timing} ${token.value.easing}`,
  46. },
  47. typographyValueTransform: {
  48. type: 'value',
  49. transitive: true,
  50. matcher: (token) => token.attributes.type === 'textStyles',
  51. transformer: (token) =>
  52. `${token.value.fontWeight} ${token.value.fontSize}/${token.value.lineHeight} ${token.value.fontFamily}`,
  53. },
  54. typographyNameTransform: {
  55. type: 'name',
  56. matcher: (token) => token.attributes.type === 'textStyles',
  57. transformer: (token) => token.name.replace(/-heading|-text|-styles/g, ''),
  58. },
  59. effectsTransform: {
  60. type: 'value',
  61. transitive: true,
  62. matcher: (token) => token.attributes.category === 'effect',
  63. transformer: (token) => {
  64. const isDivider = token.attributes.type === 'dividers'
  65. return `${isDivider ? 'inset' : ''} ${token.value.x} ${token.value.y} ${token.value.blur} ${
  66. token.value.spread
  67. } ${token.value.color}`
  68. },
  69. },
  70. },
  71. format: {
  72. customFormat: ({ dictionary }) => {
  73. // create new tokens for letter-spacing
  74. const allTokens = dictionary.allTokens
  75. const letterSpacingTokens = allTokens
  76. .filter((token) => token.attributes.type === 'textStyles')
  77. .map((token) => ({
  78. ...token,
  79. value: token.original.value.letterSpacing || 0,
  80. name: `${token.name}-letter-spacing`,
  81. }))
  82. // create new tokens for text-transform
  83. const textTransformTokens = allTokens
  84. .filter((token) => token.attributes.type === 'textStyles')
  85. .map((token) => ({
  86. ...token,
  87. value: token.original.value.textTransform || 'none',
  88. name: `${token.name}-text-transform`,
  89. }))
  90. const convertedTokens = [...allTokens, ...letterSpacingTokens, ...textTransformTokens]
  91. return variablesTemplate({
  92. cssVariables: convertedTokens
  93. .map((token) => {
  94. let keyValuePair = `--${token.name}: ${token.value};`
  95. if (dictionary.usesReference(token.original.value)) {
  96. const refs = dictionary.getReferences(token.original.value)
  97. refs.forEach((ref) => {
  98. const [key, value] = keyValuePair.split(':')
  99. const modifiedValue = value.replace(ref.value, `var(--${ref.name})`)
  100. keyValuePair = `${key}:${modifiedValue}`
  101. })
  102. }
  103. return keyValuePair
  104. })
  105. .join('\n'),
  106. themeVariables: convertedTokens
  107. .map((token) => `${camelCase(token.name)}: { variable: 'var(--${token.name})', value: '${token.value}' },`)
  108. .join('\n'),
  109. })
  110. },
  111. },
  112. platforms: {
  113. ts: {
  114. transforms: [
  115. `attribute/cti`,
  116. `name/cti/kebab`,
  117. 'removeDefaultFromName',
  118. 'typographyValueTransform',
  119. 'typographyNameTransform',
  120. 'easingTransform',
  121. 'transitionTransform',
  122. 'effectsTransform',
  123. ],
  124. buildPath: 'src/styles/generated/',
  125. files: [
  126. {
  127. destination: 'variables.ts',
  128. format: 'customFormat',
  129. filter: (token) => token.type !== 'typedef',
  130. options: {
  131. outputReferences: true,
  132. },
  133. },
  134. ],
  135. },
  136. },
  137. }