From a5305aa84ee82f5f0ed78ab6c36cd211d791c0b3 Mon Sep 17 00:00:00 2001 From: Adam Wathan <4323180+adamwathan@users.noreply.github.com> Date: Wed, 14 Jun 2023 09:40:04 -0400 Subject: [PATCH] Super hacky POC --- src/lib/setupTrackingContext.js | 15 ++++++++----- src/plugin.js | 21 ++++++++++++++++++- tests/css-configuration.test.js | 37 +++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 tests/css-configuration.test.js diff --git a/src/lib/setupTrackingContext.js b/src/lib/setupTrackingContext.js index 70e7cb684..419dd8594 100644 --- a/src/lib/setupTrackingContext.js +++ b/src/lib/setupTrackingContext.js @@ -28,7 +28,7 @@ function getCandidateFiles(context, tailwindConfig) { } // Get the config object based on a path -function getTailwindConfig(configOrPath) { +function getTailwindConfig(configOrPath, cssThemeValues) { let userConfigPath = resolveConfigPath(configOrPath) if (userConfigPath !== null) { @@ -56,14 +56,19 @@ function getTailwindConfig(configOrPath) { for (let file of newDeps) { delete require.cache[file] } - let newConfig = validateConfig(resolveConfig(loadConfig(userConfigPath))) + let newConfig = validateConfig( + resolveConfig({ theme: cssThemeValues }, loadConfig(userConfigPath)) + ) let newHash = hash(newConfig) configPathCache.set(userConfigPath, [newConfig, newHash, newDeps, newModified]) return [newConfig, userConfigPath, newHash, newDeps] } // It's a plain object, not a path - let newConfig = resolveConfig(configOrPath?.config ?? configOrPath ?? {}) + let newConfig = resolveConfig( + { theme: cssThemeValues }, + configOrPath?.config ?? configOrPath ?? {} + ) newConfig = validateConfig(newConfig) @@ -75,11 +80,11 @@ function getTailwindConfig(configOrPath) { // Retrieve an existing context from cache if possible (since contexts are unique per // source path), or set up a new one (including setting up watchers and registering // plugins) then return it -export default function setupTrackingContext(configOrPath) { +export default function setupTrackingContext(configOrPath, cssThemeValues) { return ({ tailwindDirectives, registerDependency }) => { return (root, result) => { let [tailwindConfig, userConfigPath, tailwindConfigHash, configDependencies] = - getTailwindConfig(configOrPath) + getTailwindConfig(configOrPath, cssThemeValues) let contextDependencies = new Set(configDependencies) diff --git a/src/plugin.js b/src/plugin.js index 9efabde34..d617b55cf 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -23,7 +23,26 @@ module.exports = function tailwindcss(configOrPath) { // path for the file being processed configOrPath = findAtConfigPath(root, result) ?? configOrPath - let context = setupTrackingContext(configOrPath) + // Begin CSS-first theme configuration proof-of-concept + let themeValues = { extend: { colors: {} } } + + root.each((node) => { + if (node.type === 'rule' && node.selector === ':theme') { + // Walk :theme pseudo and extract values + node.walkDecls((decl) => { + if (decl.prop.startsWith('--colors-')) { + themeValues.extend.colors[decl.prop.slice(9)] = decl.value + } + }) + + node.remove() + } + }) + + // context.tailwindConfig.theme + // End CSS-first theme configuration proof-of-concept + + let context = setupTrackingContext(configOrPath, themeValues) if (root.type === 'document') { let roots = root.nodes.filter((node) => node.type === 'root') diff --git a/tests/css-configuration.test.js b/tests/css-configuration.test.js new file mode 100644 index 000000000..470801809 --- /dev/null +++ b/tests/css-configuration.test.js @@ -0,0 +1,37 @@ +import { run, html, css } from './util/run' + +test('it does something', () => { + let config = { + darkMode: 'class', + content: [ + { + raw: html` +
+
+ `, + }, + ], + } + + return run( + css` + @tailwind utilities; + + :theme { + --colors-potato: #facade; + } + `, + config + ).then((result) => { + expect(result.css).toMatchFormattedCss(css` + .text-black { + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); + } + .text-potato { + --tw-text-opacity: 1; + color: rgb(250 202 222 / var(--tw-text-opacity)); + } + `) + }) +})