applyCompatibilityHooks() — tailwindcss Function Reference
Architecture documentation for the applyCompatibilityHooks() function in apply-compat-hooks.ts from the tailwindcss codebase.
Entity Profile
Dependency Diagram
graph TD d0cd8e91_7dbc_4e3d_f621_705d53f7a49e["applyCompatibilityHooks()"] 95cb326e_6b59_0903_0c96_d221fca5c2b1["parseCss()"] 95cb326e_6b59_0903_0c96_d221fca5c2b1 -->|calls| d0cd8e91_7dbc_4e3d_f621_705d53f7a49e 4883e410_7ef0_3846_5ee9_bba194796fa1["cssContext()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| 4883e410_7ef0_3846_5ee9_bba194796fa1 e7a34553_0273_6202_4792_07409e33d8f0["toCss()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| e7a34553_0273_6202_4792_07409e33d8f0 03b8d706_a876_a776_0056_186ced5d6067["segment()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| 03b8d706_a876_a776_0056_186ced5d6067 63b9a37b_6501_bf25_410b_7f820a1f3a11["registerLegacyUtilities()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| 63b9a37b_6501_bf25_410b_7f820a1f3a11 4b7a4cd6_9f02_0b91_8991_3889a44cd62f["resolveThemeValue()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| 4b7a4cd6_9f02_0b91_8991_3889a44cd62f 9056089b_151f_3027_844b_242ce55294db["upgradeToFullPluginSupport()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| 9056089b_151f_3027_844b_242ce55294db a32bba76_f60d_883f_1ff1_276a0bb9db9f["walk()"] d0cd8e91_7dbc_4e3d_f621_705d53f7a49e -->|calls| a32bba76_f60d_883f_1ff1_276a0bb9db9f style d0cd8e91_7dbc_4e3d_f621_705d53f7a49e fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
packages/tailwindcss/src/compat/apply-compat-hooks.ts lines 21–215
export async function applyCompatibilityHooks({
designSystem,
base,
ast,
loadModule,
sources,
}: {
designSystem: DesignSystem
base: string
ast: AstNode[]
loadModule: (
path: string,
base: string,
resourceHint: 'plugin' | 'config',
) => Promise<{
path: string
base: string
module: any
}>
sources: { base: string; pattern: string; negated: boolean }[]
}) {
let features = Features.None
let pluginPaths: [
{ id: string; base: string; reference: boolean; src: SourceLocation | undefined },
CssPluginOptions | null,
][] = []
let configPaths: {
id: string
base: string
reference: boolean
src: SourceLocation | undefined
}[] = []
walk(ast, (node, _ctx) => {
if (node.kind !== 'at-rule') return
let ctx = cssContext(_ctx)
// Collect paths from `@plugin` at-rules
if (node.name === '@plugin') {
if (ctx.parent !== null) {
throw new Error('`@plugin` cannot be nested.')
}
let pluginPath = node.params.slice(1, -1)
if (pluginPath.length === 0) {
throw new Error('`@plugin` must have a path.')
}
let options: CssPluginOptions = {}
for (let decl of node.nodes ?? []) {
if (decl.kind !== 'declaration') {
throw new Error(
`Unexpected \`@plugin\` option:\n\n${toCss([decl])}\n\n\`@plugin\` options must be a flat list of declarations.`,
)
}
if (decl.value === undefined) continue
// Parse the declaration value as a primitive type
// These are the same primitive values supported by JSON
let value: CssPluginOptions[keyof CssPluginOptions] = decl.value
let parts = segment(value, ',').map((part) => {
part = part.trim()
if (part === 'null') {
return null
} else if (part === 'true') {
return true
} else if (part === 'false') {
return false
} else if (!Number.isNaN(Number(part))) {
return Number(part)
} else if (
(part[0] === '"' && part[part.length - 1] === '"') ||
(part[0] === "'" && part[part.length - 1] === "'")
) {
return part.slice(1, -1)
} else if (part[0] === '{' && part[part.length - 1] === '}') {
throw new Error(
`Unexpected \`@plugin\` option: Value of declaration \`${toCss([decl]).trim()}\` is not supported.\n\nUsing an object as a plugin option is currently only supported in JavaScript configuration files.`,
)
}
return part
})
options[decl.property] = parts.length === 1 ? parts[0] : parts
}
pluginPaths.push([
{
id: pluginPath,
base: ctx.context.base as string,
reference: !!ctx.context.reference,
src: node.src,
},
Object.keys(options).length > 0 ? options : null,
])
features |= Features.JsPluginCompat
return WalkAction.Replace([])
}
// Collect paths from `@config` at-rules
if (node.name === '@config') {
if (node.nodes.length > 0) {
throw new Error('`@config` cannot have a body.')
}
if (ctx.parent !== null) {
throw new Error('`@config` cannot be nested.')
}
configPaths.push({
id: node.params.slice(1, -1),
base: ctx.context.base as string,
reference: !!ctx.context.reference,
src: node.src,
})
features |= Features.JsPluginCompat
return WalkAction.Replace([])
}
})
registerLegacyUtilities(designSystem)
// Override `resolveThemeValue` with a version that is backwards compatible
// with dot notation paths like `colors.red.500`. We could do this by default
// in `resolveThemeValue` but handling it here keeps all backwards
// compatibility concerns localized to our compatibility layer.
let resolveThemeVariableValue = designSystem.resolveThemeValue
designSystem.resolveThemeValue = function resolveThemeValue(path: string, forceInline?: boolean) {
if (path.startsWith('--')) {
return resolveThemeVariableValue(path, forceInline)
}
// If the theme value is not found in the simple resolver, we upgrade to the full backward
// compatibility support implementation of the `resolveThemeValue` function.
features |= upgradeToFullPluginSupport({
designSystem,
base,
ast,
sources,
configs: [],
pluginDetails: [],
})
return designSystem.resolveThemeValue(path, forceInline)
}
// If there are no plugins or configs registered, we don't need to register
// any additional backwards compatibility hooks.
if (!pluginPaths.length && !configPaths.length) return Features.None
let [configs, pluginDetails] = await Promise.all([
Promise.all(
configPaths.map(async ({ id, base, reference, src }) => {
let loaded = await loadModule(id, base, 'config')
return {
path: id,
base: loaded.base,
config: loaded.module as UserConfig,
reference,
src,
}
}),
),
Promise.all(
pluginPaths.map(async ([{ id, base, reference, src }, pluginOptions]) => {
let loaded = await loadModule(id, base, 'plugin')
return {
path: id,
base: loaded.base,
plugin: loaded.module as Plugin,
options: pluginOptions,
reference,
src,
}
}),
),
])
features |= upgradeToFullPluginSupport({
designSystem,
base,
ast,
sources,
configs,
pluginDetails,
})
return features
}
Domain
Subdomains
Calls
Called By
Source
Frequently Asked Questions
What does applyCompatibilityHooks() do?
applyCompatibilityHooks() is a function in the tailwindcss codebase.
What does applyCompatibilityHooks() call?
applyCompatibilityHooks() calls 7 function(s): cssContext, registerLegacyUtilities, resolveThemeValue, segment, toCss, upgradeToFullPluginSupport, walk.
What calls applyCompatibilityHooks()?
applyCompatibilityHooks() is called by 1 function(s): parseCss.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free