diff --git a/packages/tailwindcss-language-server/src/util/v4/design-system.ts b/packages/tailwindcss-language-server/src/util/v4/design-system.ts index f32305ce..05d2ecd3 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -9,6 +9,7 @@ import { Resolver } from '../../resolver' import { pathToFileURL } from '../../utils' import type { Jiti } from 'jiti/lib/types' import { assets } from './assets' +import { plugins } from './plugins' const HAS_V4_IMPORT = /@import\s*(?:'tailwindcss'|"tailwindcss")/ const HAS_V4_THEME = /@theme\s*\{/ @@ -58,6 +59,28 @@ function createLoader({ return await jiti.import(url.href, { default: true }) } catch (err) { + // If the request was to load a first-party plugin and we can't resolve it + // locally, then fall back to the built-in plugins that we know about. + if (resourceType === 'plugin' && id in plugins) { + console.log('Loading bundled plugin for: ', id) + return await plugins[id]() + } + + // This checks for an error thrown by enhanced-resolve + if (err && typeof err.details === 'string') { + let details: string = err.details + let pattern = /^resolve '([^']+)'/ + let match = details.match(pattern) + if (match) { + let [_, importee] = match + if (importee in plugins) { + console.log( + `[error] Cannot load '${id}' plugins inside configs or plugins is not currently supported`, + ) + } + } + } + return onError(id, err, resourceType) } } diff --git a/packages/tailwindcss-language-server/src/util/v4/plugins.ts b/packages/tailwindcss-language-server/src/util/v4/plugins.ts new file mode 100644 index 00000000..16efc4a5 --- /dev/null +++ b/packages/tailwindcss-language-server/src/util/v4/plugins.ts @@ -0,0 +1,5 @@ +export const plugins = { + '@tailwindcss/forms': () => import('@tailwindcss/forms').then((m) => m.default), + '@tailwindcss/aspect-ratio': () => import('@tailwindcss/aspect-ratio').then((m) => m.default), + '@tailwindcss/typography': () => import('@tailwindcss/typography').then((m) => m.default), +} diff --git a/packages/tailwindcss-language-server/tests/env/v4.test.js b/packages/tailwindcss-language-server/tests/env/v4.test.js index 6e5aa34c..76de7f15 100644 --- a/packages/tailwindcss-language-server/tests/env/v4.test.js +++ b/packages/tailwindcss-language-server/tests/env/v4.test.js @@ -53,6 +53,45 @@ defineTest({ }, }) +defineTest({ + name: 'v4, no npm, bundled plugins', + fs: { + 'app.css': css` + @import 'tailwindcss'; + @plugin "@tailwindcss/aspect-ratio"; + @plugin "@tailwindcss/forms"; + @plugin "@tailwindcss/typography"; + `, + }, + + // Note this test MUST run in spawn mode because Vitest hooks into import, + // require, etc… already and we need to test that any hooks are working + // without outside interference. + prepare: async ({ root }) => ({ client: await createClient({ root }) }), + + handle: async ({ client }) => { + let doc = await client.open({ + lang: 'html', + text: '
', + }) + + //
+ // ^ + let hover = await doc.hover({ line: 0, character: 13 }) + expect(hover).not.toEqual(null) + + //
+ // ^ + hover = await doc.hover({ line: 0, character: 25 }) + expect(hover).not.toEqual(null) + + //
+ // ^ + hover = await doc.hover({ line: 0, character: 37 }) + expect(hover).not.toEqual(null) + }, +}) + defineTest({ /** * Plugins and configs that import stuff from the `tailwindcss` package do diff --git a/packages/vscode-tailwindcss/CHANGELOG.md b/packages/vscode-tailwindcss/CHANGELOG.md index 18b39e02..d22e380c 100644 --- a/packages/vscode-tailwindcss/CHANGELOG.md +++ b/packages/vscode-tailwindcss/CHANGELOG.md @@ -2,7 +2,7 @@ ## Prerelease -- Nothing yet! +- v4: Support loading bundled versions of some first-party plugins ([#1240](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1240)) # 0.14.8