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 { 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 } }