From e981b4235e15cb49a020563343feafcf0393a083 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 6 Sep 2024 17:39:37 -0400 Subject: [PATCH 1/5] Support `@plugin` and `@config` in v4 --- src/config.ts | 53 ++++++++++++++++++++++++++++++++++++++++++++++---- src/resolve.ts | 3 +++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/config.ts b/src/config.ts index ee3294d9..d2195e06 100644 --- a/src/config.ts +++ b/src/config.ts @@ -18,7 +18,7 @@ import loadConfigFallback from 'tailwindcss/loadConfig' import resolveConfigFallback from 'tailwindcss/resolveConfig' import type { RequiredConfig } from 'tailwindcss/types/config.js' import { expiringMap } from './expiring-map.js' -import { resolveIn } from './resolve' +import { resolveFrom, resolveIn } from './resolve' import type { ContextContainer } from './types' let localRequire = createRequire(import.meta.url) @@ -147,6 +147,37 @@ async function loadTailwindConfig( } } +/** + * Create a loader function that can load plugins and config files relative to + * the CSS file that uses them. However, we don't want missing files to prevent + * everything from working so we'll let the error handler decide how to proceed. + * + * @param {object} param0 + * @returns + */ +function createLoader({ + filepath, + onError, +}: { + filepath: string + onError: (id: string, error: unknown) => T +}) { + let baseDir = path.dirname(filepath) + let cacheKey = `${+Date.now()}` + + return async function loadFile(id: string) { + try { + let resolved = resolveFrom(baseDir, id) + let url = pathToFileURL(resolved) + url.searchParams.append('t', cacheKey) + + return await import(url.href).then((m) => m.default ?? m) + } catch (err) { + return onError(id, err) + } + } +} + async function loadV4( baseDir: string, pkgDir: string, @@ -172,9 +203,23 @@ async function loadV4( // Load the design system and set up a compatible context object that is // usable by the rest of the plugin let design = await tw.__unstable__loadDesignSystem(result.css, { - loadPlugin() { - return () => {} - }, + loadPlugin: createLoader({ + filepath: entryPoint, + onError(id, err) { + console.error(`Unable to load plugin: ${id}`, err) + + return () => {} + }, + }), + + loadConfig: createLoader({ + filepath: entryPoint, + onError(id, err) { + console.error(`Unable to load config: ${id}`, err) + + return {} + }, + }), }) return { diff --git a/src/resolve.ts b/src/resolve.ts index 80a095ff..00f5c08e 100644 --- a/src/resolve.ts +++ b/src/resolve.ts @@ -1,4 +1,5 @@ import { createRequire as req } from 'node:module' +import resolveFrom from 'resolve-from' import { expiringMap } from './expiring-map' const localRequire = req(import.meta.url) @@ -45,3 +46,5 @@ function freshMaybeResolve(name: string) { return null } } + +export { resolveFrom } From 4cb5831c86e3d970130996771931cdd83bd1e6b2 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 6 Sep 2024 17:48:13 -0400 Subject: [PATCH 2/5] Rework fixture installation script --- scripts/install-fixture-deps.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/scripts/install-fixture-deps.js b/scripts/install-fixture-deps.js index c79939d7..9103ba89 100644 --- a/scripts/install-fixture-deps.js +++ b/scripts/install-fixture-deps.js @@ -3,26 +3,23 @@ import * as fs from 'node:fs/promises' import * as path from 'node:path' import { fileURLToPath } from 'node:url' import { promisify } from 'node:util' - -const execAsync = promisify(exec) +import glob from 'fast-glob' const __dirname = path.dirname(fileURLToPath(import.meta.url)) -let fixturesDir = path.resolve(__dirname, '../tests/fixtures') -let fixtureDirs = await fs.readdir(fixturesDir) -let fixtures = fixtureDirs.map((name) => path.join(fixturesDir, name)) +const fixtures = glob.sync( + ['tests/fixtures/*/package.json', 'tests/fixtures/v4/*/package.json'], + { + cwd: path.resolve(__dirname, '..'), + }, +) + +const execAsync = promisify(exec) await Promise.all( fixtures.map(async (fixture) => { - let exists = await fs.access(path.join(fixture, 'package.json')).then( - () => true, - () => false, - ) - - if (!exists) return - console.log(`Installing dependencies for ${fixture}`) - await execAsync('npm install', { cwd: fixture }) + await execAsync('npm install', { cwd: path.dirname(fixture) }) }), ) From 413c68ba67d5209f3bbfb418ed49ab1208261755 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 6 Sep 2024 17:50:13 -0400 Subject: [PATCH 3/5] Add basic v4 test --- tests/fixtures.test.ts | 6 ++++++ tests/fixtures/v4/basic/app.css | 5 +++++ tests/fixtures/v4/basic/index.html | 1 + tests/fixtures/v4/basic/output.html | 1 + tests/fixtures/v4/basic/package-lock.json | 17 +++++++++++++++++ tests/fixtures/v4/basic/package.json | 8 ++++++++ 6 files changed, 38 insertions(+) create mode 100644 tests/fixtures/v4/basic/app.css create mode 100644 tests/fixtures/v4/basic/index.html create mode 100644 tests/fixtures/v4/basic/output.html create mode 100644 tests/fixtures/v4/basic/package-lock.json create mode 100644 tests/fixtures/v4/basic/package.json diff --git a/tests/fixtures.test.ts b/tests/fixtures.test.ts index 0cecbbd6..7e368763 100644 --- a/tests/fixtures.test.ts +++ b/tests/fixtures.test.ts @@ -62,6 +62,12 @@ let fixtures = [ dir: 'custom-jsx', ext: 'jsx', }, + + { + name: 'v4: basic formatting', + dir: 'v4/basic', + ext: 'html', + }, ] let configs = [ diff --git a/tests/fixtures/v4/basic/app.css b/tests/fixtures/v4/basic/app.css new file mode 100644 index 00000000..ac52a795 --- /dev/null +++ b/tests/fixtures/v4/basic/app.css @@ -0,0 +1,5 @@ +@import 'tailwindcss'; + +@theme { + --color-tomato: tomato; +} diff --git a/tests/fixtures/v4/basic/index.html b/tests/fixtures/v4/basic/index.html new file mode 100644 index 00000000..f7a76090 --- /dev/null +++ b/tests/fixtures/v4/basic/index.html @@ -0,0 +1 @@ +
diff --git a/tests/fixtures/v4/basic/output.html b/tests/fixtures/v4/basic/output.html new file mode 100644 index 00000000..8409de1a --- /dev/null +++ b/tests/fixtures/v4/basic/output.html @@ -0,0 +1 @@ +
diff --git a/tests/fixtures/v4/basic/package-lock.json b/tests/fixtures/v4/basic/package-lock.json new file mode 100644 index 00000000..04abdf83 --- /dev/null +++ b/tests/fixtures/v4/basic/package-lock.json @@ -0,0 +1,17 @@ +{ + "name": "basic", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "tailwindcss": "^4.0.0-alpha.23" + } + }, + "node_modules/tailwindcss": { + "version": "4.0.0-alpha.23", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.23.tgz", + "integrity": "sha512-5dy4L1icQUYkG2Fa427QG3fKGkNqMi6V4bJE0DoxBZkR4e550w7uxYJ7vBXINWrRmDd4LHmQInkgsHza3lwONg==" + } + } +} diff --git a/tests/fixtures/v4/basic/package.json b/tests/fixtures/v4/basic/package.json new file mode 100644 index 00000000..7f5a61c1 --- /dev/null +++ b/tests/fixtures/v4/basic/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "tailwindcss": "^4.0.0-alpha.23" + }, + "prettier": { + "tailwindEntryPoint": "./app.css" + } +} From 48e75fbbf9f3bc8b57a10dea3289402e6b02dc94 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 6 Sep 2024 17:56:31 -0400 Subject: [PATCH 4/5] Add v4 configs test --- tests/fixtures.test.ts | 5 +++++ tests/fixtures/v4/configs/app.css | 8 ++++++++ tests/fixtures/v4/configs/index.html | 3 +++ tests/fixtures/v4/configs/my-plugin.mjs | 13 +++++++++++++ tests/fixtures/v4/configs/output.html | 3 +++ tests/fixtures/v4/configs/package-lock.json | 17 +++++++++++++++++ tests/fixtures/v4/configs/package.json | 8 ++++++++ tests/fixtures/v4/configs/tailwind.config.mjs | 9 +++++++++ 8 files changed, 66 insertions(+) create mode 100644 tests/fixtures/v4/configs/app.css create mode 100644 tests/fixtures/v4/configs/index.html create mode 100644 tests/fixtures/v4/configs/my-plugin.mjs create mode 100644 tests/fixtures/v4/configs/output.html create mode 100644 tests/fixtures/v4/configs/package-lock.json create mode 100644 tests/fixtures/v4/configs/package.json create mode 100644 tests/fixtures/v4/configs/tailwind.config.mjs diff --git a/tests/fixtures.test.ts b/tests/fixtures.test.ts index 7e368763..e6d65826 100644 --- a/tests/fixtures.test.ts +++ b/tests/fixtures.test.ts @@ -68,6 +68,11 @@ let fixtures = [ dir: 'v4/basic', ext: 'html', }, + { + name: 'v4: configs and plugins', + dir: 'v4/configs', + ext: 'html', + }, ] let configs = [ diff --git a/tests/fixtures/v4/configs/app.css b/tests/fixtures/v4/configs/app.css new file mode 100644 index 00000000..bd6458d4 --- /dev/null +++ b/tests/fixtures/v4/configs/app.css @@ -0,0 +1,8 @@ +@import "tailwindcss"; + +@config "./tailwind.config.mjs"; +@plugin "./my-plugin.mjs"; + +@theme { + --color-tomato: tomato; +} diff --git a/tests/fixtures/v4/configs/index.html b/tests/fixtures/v4/configs/index.html new file mode 100644 index 00000000..296b7d7f --- /dev/null +++ b/tests/fixtures/v4/configs/index.html @@ -0,0 +1,3 @@ +
diff --git a/tests/fixtures/v4/configs/my-plugin.mjs b/tests/fixtures/v4/configs/my-plugin.mjs new file mode 100644 index 00000000..bbbd63db --- /dev/null +++ b/tests/fixtures/v4/configs/my-plugin.mjs @@ -0,0 +1,13 @@ +import plugin from 'tailwindcss/plugin' + +export default plugin(function ({ addUtilities }) { + addUtilities({ + '.from-plugin-1': { + width: '100%', + }, + '.from-plugin-2': { + color: 'red', + margin: '2rem', + }, + }) +}) diff --git a/tests/fixtures/v4/configs/output.html b/tests/fixtures/v4/configs/output.html new file mode 100644 index 00000000..6b4aae01 --- /dev/null +++ b/tests/fixtures/v4/configs/output.html @@ -0,0 +1,3 @@ +
diff --git a/tests/fixtures/v4/configs/package-lock.json b/tests/fixtures/v4/configs/package-lock.json new file mode 100644 index 00000000..fbba9f01 --- /dev/null +++ b/tests/fixtures/v4/configs/package-lock.json @@ -0,0 +1,17 @@ +{ + "name": "configs", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "tailwindcss": "^4.0.0-alpha.23" + } + }, + "node_modules/tailwindcss": { + "version": "4.0.0-alpha.23", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.23.tgz", + "integrity": "sha512-5dy4L1icQUYkG2Fa427QG3fKGkNqMi6V4bJE0DoxBZkR4e550w7uxYJ7vBXINWrRmDd4LHmQInkgsHza3lwONg==" + } + } +} diff --git a/tests/fixtures/v4/configs/package.json b/tests/fixtures/v4/configs/package.json new file mode 100644 index 00000000..7f5a61c1 --- /dev/null +++ b/tests/fixtures/v4/configs/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "tailwindcss": "^4.0.0-alpha.23" + }, + "prettier": { + "tailwindEntryPoint": "./app.css" + } +} diff --git a/tests/fixtures/v4/configs/tailwind.config.mjs b/tests/fixtures/v4/configs/tailwind.config.mjs new file mode 100644 index 00000000..9c3cfa75 --- /dev/null +++ b/tests/fixtures/v4/configs/tailwind.config.mjs @@ -0,0 +1,9 @@ +export default { + theme: { + extend: { + colors: { + "from-config": "#3490dc", + }, + }, + }, +}; From 78dbac3b528d58d6900050978134ad98600feda4 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 6 Sep 2024 18:09:51 -0400 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e8b14ef..d8d08b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Improved performance with large Svelte, Liquid, and Angular files ([#312](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/312)) +- Add support for @plugin and @config in v4 ([#316](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/316)) ## [0.6.6] - 2024-08-09