Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
23 changes: 10 additions & 13 deletions scripts/install-fixture-deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) })
}),
)
53 changes: 49 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<T>({
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,
Expand All @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions src/resolve.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -45,3 +46,5 @@ function freshMaybeResolve(name: string) {
return null
}
}

export { resolveFrom }
11 changes: 11 additions & 0 deletions tests/fixtures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ let fixtures = [
dir: 'custom-jsx',
ext: 'jsx',
},

{
name: 'v4: basic formatting',
dir: 'v4/basic',
ext: 'html',
},
{
name: 'v4: configs and plugins',
dir: 'v4/configs',
ext: 'html',
},
]

let configs = [
Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/v4/basic/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import 'tailwindcss';

@theme {
--color-tomato: tomato;
}
1 change: 1 addition & 0 deletions tests/fixtures/v4/basic/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="sm:bg-tomato bg-red-500"></div>
1 change: 1 addition & 0 deletions tests/fixtures/v4/basic/output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="bg-red-500 sm:bg-tomato"></div>
17 changes: 17 additions & 0 deletions tests/fixtures/v4/basic/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/fixtures/v4/basic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"dependencies": {
"tailwindcss": "^4.0.0-alpha.23"
},
"prettier": {
"tailwindEntryPoint": "./app.css"
}
}
8 changes: 8 additions & 0 deletions tests/fixtures/v4/configs/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@import "tailwindcss";

@config "./tailwind.config.mjs";
@plugin "./my-plugin.mjs";

@theme {
--color-tomato: tomato;
}
3 changes: 3 additions & 0 deletions tests/fixtures/v4/configs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div
class="sm:bg-tomato bg-red-500 from-plugin-1 from-plugin-2 bg-from-config sm:from-plugin-1"
></div>
13 changes: 13 additions & 0 deletions tests/fixtures/v4/configs/my-plugin.mjs
Original file line number Diff line number Diff line change
@@ -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',
},
})
})
3 changes: 3 additions & 0 deletions tests/fixtures/v4/configs/output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div
class="from-plugin-2 from-plugin-1 bg-from-config bg-red-500 sm:from-plugin-1 sm:bg-tomato"
></div>
17 changes: 17 additions & 0 deletions tests/fixtures/v4/configs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/fixtures/v4/configs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"dependencies": {
"tailwindcss": "^4.0.0-alpha.23"
},
"prettier": {
"tailwindEntryPoint": "./app.css"
}
}
9 changes: 9 additions & 0 deletions tests/fixtures/v4/configs/tailwind.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default {
theme: {
extend: {
colors: {
"from-config": "#3490dc",
},
},
},
};
Loading