tailwindcss/packages/@tailwindcss-node/src/compile.ts
Philipp Spiess 390e2d3e8d
Allow @plugin and @config to point to TS files (#14317)
Tailwind V3 used [jiti](https://github.com/unjs/jiti/) to allow
importing of TypeScript files for the config and plugins. This PR adds
the new Jiti V2 beta to our `@tailwindcss/node` and uses it if a native
`import()` fails. I added a new integration test to the CLI config
setup, to ensure it still works with our module cache cleanup.
2024-09-03 18:35:39 +02:00

64 lines
2 KiB
TypeScript

import { createJiti, type Jiti } from 'jiti'
import path from 'node:path'
import { pathToFileURL } from 'node:url'
import { compile as _compile } from 'tailwindcss'
import { getModuleDependencies } from './get-module-dependencies'
export async function compile(
css: string,
{ base, onDependency }: { base: string; onDependency: (path: string) => void },
) {
return await _compile(css, {
loadPlugin: async (pluginPath) => {
if (pluginPath[0] !== '.') {
return importModule(pluginPath).then((m) => m.default ?? m)
}
let resolvedPath = path.resolve(base, pluginPath)
let [module, moduleDependencies] = await Promise.all([
importModule(pathToFileURL(resolvedPath).href + '?id=' + Date.now()),
getModuleDependencies(resolvedPath),
])
onDependency(resolvedPath)
for (let file of moduleDependencies) {
onDependency(file)
}
return module.default ?? module
},
loadConfig: async (configPath) => {
if (configPath[0] !== '.') {
return importModule(configPath).then((m) => m.default ?? m)
}
let resolvedPath = path.resolve(base, configPath)
let [module, moduleDependencies] = await Promise.all([
importModule(pathToFileURL(resolvedPath).href + '?id=' + Date.now()),
getModuleDependencies(resolvedPath),
])
onDependency(resolvedPath)
for (let file of moduleDependencies) {
onDependency(file)
}
return module.default ?? module
},
})
}
// Attempts to import the module using the native `import()` function. If this
// fails, it sets up `jiti` and attempts to import this way so that `.ts` files
// can be resolved properly.
let jiti: null | Jiti = null
async function importModule(path: string): Promise<any> {
try {
return await import(path)
} catch (error) {
try {
jiti ??= createJiti(import.meta.url, { moduleCache: false, fsCache: false })
return await jiti.import(path)
} catch {}
throw error
}
}