createConverterCache() — tailwindcss Function Reference
Architecture documentation for the createConverterCache() function in canonicalize-candidates.ts from the tailwindcss codebase.
Entity Profile
Dependency Diagram
graph TD 3a7318a6_ec18_9d9c_0667_804b7d2f542d["createConverterCache()"] 20406e7c_6ee8_4626_dbef_5b37708f4d30["prepareDesignSystemStorage()"] 20406e7c_6ee8_4626_dbef_5b37708f4d30 -->|calls| 3a7318a6_ec18_9d9c_0667_804b7d2f542d 1e85b11a_69b5_68fc_237d_f0167751c10b["substituteFunctionsInValue()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| 1e85b11a_69b5_68fc_237d_f0167751c10b 2a20ea29_c850_cd61_5600_aeebbe3dda66["segment()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| 2a20ea29_c850_cd61_5600_aeebbe3dda66 971f7bc7_6ac2_a554_ba52_47038ff41b13["keyPathToCssProperty()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| 971f7bc7_6ac2_a554_ba52_47038ff41b13 f1189154_e89f_8988_3e83_53458fbcad21["toKeyPath()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| f1189154_e89f_8988_3e83_53458fbcad21 c12acffb_80f9_0b95_b1a6_e663fbaca197["isValidSpacingMultiplier()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| c12acffb_80f9_0b95_b1a6_e663fbaca197 d2ce75c7_eb19_6cb1_229b_297218cbe158["walk()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| d2ce75c7_eb19_6cb1_229b_297218cbe158 4cd99e59_ac1e_2a1f_0946_33cc1afd2532["get()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| 4cd99e59_ac1e_2a1f_0946_33cc1afd2532 cb368927_d6ec_d016_7fb3_2ea287d31108["parse()"] 3a7318a6_ec18_9d9c_0667_804b7d2f542d -->|calls| cb368927_d6ec_d016_7fb3_2ea287d31108 style 3a7318a6_ec18_9d9c_0667_804b7d2f542d fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
packages/tailwindcss/src/canonicalize-candidates.ts lines 640–799
function createConverterCache(
designSystem: DesignSystem,
): DesignSystem['storage'][typeof CONVERTER_KEY] {
return createConverter(designSystem)
function createConverter(designSystem: DesignSystem) {
function convert(input: string, options = Convert.All): [string, CandidateModifier | null] {
let ast = ValueParser.parse(input)
// In some scenarios (e.g.: variants), we can't migrate to `var(…)` if it
// ends up in the `@media (…)` part. In this case we only have to migrate to
// the new `theme(…)` notation.
if (options & Convert.MigrateThemeOnly) {
return [substituteFunctionsInValue(ast, toTheme), null]
}
let themeUsageCount = 0
let themeModifierCount = 0
// Analyze AST
walk(ast, (node) => {
if (node.kind !== 'function') return
if (node.value !== 'theme') return
// We are only interested in the `theme` function
themeUsageCount += 1
// Figure out if a modifier is used
walk(node.nodes, (child) => {
// If we see a `,`, it means that we have a fallback value
if (child.kind === 'separator' && child.value.includes(',')) {
return WalkAction.Stop
}
// If we see a `/`, we have a modifier
else if (child.kind === 'word' && child.value === '/') {
themeModifierCount += 1
return WalkAction.Stop
}
return WalkAction.Skip
})
})
// No `theme(…)` calls, nothing to do
if (themeUsageCount === 0) {
return [input, null]
}
// No `theme(…)` with modifiers, we can migrate to `var(…)`
if (themeModifierCount === 0) {
return [substituteFunctionsInValue(ast, toVar), null]
}
// Multiple modifiers which means that there are multiple `theme(…/…)`
// values. In this case, we can't convert the modifier to a candidate
// modifier.
//
// We also can't migrate to `var(…)` because that would lose the modifier.
//
// Try to convert each `theme(…)` call to the modern syntax.
if (themeModifierCount > 1) {
return [substituteFunctionsInValue(ast, toTheme), null]
}
// Only a single `theme(…)` with a modifier left, that modifier will be
// migrated to a candidate modifier.
let modifier: CandidateModifier | null = null
let result = substituteFunctionsInValue(ast, (path, fallback) => {
let parts = segment(path, '/').map((part) => part.trim())
// Multiple `/` separators, which makes this an invalid path
if (parts.length > 2) return null
// The path contains a `/`, which means that there is a modifier such as
// `theme(colors.red.500/50%)`.
//
// Currently, we are assuming that this is only being used for colors,
// which means that we can typically convert them to a modifier on the
// candidate itself.
//
// If there is more than one node in the AST though, `theme(…)` must not
// be the whole value so it's not safe to use a modifier instead.
//
// E.g.: `inset 0px 1px theme(colors.red.500/50%)` is a shadow, not a color.
if (ast.length === 1 && parts.length === 2 && options & Convert.MigrateModifier) {
let [pathPart, modifierPart] = parts
// 50% -> /50
if (/^\d+%$/.test(modifierPart)) {
modifier = { kind: 'named', value: modifierPart.slice(0, -1) }
}
// .12 -> /12
// .12345 -> /[12.345]
else if (/^0?\.\d+$/.test(modifierPart)) {
let value = Number(modifierPart) * 100
modifier = {
kind: Number.isInteger(value) ? 'named' : 'arbitrary',
value: value.toString(),
}
}
// Anything else becomes arbitrary
else {
modifier = { kind: 'arbitrary', value: modifierPart }
}
// Update path to be the first part
path = pathPart
}
return toVar(path, fallback) || toTheme(path, fallback)
})
return [result, modifier]
}
function pathToVariableName(path: string, shouldPrefix = true) {
let variable = `--${keyPathToCssProperty(toKeyPath(path))}` as const
if (!designSystem.theme.get([variable])) return null
if (shouldPrefix && designSystem.theme.prefix) {
return `--${designSystem.theme.prefix}-${variable.slice(2)}`
}
return variable
}
function toVar(path: string, fallback?: string) {
let variable = pathToVariableName(path)
if (variable) return fallback ? `var(${variable}, ${fallback})` : `var(${variable})`
let keyPath = toKeyPath(path)
if (keyPath[0] === 'spacing' && designSystem.theme.get(['--spacing'])) {
let multiplier = keyPath[1]
if (!isValidSpacingMultiplier(multiplier)) return null
return `--spacing(${multiplier})`
}
return null
}
function toTheme(path: string, fallback?: string) {
let parts = segment(path, '/').map((part) => part.trim())
path = parts.shift()!
let variable = pathToVariableName(path, false)
if (!variable) return null
let modifier = parts.length > 0 ? `/${parts.join('/')}` : ''
return fallback
? `--theme(${variable}${modifier}, ${fallback})`
: `--theme(${variable}${modifier})`
}
return convert
}
}
Domain
Subdomains
Calls
Called By
Source
Frequently Asked Questions
What does createConverterCache() do?
createConverterCache() is a function in the tailwindcss codebase.
What does createConverterCache() call?
createConverterCache() calls 8 function(s): get, isValidSpacingMultiplier, keyPathToCssProperty, parse, segment, substituteFunctionsInValue, toKeyPath, walk.
What calls createConverterCache()?
createConverterCache() is called by 1 function(s): prepareDesignSystemStorage.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free