From 2bc30d05801ceb38dbf101cd23ab1aea218e15bf Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 6 Aug 2024 15:33:04 +0200 Subject: [PATCH 01/22] Supress diagnostics on @plugin and @source --- packages/tailwindcss-language-server/src/language/cssServer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/src/language/cssServer.ts b/packages/tailwindcss-language-server/src/language/cssServer.ts index a9b85498..6c47a727 100644 --- a/packages/tailwindcss-language-server/src/language/cssServer.ts +++ b/packages/tailwindcss-language-server/src/language/cssServer.ts @@ -381,7 +381,7 @@ async function validateTextDocument(textDocument: TextDocument): Promise { .filter((diagnostic) => { if ( diagnostic.code === 'unknownAtRules' && - /Unknown at rule @(tailwind|apply|config|theme)/.test(diagnostic.message) + /Unknown at rule @(tailwind|apply|config|theme|plugin|source)/.test(diagnostic.message) ) { return false } From ddf3d5a447a2917f820be87b66a2caf3ef620100 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Fri, 9 Aug 2024 14:19:23 +0200 Subject: [PATCH 02/22] WIPWIP V4 load custom @content --- .../tailwindcss-language-server/package.json | 2 +- .../src/project-locator.test.ts | 180 ++++++++++-------- .../src/project-locator.ts | 36 +++- .../src/projects.ts | 2 + .../src/resolve-css-imports.ts | 124 ++++++++++++ .../src/util/v4/design-system.ts | 23 ++- .../fixtures/v4/custom-content/admin/app.css | 2 + .../fixtures/v4/custom-content/admin/foo.bin | 1 + .../fixtures/v4/custom-content/admin/tw.css | 2 + .../fixtures/v4/custom-content/admin/ui.css | 3 + .../v4/custom-content/package-lock.json | 18 ++ .../fixtures/v4/custom-content/package.json | 5 + .../fixtures/v4/custom-content/shared.html | 1 + .../fixtures/v4/custom-content/web/app.css | 2 + .../fixtures/v4/custom-content/web/bar.bin | 1 + 15 files changed, 319 insertions(+), 83 deletions(-) create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/app.css create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/foo.bin create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/tw.css create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/ui.css create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package.json create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/shared.html create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css create mode 100644 packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/bar.bin diff --git a/packages/tailwindcss-language-server/package.json b/packages/tailwindcss-language-server/package.json index 813e139b..9b63e455 100644 --- a/packages/tailwindcss-language-server/package.json +++ b/packages/tailwindcss-language-server/package.json @@ -36,7 +36,7 @@ "@tailwindcss/forms": "0.5.3", "@tailwindcss/language-service": "workspace:*", "@tailwindcss/line-clamp": "0.4.2", - "@tailwindcss/oxide": "^4.0.0-alpha.16", + "@tailwindcss/oxide": "file:/Users/philipp/dev/tailwindcss/dist/tailwindcss-oxide.tgz", "@tailwindcss/typography": "0.5.7", "@types/color-name": "^1.1.3", "@types/culori": "^2.1.0", diff --git a/packages/tailwindcss-language-server/src/project-locator.test.ts b/packages/tailwindcss-language-server/src/project-locator.test.ts index 34bb73ec..68c996f7 100644 --- a/packages/tailwindcss-language-server/src/project-locator.test.ts +++ b/packages/tailwindcss-language-server/src/project-locator.test.ts @@ -54,90 +54,116 @@ function testFixture(fixture: string, details: any[]) { }) } -testFixture('basic', [ +// testFixture('basic', [ +// // +// { config: 'tailwind.config.js' }, +// ]) + +// testFixture('dependencies', [ +// // +// { config: 'tailwind.config.js' }, +// ]) + +// testFixture('multi-config', [ +// // +// { config: 'one/tailwind.config.js' }, +// { config: 'two/tailwind.config.js' }, +// ]) + +// testFixture('multi-config-content', [ +// // +// { config: 'tailwind.config.one.js' }, +// { config: 'tailwind.config.two.js' }, +// ]) + +// testFixture('v3/esm-config', [ +// // +// { config: 'tailwind.config.mjs' }, +// ]) + +// testFixture('v3/ts-config', [ +// // +// { config: 'tailwind.config.ts' }, +// ]) + +// testFixture('v4/basic', [ +// // +// { config: 'app.css' }, +// ]) + +// testFixture('v4/multi-config', [ +// // +// { config: 'admin/app.css' }, +// { config: 'web/app.css' }, +// ]) + +// testFixture('v4/workspaces', [ +// { +// config: 'packages/admin/app.css', +// selectors: [ +// '{URL}/node_modules/tailwindcss/**', +// '{URL}/node_modules/tailwindcss/index.css', +// '{URL}/node_modules/tailwindcss/theme.css', +// '{URL}/node_modules/tailwindcss/utilities.css', +// '{URL}/packages/admin/**', +// '{URL}/packages/admin/app.css', +// '{URL}/packages/admin/package.json', +// ], +// }, +// { +// config: 'packages/web/app.css', +// selectors: [ +// '{URL}/node_modules/tailwindcss/**', +// '{URL}/node_modules/tailwindcss/index.css', +// '{URL}/node_modules/tailwindcss/theme.css', +// '{URL}/node_modules/tailwindcss/utilities.css', +// '{URL}/packages/style-export/**', +// '{URL}/packages/style-export/lib.css', +// '{URL}/packages/style-export/theme.css', +// '{URL}/packages/style-main-field/**', +// '{URL}/packages/style-main-field/lib.css', +// '{URL}/packages/web/**', +// '{URL}/packages/web/app.css', +// '{URL}/packages/web/package.json', +// ], +// }, +// ]) + +// testFixture('v4/auto-content', [ +// // +// { +// config: 'src/app.css', +// content: [ +// '{URL}/package.json', +// '{URL}/src/index.html', +// '{URL}/src/components/example.html', +// '{URL}/src/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', +// ], +// }, +// ]) + +testFixture('v4/custom-content', [ // - { config: 'tailwind.config.js' }, -]) - -testFixture('dependencies', [ - // - { config: 'tailwind.config.js' }, -]) - -testFixture('multi-config', [ - // - { config: 'one/tailwind.config.js' }, - { config: 'two/tailwind.config.js' }, -]) - -testFixture('multi-config-content', [ - // - { config: 'tailwind.config.one.js' }, - { config: 'tailwind.config.two.js' }, -]) - -testFixture('v3/esm-config', [ - // - { config: 'tailwind.config.mjs' }, -]) - -testFixture('v3/ts-config', [ - // - { config: 'tailwind.config.ts' }, -]) - -testFixture('v4/basic', [ - // - { config: 'app.css' }, -]) - -testFixture('v4/multi-config', [ - // - { config: 'admin/app.css' }, - { config: 'web/app.css' }, -]) - -testFixture('v4/workspaces', [ { - config: 'packages/admin/app.css', - selectors: [ - '{URL}/node_modules/tailwindcss/**', - '{URL}/node_modules/tailwindcss/index.css', - '{URL}/node_modules/tailwindcss/theme.css', - '{URL}/node_modules/tailwindcss/utilities.css', - '{URL}/packages/admin/**', - '{URL}/packages/admin/app.css', - '{URL}/packages/admin/package.json', - ], - }, - { - config: 'packages/web/app.css', - selectors: [ - '{URL}/node_modules/tailwindcss/**', - '{URL}/node_modules/tailwindcss/index.css', - '{URL}/node_modules/tailwindcss/theme.css', - '{URL}/node_modules/tailwindcss/utilities.css', - '{URL}/packages/style-export/**', - '{URL}/packages/style-export/lib.css', - '{URL}/packages/style-export/theme.css', - '{URL}/packages/style-main-field/**', - '{URL}/packages/style-main-field/lib.css', - '{URL}/packages/web/**', - '{URL}/packages/web/app.css', - '{URL}/packages/web/package.json', + config: 'admin/app.css', + content: [ + '{URL}/admin/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', + '{URL}/admin/**/*.bin', + '{URL}/admin/foo.bin', + '{URL}/package.json', + '{URL}/shared.html', + '{URL}/web/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', ], }, -]) - -testFixture('v4/auto-content', [ - // { - config: 'src/app.css', + config: 'web/app.css', content: [ + '{URL}/web/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', + '{URL}/web/*.bin', + '{URL}/web/bar.bin', '{URL}/package.json', - '{URL}/src/index.html', - '{URL}/src/components/example.html', - '{URL}/src/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', + '{URL}/shared.html', + '{URL}/admin/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', ], }, ]) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 6a96a967..399d5846 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -15,6 +15,7 @@ import resolveFrom from './util/resolveFrom' import { type Feature, supportedFeatures } from '@tailwindcss/language-service/src/features' import { resolveCssImports } from './resolve-css-imports' import { normalizeDriveLetter, normalizePath, pathToFileURL } from './utils' +import { loadConfig } from './util/v4/design-system' export interface ProjectConfig { /** The folder that contains the project */ @@ -105,6 +106,7 @@ export class ProjectLocator { entries: [], content: [], packageRoot: '', + globs: [], } let tailwind = await this.detectTailwindVersion(config) @@ -291,6 +293,7 @@ export class ProjectLocator { entries: [], packageRoot: null, content: [], + globs: [], })), ]) }) @@ -323,6 +326,7 @@ export class ProjectLocator { entries: [], packageRoot: null, content: [], + globs: [], })), ) continue @@ -378,7 +382,11 @@ export class ProjectLocator { if (indexPath && themePath) graph.connect(indexPath, themePath) if (indexPath && utilitiesPath) graph.connect(indexPath, utilitiesPath) + // QUESTION: Is this code path only for v4? I don't understand the gating + // here but adding a content kind auto indicates that this is the case. for (let root of graph.roots()) { + let globs = await loadConfig(root.path, root.content) + let config: ConfigEntry = configs.remember(root.path, () => ({ source: 'css', type: 'css', @@ -386,6 +394,7 @@ export class ProjectLocator { entries: [], packageRoot: null, content: [{ kind: 'auto' }], + globs, })) // The root is a CSS entrypoint so lets use it as the "config" file @@ -500,7 +509,7 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable } } else if (item.kind === 'auto' && !auto) { auto = true - for await (let pattern of detectContentFiles(entry.packageRoot)) { + for await (let pattern of detectContentFiles(entry.packageRoot, entry.path, entry.globs)) { yield { pattern, priority: DocumentSelectorPriority.CONTENT_FILE, @@ -510,17 +519,35 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable } } -async function* detectContentFiles(base: string): AsyncIterable { +async function* detectContentFiles( + base: string, + inputFile, + inputGlobs: string[], +): AsyncIterable { try { let oxidePath = resolveFrom(path.dirname(base), '@tailwindcss/oxide') oxidePath = pathToFileURL(oxidePath).href + console.log({ oxidePath }) - const oxide: typeof import('@tailwindcss/oxide') = await import(oxidePath) + const oxide: typeof import('@tailwindcss/oxide') = await import(oxidePath).then( + (o) => o.default, + ) // This isn't a v4 project if (!oxide.scanDir) return - let { files, globs } = oxide.scanDir({ base, globs: true }) + console.log(oxide.scanDir.toString()) + + console.log({ + inputFile, + s: inputGlobs.map((pattern) => ({ base: path.dirname(inputFile), pattern })), + }) + + let { files, globs } = oxide.scanDir({ + base, + sources: inputGlobs.map((pattern) => ({ base, pattern })), + }) + console.log({ files, globs }) for (let file of files) { yield normalizePath(file) @@ -547,6 +574,7 @@ type ConfigEntry = { entries: FileEntry[] packageRoot: string content: ContentItem[] + globs: string[] } class FileEntry { diff --git a/packages/tailwindcss-language-server/src/projects.ts b/packages/tailwindcss-language-server/src/projects.ts index 6704c871..48261297 100644 --- a/packages/tailwindcss-language-server/src/projects.ts +++ b/packages/tailwindcss-language-server/src/projects.ts @@ -750,6 +750,8 @@ export async function createProjectService( css, ) + console.log({ designSystem }) + state.designSystem = designSystem originalConfig = { theme: {} } diff --git a/packages/tailwindcss-language-server/src/resolve-css-imports.ts b/packages/tailwindcss-language-server/src/resolve-css-imports.ts index 2824c35a..d347b6ed 100644 --- a/packages/tailwindcss-language-server/src/resolve-css-imports.ts +++ b/packages/tailwindcss-language-server/src/resolve-css-imports.ts @@ -2,6 +2,9 @@ import postcss from 'postcss' import postcssImport from 'postcss-import' import { createResolver } from './util/resolve' +import path from 'node:path' +import type { AtRule, Plugin } from 'postcss' + const resolver = createResolver({ extensions: ['.css'], mainFields: ['style'], @@ -15,8 +18,129 @@ const resolveImports = postcss([ return paths ? paths : id }, }), + fixRelativePathsPlugin(), ]) export function resolveCssImports() { return resolveImports } + +const SINGLE_QUOTE = "'" +const DOUBLE_QUOTE = '"' + +export default function fixRelativePathsPlugin(): Plugin { + // Retain a list of touched at-rules to avoid infinite loops + let touched: WeakSet = new WeakSet() + + function fixRelativePath(atRule: AtRule) { + let rootPath = atRule.root().source?.input.file + if (!rootPath) { + return + } + + let inputFilePath = atRule.source?.input.file + if (!inputFilePath) { + return + } + + if (touched.has(atRule)) { + return + } + + let value = atRule.params[0] + + let quote = + value[0] === DOUBLE_QUOTE && value[value.length - 1] === DOUBLE_QUOTE + ? DOUBLE_QUOTE + : value[0] === SINGLE_QUOTE && value[value.length - 1] === SINGLE_QUOTE + ? SINGLE_QUOTE + : null + if (!quote) { + return + } + let glob = atRule.params.slice(1, -1) + + // Handle eventual negative rules. We only support one level of negation. + let negativePrefix = '' + if (glob.startsWith('!')) { + glob = glob.slice(1) + negativePrefix = '!' + } + + // We only want to rewrite relative paths. + if (!glob.startsWith('./') && !glob.startsWith('../')) { + return + } + + let absoluteGlob = path.posix.join(normalizePath(path.dirname(inputFilePath)), glob) + let absoluteRootPosixPath = path.posix.dirname(normalizePath(rootPath)) + + let relative = path.posix.relative(absoluteRootPosixPath, absoluteGlob) + + // If the path points to a file in the same directory, `path.relative` will + // remove the leading `./` and we need to add it back in order to still + // consider the path relative + if (!relative.startsWith('.')) { + relative = './' + relative + } + + atRule.params = quote + negativePrefix + relative + quote + touched.add(atRule) + } + + return { + postcssPlugin: 'tailwindcss-postcss-fix-relative-paths', + AtRule: { + source: fixRelativePath, + plugin: fixRelativePath, + }, + } +} + +// Inlined version of `normalize-path` +// Copyright (c) 2014-2018, Jon Schlinkert. +// Released under the MIT License. +function normalizePathBase(path: string, stripTrailing?: boolean) { + if (typeof path !== 'string') { + throw new TypeError('expected path to be a string') + } + + if (path === '\\' || path === '/') return '/' + + var len = path.length + if (len <= 1) return path + + // ensure that win32 namespaces has two leading slashes, so that the path is + // handled properly by the win32 version of path.parse() after being normalized + // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces + var prefix = '' + if (len > 4 && path[3] === '\\') { + var ch = path[2] + if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { + path = path.slice(2) + prefix = '//' + } + } + + var segs = path.split(/[/\\]+/) + if (stripTrailing !== false && segs[segs.length - 1] === '') { + segs.pop() + } + return prefix + segs.join('/') +} + +export function normalizePath(originalPath: string) { + let normalized = normalizePathBase(originalPath) + + // Make sure Windows network share paths are normalized properly + // They have to begin with two slashes or they won't resolve correctly + if ( + originalPath.startsWith('\\\\') && + normalized.startsWith('/') && + !normalized.startsWith('//') + ) { + return `/${normalized}` + } + + return normalized +} 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 818902da..4077a84e 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -1,6 +1,6 @@ import type { DesignSystem } from '@tailwindcss/language-service/src/util/v4' -import postcss from 'postcss' +import postcss, { AtRule } from 'postcss' import { resolveCssImports } from '../../resolve-css-imports' const HAS_V4_IMPORT = /@import\s*(?:'tailwindcss'|"tailwindcss")/ @@ -76,3 +76,24 @@ export async function loadDesignSystem( return design } + +export async function loadConfig(filepath: string, css: string): Promise { + let resolved = await resolveCssImports().process(css, { from: filepath }) + + let contentRules: string[] = [] + await postcss([ + { + postcssPlugin: 'extract-at-rules', + AtRule: { + content({ params }: AtRule) { + if (params[0] !== '"' && params[0] !== "'") { + return + } + contentRules.push(params.slice(1, -1)) + }, + }, + }, + ]).process(resolved, { from: filepath }) + + return contentRules +} diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/app.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/app.css new file mode 100644 index 00000000..41dcb5f8 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/app.css @@ -0,0 +1,2 @@ +@import './tw.css'; +@import './ui.css'; diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/foo.bin b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/foo.bin new file mode 100644 index 00000000..ec56c434 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/foo.bin @@ -0,0 +1 @@ +

Admin

diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/tw.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/tw.css new file mode 100644 index 00000000..999899d5 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/tw.css @@ -0,0 +1,2 @@ +@import 'tailwindcss'; +@content './**/*.bin'; diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/ui.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/ui.css new file mode 100644 index 00000000..24ea64d2 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/ui.css @@ -0,0 +1,3 @@ +@theme { + --color-potato: #907a70; +} diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json new file mode 100644 index 00000000..67939bec --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json @@ -0,0 +1,18 @@ +{ + "name": "custom-content", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "tailwindcss": "file:/Users/philipp/dev/tailwindcss/dist/tailwindcss.tgz" + } + }, + "node_modules/tailwindcss": { + "version": "4.0.0-alpha.18", + "resolved": "file:../../../../../../../tailwindcss/dist/tailwindcss.tgz", + "integrity": "sha512-AQnvDDzGzMBGT4gfMabcL+x4OEY5jbuRnndx5Kb5hsaE1jXERvGx/RHNwOo3pDdAJbowZko4dZTWFkLnFbcdtQ==", + "license": "MIT" + } + } +} diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package.json new file mode 100644 index 00000000..33e8e749 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "tailwindcss": "file:/Users/philipp/dev/tailwindcss/dist/tailwindcss.tgz" + } +} diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/shared.html b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/shared.html new file mode 100644 index 00000000..49b293bf --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/shared.html @@ -0,0 +1 @@ +

I belong to no one!

diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css new file mode 100644 index 00000000..9c5b8eb7 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css @@ -0,0 +1,2 @@ +@import 'tailwindcss'; +@content './*.bin'; diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/bar.bin b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/bar.bin new file mode 100644 index 00000000..56ee61a2 --- /dev/null +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/bar.bin @@ -0,0 +1 @@ +

Web

From 245806c88ae9aad7f0c9672a96ae8c0858e9c0ab Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Mon, 12 Aug 2024 15:21:53 +0200 Subject: [PATCH 03/22] Upgrade to latest stable release of V4 --- .../tailwindcss-language-server/package.json | 2 +- .../src/project-locator.test.ts | 178 +++++++++--------- .../src/project-locator.ts | 32 ++-- .../src/util/v4/design-system.ts | 4 +- .../v4/auto-content/package-lock.json | 108 ++++++----- .../fixtures/v4/auto-content/package.json | 4 +- .../tests/fixtures/v4/basic/package-lock.json | 9 +- .../tests/fixtures/v4/basic/package.json | 2 +- .../v4/multi-config/package-lock.json | 9 +- .../fixtures/v4/multi-config/package.json | 2 +- .../fixtures/v4/workspaces/package-lock.json | 9 +- .../tests/fixtures/v4/workspaces/package.json | 2 +- pnpm-lock.yaml | 90 ++++----- 13 files changed, 233 insertions(+), 218 deletions(-) diff --git a/packages/tailwindcss-language-server/package.json b/packages/tailwindcss-language-server/package.json index 9b63e455..d877569a 100644 --- a/packages/tailwindcss-language-server/package.json +++ b/packages/tailwindcss-language-server/package.json @@ -36,7 +36,7 @@ "@tailwindcss/forms": "0.5.3", "@tailwindcss/language-service": "workspace:*", "@tailwindcss/line-clamp": "0.4.2", - "@tailwindcss/oxide": "file:/Users/philipp/dev/tailwindcss/dist/tailwindcss-oxide.tgz", + "@tailwindcss/oxide": "^4.0.0-alpha.19", "@tailwindcss/typography": "0.5.7", "@types/color-name": "^1.1.3", "@types/culori": "^2.1.0", diff --git a/packages/tailwindcss-language-server/src/project-locator.test.ts b/packages/tailwindcss-language-server/src/project-locator.test.ts index 68c996f7..6f01dbfe 100644 --- a/packages/tailwindcss-language-server/src/project-locator.test.ts +++ b/packages/tailwindcss-language-server/src/project-locator.test.ts @@ -54,93 +54,93 @@ function testFixture(fixture: string, details: any[]) { }) } -// testFixture('basic', [ -// // -// { config: 'tailwind.config.js' }, -// ]) - -// testFixture('dependencies', [ -// // -// { config: 'tailwind.config.js' }, -// ]) - -// testFixture('multi-config', [ -// // -// { config: 'one/tailwind.config.js' }, -// { config: 'two/tailwind.config.js' }, -// ]) - -// testFixture('multi-config-content', [ -// // -// { config: 'tailwind.config.one.js' }, -// { config: 'tailwind.config.two.js' }, -// ]) - -// testFixture('v3/esm-config', [ -// // -// { config: 'tailwind.config.mjs' }, -// ]) - -// testFixture('v3/ts-config', [ -// // -// { config: 'tailwind.config.ts' }, -// ]) - -// testFixture('v4/basic', [ -// // -// { config: 'app.css' }, -// ]) - -// testFixture('v4/multi-config', [ -// // -// { config: 'admin/app.css' }, -// { config: 'web/app.css' }, -// ]) - -// testFixture('v4/workspaces', [ -// { -// config: 'packages/admin/app.css', -// selectors: [ -// '{URL}/node_modules/tailwindcss/**', -// '{URL}/node_modules/tailwindcss/index.css', -// '{URL}/node_modules/tailwindcss/theme.css', -// '{URL}/node_modules/tailwindcss/utilities.css', -// '{URL}/packages/admin/**', -// '{URL}/packages/admin/app.css', -// '{URL}/packages/admin/package.json', -// ], -// }, -// { -// config: 'packages/web/app.css', -// selectors: [ -// '{URL}/node_modules/tailwindcss/**', -// '{URL}/node_modules/tailwindcss/index.css', -// '{URL}/node_modules/tailwindcss/theme.css', -// '{URL}/node_modules/tailwindcss/utilities.css', -// '{URL}/packages/style-export/**', -// '{URL}/packages/style-export/lib.css', -// '{URL}/packages/style-export/theme.css', -// '{URL}/packages/style-main-field/**', -// '{URL}/packages/style-main-field/lib.css', -// '{URL}/packages/web/**', -// '{URL}/packages/web/app.css', -// '{URL}/packages/web/package.json', -// ], -// }, -// ]) - -// testFixture('v4/auto-content', [ -// // -// { -// config: 'src/app.css', -// content: [ -// '{URL}/package.json', -// '{URL}/src/index.html', -// '{URL}/src/components/example.html', -// '{URL}/src/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', -// ], -// }, -// ]) +testFixture('basic', [ + // + { config: 'tailwind.config.js' }, +]) + +testFixture('dependencies', [ + // + { config: 'tailwind.config.js' }, +]) + +testFixture('multi-config', [ + // + { config: 'one/tailwind.config.js' }, + { config: 'two/tailwind.config.js' }, +]) + +testFixture('multi-config-content', [ + // + { config: 'tailwind.config.one.js' }, + { config: 'tailwind.config.two.js' }, +]) + +testFixture('v3/esm-config', [ + // + { config: 'tailwind.config.mjs' }, +]) + +testFixture('v3/ts-config', [ + // + { config: 'tailwind.config.ts' }, +]) + +testFixture('v4/basic', [ + // + { config: 'app.css' }, +]) + +testFixture('v4/multi-config', [ + // + { config: 'admin/app.css' }, + { config: 'web/app.css' }, +]) + +testFixture('v4/workspaces', [ + { + config: 'packages/admin/app.css', + selectors: [ + '{URL}/node_modules/tailwindcss/**', + '{URL}/node_modules/tailwindcss/index.css', + '{URL}/node_modules/tailwindcss/theme.css', + '{URL}/node_modules/tailwindcss/utilities.css', + '{URL}/packages/admin/**', + '{URL}/packages/admin/app.css', + '{URL}/packages/admin/package.json', + ], + }, + { + config: 'packages/web/app.css', + selectors: [ + '{URL}/node_modules/tailwindcss/**', + '{URL}/node_modules/tailwindcss/index.css', + '{URL}/node_modules/tailwindcss/theme.css', + '{URL}/node_modules/tailwindcss/utilities.css', + '{URL}/packages/style-export/**', + '{URL}/packages/style-export/lib.css', + '{URL}/packages/style-export/theme.css', + '{URL}/packages/style-main-field/**', + '{URL}/packages/style-main-field/lib.css', + '{URL}/packages/web/**', + '{URL}/packages/web/app.css', + '{URL}/packages/web/package.json', + ], + }, +]) + +testFixture('v4/auto-content', [ + // + { + config: 'src/app.css', + content: [ + '{URL}/package.json', + '{URL}/src/index.html', + '{URL}/src/components/example.html', + '{URL}/src/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', + ], + }, +]) testFixture('v4/custom-content', [ // @@ -158,12 +158,12 @@ testFixture('v4/custom-content', [ { config: 'web/app.css', content: [ - '{URL}/web/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', + '{URL}/admin/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', '{URL}/web/*.bin', '{URL}/web/bar.bin', '{URL}/package.json', '{URL}/shared.html', - '{URL}/admin/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', + '{URL}/web/**/*.{py,tpl,js,vue,php,mjs,cts,jsx,tsx,rhtml,slim,handlebars,twig,rs,njk,svelte,liquid,pug,md,ts,heex,mts,astro,nunjucks,rb,eex,haml,cjs,html,hbs,jade,aspx,razor,erb,mustache,mdx}', ], }, ]) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 399d5846..d8b9b506 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -382,8 +382,6 @@ export class ProjectLocator { if (indexPath && themePath) graph.connect(indexPath, themePath) if (indexPath && utilitiesPath) graph.connect(indexPath, utilitiesPath) - // QUESTION: Is this code path only for v4? I don't understand the gating - // here but adding a content kind auto indicates that this is the case. for (let root of graph.roots()) { let globs = await loadConfig(root.path, root.content) @@ -527,7 +525,6 @@ async function* detectContentFiles( try { let oxidePath = resolveFrom(path.dirname(base), '@tailwindcss/oxide') oxidePath = pathToFileURL(oxidePath).href - console.log({ oxidePath }) const oxide: typeof import('@tailwindcss/oxide') = await import(oxidePath).then( (o) => o.default, @@ -536,26 +533,31 @@ async function* detectContentFiles( // This isn't a v4 project if (!oxide.scanDir) return - console.log(oxide.scanDir.toString()) - - console.log({ - inputFile, - s: inputGlobs.map((pattern) => ({ base: path.dirname(inputFile), pattern })), - }) - - let { files, globs } = oxide.scanDir({ + let { files, globs, candidates } = oxide.scanDir({ base, - sources: inputGlobs.map((pattern) => ({ base, pattern })), + sources: inputGlobs.map((pattern) => ({ + base: path.dirname(inputFile), + pattern, + })), }) - console.log({ files, globs }) + console.log( + { + base, + sources: inputGlobs.map((pattern) => ({ + base: path.dirname(inputFile), + pattern, + })), + }, + { files, globs, candidates }, + ) for (let file of files) { yield normalizePath(file) } - for (let { base, glob } of globs) { + for (let { base, pattern } of globs) { // Do not normalize the glob itself as it may contain escape sequences - yield normalizePath(base) + '/' + glob + yield normalizePath(base) + '/' + pattern } } catch { // 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 4077a84e..59ae0488 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -78,8 +78,6 @@ export async function loadDesignSystem( } export async function loadConfig(filepath: string, css: string): Promise { - let resolved = await resolveCssImports().process(css, { from: filepath }) - let contentRules: string[] = [] await postcss([ { @@ -93,7 +91,7 @@ export async function loadConfig(filepath: string, css: string): Promise= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.0.0-alpha.16", - "@tailwindcss/oxide-darwin-arm64": "4.0.0-alpha.16", - "@tailwindcss/oxide-darwin-x64": "4.0.0-alpha.16", - "@tailwindcss/oxide-freebsd-x64": "4.0.0-alpha.16", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.0-alpha.16", - "@tailwindcss/oxide-linux-arm64-gnu": "4.0.0-alpha.16", - "@tailwindcss/oxide-linux-arm64-musl": "4.0.0-alpha.16", - "@tailwindcss/oxide-linux-x64-gnu": "4.0.0-alpha.16", - "@tailwindcss/oxide-linux-x64-musl": "4.0.0-alpha.16", - "@tailwindcss/oxide-win32-x64-msvc": "4.0.0-alpha.16" + "@tailwindcss/oxide-android-arm64": "4.0.0-alpha.19", + "@tailwindcss/oxide-darwin-arm64": "4.0.0-alpha.19", + "@tailwindcss/oxide-darwin-x64": "4.0.0-alpha.19", + "@tailwindcss/oxide-freebsd-x64": "4.0.0-alpha.19", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.0-alpha.19", + "@tailwindcss/oxide-linux-arm64-gnu": "4.0.0-alpha.19", + "@tailwindcss/oxide-linux-arm64-musl": "4.0.0-alpha.19", + "@tailwindcss/oxide-linux-x64-gnu": "4.0.0-alpha.19", + "@tailwindcss/oxide-linux-x64-musl": "4.0.0-alpha.19", + "@tailwindcss/oxide-win32-x64-msvc": "4.0.0-alpha.19" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.0-alpha.16.tgz", - "integrity": "sha512-duaTHvkAeUJQoqfA5XnYIp6F0PtqdcjXILuUF43wV0hC3NH2CECaxAgG2Ca5OVFAGqCI3fo29iqPMVcEEDlyjA==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.0-alpha.19.tgz", + "integrity": "sha512-NhpXem1j7g0uSGyLucmMj0VVQMeUrWc6kR/Ymnri3tpw2eaykgFYwLfdnI7jdJRxUxa/nNJip9yBJ3diZXl60w==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "android" @@ -45,12 +47,13 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.0-alpha.16.tgz", - "integrity": "sha512-4T5+35t5Qb0hZLLmclhVzsV5tmnjMwCqEySMnG8YLMB7YlATvmZG9TL8JqJLQjxqwjMDsl5tCddkui4FAxgLbA==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.0-alpha.19.tgz", + "integrity": "sha512-KCdalT+huX2cW9snNmPr+B66V91cSzIobBCXVgYCPCh0NZF4ueKu+X+kQN2gFxurDUm/D+aKW/0rQUIsUmFpdQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -60,12 +63,13 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.0-alpha.16.tgz", - "integrity": "sha512-dchop1QRdOcnh8hwI/w1HrUgE3ZAvvz8iCEv5akEA0zOglBsHd3hGA2u8zAt5PrDz/wBmdOpr+R5H2bYLw1MPw==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.0-alpha.19.tgz", + "integrity": "sha512-ETOWA08loUmOVTEa3zhRhY8HyqdGtR9DNhXdrRZBi67ZwCAmA+jg5B+mZaYeQJ6CjETx07BnhcGmmxGz3/6c8w==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -75,12 +79,13 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.0-alpha.16.tgz", - "integrity": "sha512-K5otxfNigxsY2fkgHI63Jjm+hvSI4gCFa2xGtsvTVUEHPUTOEo4n+aj9yIkNFgGpeIDii2nt3DtKYjhKyfUirw==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.0-alpha.19.tgz", + "integrity": "sha512-uB0rYLpqPnmyqtYSKHu1AtnHeerNcVH+de0sIufGCBDFGYNxmW8feCKNZwo6r7U/Fzg+AF9BOjwvdvd4yLfQ8g==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -90,12 +95,13 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.0-alpha.16.tgz", - "integrity": "sha512-AT8tYba/32q5FVLnJThcvYS8zmOBwLU5JzScaTY0Lc34WbGQ0+y6dtPlZoyyW+e+OBI8mDsTiD2BR3h0rdqb7g==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.0-alpha.19.tgz", + "integrity": "sha512-hIfm6DNh18rkz2PFRsQANINH0tpso6/vaU8p0Qw7rgYqqrxJTRpyLVsnvx3ahMOplJrDT6Z+Nfak8udnZN2C/Q==", "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -105,12 +111,13 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.0-alpha.16.tgz", - "integrity": "sha512-RcKr+fXs0kOT679UM2SEBRqGkXTP+jzk9+G96gwqa4OLgp6fiW1TSRB22V8j+Q10oWqfMHxsBSe9awM7F2ebuw==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.0-alpha.19.tgz", + "integrity": "sha512-n1Hr+8Hup2GLmeonQy9ydZxMBCs0FR1rcv4K7AHip+6PbD0se8k9LBIZac3OguFNj2hTehiadaiRb18rsVUw0g==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -120,12 +127,13 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.0-alpha.16.tgz", - "integrity": "sha512-lsUf21WkPufMVSOmj3EwoSGdb0KbCq0czMChkeIyLlt5WC/ZvH0ZMd9U5sfHQ7c1Q9usWfhz+Is9SbX7n2WvuA==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.0-alpha.19.tgz", + "integrity": "sha512-KhwthLZh9Js3t5URkuRURw45iU3rSh9vhuHRaV4KQT10ZFiXQMUlFfMKJyxRMcgC2fcL5vsiqwjOaMwp7Y8vsQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -135,12 +143,13 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.0-alpha.16.tgz", - "integrity": "sha512-D+uu2PCFb1fOuVWWS+xhtKVfbNbPmGYdMy4xwplOdHn8gacokUvDGsKdW/nogFoHtSws4+U6O4+mFjSQH3heSg==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.0-alpha.19.tgz", + "integrity": "sha512-qqEuULSiczyZkdWVzwkiiFyOYqx5RR2De75iwYREzXUuHRHval1ep2qO7tvZdgt37t2vgjoQwaPA6zO+JGUa+Q==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -150,12 +159,13 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.0-alpha.16.tgz", - "integrity": "sha512-zFoaEQvx9DhXO7LUNRlmUFm8N92LXs9n1YD/60MOYJqpVzPdqLBplk+Ltpw1NPE/Y2BZ7XvXyrBl11XH6Wj0/A==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.0-alpha.19.tgz", + "integrity": "sha512-JKTYCiNz83sYl2FgKJk3dL11FS4dAj7Rgmuz3TVANmeMYTBtwmFPthoH0qAmF+hjPJgT5Ne7lSwplfuHJAD3MQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -165,12 +175,13 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.0-alpha.16.tgz", - "integrity": "sha512-ClCzUFuD6xptvcksYtoLJekUdSN9TVoSrr66eNVAErtA+vKKTThOyliEz/pZfe7lHsI93sDR22HMtu/zP0prJA==", + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.0-alpha.19.tgz", + "integrity": "sha512-D43tji14+i/GhJn5YZX8c2FXFmAqlI6DDGX8caUM35dga/uT+sJUfLJ84YigJyvAdSF1gBVdm7MvhYRcVYHOwg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -180,9 +191,10 @@ } }, "node_modules/tailwindcss": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.16.tgz", - "integrity": "sha512-h6UIkQEpOJZy0N8tXeWgIhsEYPfUyqST9Oidr46+1W78p8S9hjJDfnW08/bKW17NA9/ro8sZvFHT98LtwwxtSQ==" + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.19.tgz", + "integrity": "sha512-4k8i6ml9ZQaj4xmdTHA2ZVp4YGsA+9+8VsIj/VkwyD38J5jX3L3NSi7TnPvlYT+WXcqAJF7EX8x76yCTfi2CyA==", + "license": "MIT" } } } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/auto-content/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/auto-content/package.json index 874817d0..50f951e7 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/auto-content/package.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/auto-content/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "tailwindcss": "^4.0.0-alpha.16", - "@tailwindcss/oxide": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19", + "@tailwindcss/oxide": "^4.0.0-alpha.19" } } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package-lock.json index 4e476083..cf1b17a6 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package-lock.json @@ -5,13 +5,14 @@ "packages": { "": { "dependencies": { - "tailwindcss": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19" } }, "node_modules/tailwindcss": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.16.tgz", - "integrity": "sha512-h6UIkQEpOJZy0N8tXeWgIhsEYPfUyqST9Oidr46+1W78p8S9hjJDfnW08/bKW17NA9/ro8sZvFHT98LtwwxtSQ==" + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.19.tgz", + "integrity": "sha512-4k8i6ml9ZQaj4xmdTHA2ZVp4YGsA+9+8VsIj/VkwyD38J5jX3L3NSi7TnPvlYT+WXcqAJF7EX8x76yCTfi2CyA==", + "license": "MIT" } } } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package.json index 996efe04..efa461d1 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/basic/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "tailwindcss": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19" } } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package-lock.json index 697a0096..b64395e4 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package-lock.json @@ -5,13 +5,14 @@ "packages": { "": { "dependencies": { - "tailwindcss": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19" } }, "node_modules/tailwindcss": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.16.tgz", - "integrity": "sha512-h6UIkQEpOJZy0N8tXeWgIhsEYPfUyqST9Oidr46+1W78p8S9hjJDfnW08/bKW17NA9/ro8sZvFHT98LtwwxtSQ==" + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.19.tgz", + "integrity": "sha512-4k8i6ml9ZQaj4xmdTHA2ZVp4YGsA+9+8VsIj/VkwyD38J5jX3L3NSi7TnPvlYT+WXcqAJF7EX8x76yCTfi2CyA==", + "license": "MIT" } } } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package.json index 996efe04..efa461d1 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/multi-config/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "tailwindcss": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19" } } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package-lock.json index 1dd6e822..df3317ef 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package-lock.json @@ -8,7 +8,7 @@ "packages/*" ], "dependencies": { - "tailwindcss": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19" } }, "node_modules/@private/admin": { @@ -32,9 +32,10 @@ "link": true }, "node_modules/tailwindcss": { - "version": "4.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.16.tgz", - "integrity": "sha512-h6UIkQEpOJZy0N8tXeWgIhsEYPfUyqST9Oidr46+1W78p8S9hjJDfnW08/bKW17NA9/ro8sZvFHT98LtwwxtSQ==" + "version": "4.0.0-alpha.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0-alpha.19.tgz", + "integrity": "sha512-4k8i6ml9ZQaj4xmdTHA2ZVp4YGsA+9+8VsIj/VkwyD38J5jX3L3NSi7TnPvlYT+WXcqAJF7EX8x76yCTfi2CyA==", + "license": "MIT" }, "packages/admin": { "name": "@private/admin" diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package.json index 3f0204c3..700667f2 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/workspaces/package.json @@ -3,6 +3,6 @@ "packages/*" ], "dependencies": { - "tailwindcss": "^4.0.0-alpha.16" + "tailwindcss": "^4.0.0-alpha.19" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d746a236..851a1c97 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,8 +51,8 @@ importers: specifier: 0.4.2 version: 0.4.2(tailwindcss@3.4.4) '@tailwindcss/oxide': - specifier: ^4.0.0-alpha.16 - version: 4.0.0-alpha.18 + specifier: ^4.0.0-alpha.19 + version: 4.0.0-alpha.19 '@tailwindcss/typography': specifier: 0.5.7 version: 0.5.7(tailwindcss@3.4.4) @@ -840,68 +840,68 @@ packages: peerDependencies: tailwindcss: '>=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1' - '@tailwindcss/oxide-android-arm64@4.0.0-alpha.18': - resolution: {integrity: sha512-fAdyr3GC5CDEdiVs/wg6aZFr0BD/RZxlEAjzGUL9mFyqyX5HsGbu0rVwyJvDaFjKMw5nB6hjfyaZMpuwHfQr8w==} + '@tailwindcss/oxide-android-arm64@4.0.0-alpha.19': + resolution: {integrity: sha512-NhpXem1j7g0uSGyLucmMj0VVQMeUrWc6kR/Ymnri3tpw2eaykgFYwLfdnI7jdJRxUxa/nNJip9yBJ3diZXl60w==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.0.0-alpha.18': - resolution: {integrity: sha512-K3YoYtAQNyaLXJ8q6f2ib4K6hm1+MT2ajh59C8rLOjfBp0jL4Whd8k9DuL8ctjlVoRvRT9ggQO90fKqx5g+6HA==} + '@tailwindcss/oxide-darwin-arm64@4.0.0-alpha.19': + resolution: {integrity: sha512-KCdalT+huX2cW9snNmPr+B66V91cSzIobBCXVgYCPCh0NZF4ueKu+X+kQN2gFxurDUm/D+aKW/0rQUIsUmFpdQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.0.0-alpha.18': - resolution: {integrity: sha512-WYIK59UaKWhh1LVV6E3VdfPjrZZl/d1q1B3pBVXSoxOWU2fX1OP1f6pqs78/cADAK3FDJ24MByn2m/rDyfFXvg==} + '@tailwindcss/oxide-darwin-x64@4.0.0-alpha.19': + resolution: {integrity: sha512-ETOWA08loUmOVTEa3zhRhY8HyqdGtR9DNhXdrRZBi67ZwCAmA+jg5B+mZaYeQJ6CjETx07BnhcGmmxGz3/6c8w==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.0.0-alpha.18': - resolution: {integrity: sha512-awG9qCHfVEa7yyEnFziDf0jkbJ/zB7n8CYv6jnDt43nfrdiytTmXOD7+QUt1PEY+mKw5mOJR4yWH1rMVnWIV5w==} + '@tailwindcss/oxide-freebsd-x64@4.0.0-alpha.19': + resolution: {integrity: sha512-uB0rYLpqPnmyqtYSKHu1AtnHeerNcVH+de0sIufGCBDFGYNxmW8feCKNZwo6r7U/Fzg+AF9BOjwvdvd4yLfQ8g==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.0-alpha.18': - resolution: {integrity: sha512-4aY4B9Ips0KuvCF9vDLKE99APi7GxyueQPzKWkHE1T9CJVFk1JpsPF1hnSzaZewxloM18yLXBFCl7SImoaGh0A==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.0-alpha.19': + resolution: {integrity: sha512-hIfm6DNh18rkz2PFRsQANINH0tpso6/vaU8p0Qw7rgYqqrxJTRpyLVsnvx3ahMOplJrDT6Z+Nfak8udnZN2C/Q==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.0.0-alpha.18': - resolution: {integrity: sha512-Ky9gcVhJZQBaRLL5w35dE+fHoHXVn9PJy7iNAqgauh+kkPeU7L/EoWu70XMBVaxu7jw8J7KLAUgLR9E6Atwldg==} + '@tailwindcss/oxide-linux-arm64-gnu@4.0.0-alpha.19': + resolution: {integrity: sha512-n1Hr+8Hup2GLmeonQy9ydZxMBCs0FR1rcv4K7AHip+6PbD0se8k9LBIZac3OguFNj2hTehiadaiRb18rsVUw0g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.0.0-alpha.18': - resolution: {integrity: sha512-dcq/3wleXfqc9+QAe1eZO00yJEGJRhwA6U80p3C1cgVSg3sZOeKwLPi/69MbkXN1I+VoKqLbYgtv/GzzLY9g2A==} + '@tailwindcss/oxide-linux-arm64-musl@4.0.0-alpha.19': + resolution: {integrity: sha512-KhwthLZh9Js3t5URkuRURw45iU3rSh9vhuHRaV4KQT10ZFiXQMUlFfMKJyxRMcgC2fcL5vsiqwjOaMwp7Y8vsQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.0.0-alpha.18': - resolution: {integrity: sha512-R0NeALYR7vhGNvY5PJpmwPdAfp5X2CyYo8FqR2fMgqVyKHpGhJsj+BR2Hg6AcSFg7t4DA1T+fOOcGUupK9cnkQ==} + '@tailwindcss/oxide-linux-x64-gnu@4.0.0-alpha.19': + resolution: {integrity: sha512-qqEuULSiczyZkdWVzwkiiFyOYqx5RR2De75iwYREzXUuHRHval1ep2qO7tvZdgt37t2vgjoQwaPA6zO+JGUa+Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.0.0-alpha.18': - resolution: {integrity: sha512-dY/j372Jc+MwGoyHnFW8eGBW6Gab1lU1cMIFm+4TcA63HuYAJfnzt+KU1Jai/5huYj+cy6qrHnWAdO9V3yWpdQ==} + '@tailwindcss/oxide-linux-x64-musl@4.0.0-alpha.19': + resolution: {integrity: sha512-JKTYCiNz83sYl2FgKJk3dL11FS4dAj7Rgmuz3TVANmeMYTBtwmFPthoH0qAmF+hjPJgT5Ne7lSwplfuHJAD3MQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-win32-x64-msvc@4.0.0-alpha.18': - resolution: {integrity: sha512-B7eSqgxLfJYZCOX+PZZRWJB5pKTRAVWDRzlMy86cdOIT12TRL4OPT4KQuWnrvfNKVKgcQv6eZhG6CZS6pLi20Q==} + '@tailwindcss/oxide-win32-x64-msvc@4.0.0-alpha.19': + resolution: {integrity: sha512-D43tji14+i/GhJn5YZX8c2FXFmAqlI6DDGX8caUM35dga/uT+sJUfLJ84YigJyvAdSF1gBVdm7MvhYRcVYHOwg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.0.0-alpha.18': - resolution: {integrity: sha512-Pc4c8khaklIqLWWSVqbVX8P3imjmM3SChJaSPkajbzlQRx17iwqZWVQJIhwP/rZh1aGeJDOVb0kduVlw/J5bIA==} + '@tailwindcss/oxide@4.0.0-alpha.19': + resolution: {integrity: sha512-DdkrVz/MKPoe9v7W3c0+SEFKRDIPMSsxgN7gPC+xeTnTL4BGoT5b1EiVGFuXWEyLbDmWztuN6z75Yuze2BwvMQ==} engines: {node: '>= 10'} '@tailwindcss/typography@0.5.7': @@ -3056,48 +3056,48 @@ snapshots: dependencies: tailwindcss: 3.4.4 - '@tailwindcss/oxide-android-arm64@4.0.0-alpha.18': + '@tailwindcss/oxide-android-arm64@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-darwin-arm64@4.0.0-alpha.18': + '@tailwindcss/oxide-darwin-arm64@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-darwin-x64@4.0.0-alpha.18': + '@tailwindcss/oxide-darwin-x64@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-freebsd-x64@4.0.0-alpha.18': + '@tailwindcss/oxide-freebsd-x64@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.0-alpha.18': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.0.0-alpha.18': + '@tailwindcss/oxide-linux-arm64-gnu@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.0.0-alpha.18': + '@tailwindcss/oxide-linux-arm64-musl@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.0.0-alpha.18': + '@tailwindcss/oxide-linux-x64-gnu@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.0.0-alpha.18': + '@tailwindcss/oxide-linux-x64-musl@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.0.0-alpha.18': + '@tailwindcss/oxide-win32-x64-msvc@4.0.0-alpha.19': optional: true - '@tailwindcss/oxide@4.0.0-alpha.18': + '@tailwindcss/oxide@4.0.0-alpha.19': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.0.0-alpha.18 - '@tailwindcss/oxide-darwin-arm64': 4.0.0-alpha.18 - '@tailwindcss/oxide-darwin-x64': 4.0.0-alpha.18 - '@tailwindcss/oxide-freebsd-x64': 4.0.0-alpha.18 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.0-alpha.18 - '@tailwindcss/oxide-linux-arm64-gnu': 4.0.0-alpha.18 - '@tailwindcss/oxide-linux-arm64-musl': 4.0.0-alpha.18 - '@tailwindcss/oxide-linux-x64-gnu': 4.0.0-alpha.18 - '@tailwindcss/oxide-linux-x64-musl': 4.0.0-alpha.18 - '@tailwindcss/oxide-win32-x64-msvc': 4.0.0-alpha.18 + '@tailwindcss/oxide-android-arm64': 4.0.0-alpha.19 + '@tailwindcss/oxide-darwin-arm64': 4.0.0-alpha.19 + '@tailwindcss/oxide-darwin-x64': 4.0.0-alpha.19 + '@tailwindcss/oxide-freebsd-x64': 4.0.0-alpha.19 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.0-alpha.19 + '@tailwindcss/oxide-linux-arm64-gnu': 4.0.0-alpha.19 + '@tailwindcss/oxide-linux-arm64-musl': 4.0.0-alpha.19 + '@tailwindcss/oxide-linux-x64-gnu': 4.0.0-alpha.19 + '@tailwindcss/oxide-linux-x64-musl': 4.0.0-alpha.19 + '@tailwindcss/oxide-win32-x64-msvc': 4.0.0-alpha.19 '@tailwindcss/typography@0.5.7(tailwindcss@3.4.4)': dependencies: From 378220dab6119a345cf375f2a460662f25007a7a Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Mon, 12 Aug 2024 15:25:23 +0200 Subject: [PATCH 04/22] Rename to @source --- .../src/project-locator.test.ts | 2 +- .../src/util/v4/design-system.ts | 8 ++++---- .../v4/{custom-content => custom-source}/admin/app.css | 0 .../v4/{custom-content => custom-source}/admin/foo.bin | 0 .../v4/{custom-content => custom-source}/admin/tw.css | 0 .../v4/{custom-content => custom-source}/admin/ui.css | 0 .../{custom-content => custom-source}/package-lock.json | 2 +- .../v4/{custom-content => custom-source}/package.json | 0 .../v4/{custom-content => custom-source}/shared.html | 0 .../v4/{custom-content => custom-source}/web/app.css | 2 +- .../v4/{custom-content => custom-source}/web/bar.bin | 0 11 files changed, 7 insertions(+), 7 deletions(-) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/admin/app.css (100%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/admin/foo.bin (100%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/admin/tw.css (100%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/admin/ui.css (100%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/package-lock.json (94%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/package.json (100%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/shared.html (100%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/web/app.css (53%) rename packages/tailwindcss-language-server/tests/fixtures/v4/{custom-content => custom-source}/web/bar.bin (100%) diff --git a/packages/tailwindcss-language-server/src/project-locator.test.ts b/packages/tailwindcss-language-server/src/project-locator.test.ts index 6f01dbfe..7db5f1b1 100644 --- a/packages/tailwindcss-language-server/src/project-locator.test.ts +++ b/packages/tailwindcss-language-server/src/project-locator.test.ts @@ -142,7 +142,7 @@ testFixture('v4/auto-content', [ }, ]) -testFixture('v4/custom-content', [ +testFixture('v4/custom-source', [ // { config: 'admin/app.css', 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 59ae0488..f3f08484 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -78,20 +78,20 @@ export async function loadDesignSystem( } export async function loadConfig(filepath: string, css: string): Promise { - let contentRules: string[] = [] + let sourceRules: string[] = [] await postcss([ { postcssPlugin: 'extract-at-rules', AtRule: { - content({ params }: AtRule) { + source({ params }: AtRule) { if (params[0] !== '"' && params[0] !== "'") { return } - contentRules.push(params.slice(1, -1)) + sourceRules.push(params.slice(1, -1)) }, }, }, ]).process(css, { from: filepath }) - return contentRules + return sourceRules } diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/app.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/app.css similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/app.css rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/app.css diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/foo.bin b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/foo.bin similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/foo.bin rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/foo.bin diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/tw.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/tw.css similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/tw.css rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/tw.css diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/ui.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/ui.css similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/admin/ui.css rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/ui.css diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json similarity index 94% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json index 67939bec..1c1396f2 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json @@ -1,5 +1,5 @@ { - "name": "custom-content", + "name": "custom-source", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/package.json rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/shared.html b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/shared.html similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/shared.html rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/shared.html diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/web/app.css similarity index 53% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/web/app.css index 9c5b8eb7..9357eb02 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/app.css +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/web/app.css @@ -1,2 +1,2 @@ @import 'tailwindcss'; -@content './*.bin'; +@source './*.bin'; diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/bar.bin b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/web/bar.bin similarity index 100% rename from packages/tailwindcss-language-server/tests/fixtures/v4/custom-content/web/bar.bin rename to packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/web/bar.bin From 0c204ec7c538a21be3dd82e4ef16e55f77405fe1 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Mon, 12 Aug 2024 15:44:32 +0200 Subject: [PATCH 05/22] More fixes --- .../src/project-locator.ts | 12 ------------ .../tests/fixtures/v4/custom-source/admin/tw.css | 2 +- .../fixtures/v4/custom-source/package-lock.json | 2 +- .../tests/fixtures/v4/custom-source/package.json | 2 +- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index d8b9b506..0bb38baa 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -130,8 +130,6 @@ export class ProjectLocator { private async createProject(config: ConfigEntry): Promise { let tailwind = await this.detectTailwindVersion(config) - console.log(JSON.stringify({ tailwind })) - // A JS/TS config file was loaded from an `@config`` directive in a CSS file if (config.type === 'js' && config.source === 'css') { // We only allow local versions of Tailwind to use `@config` directives @@ -540,16 +538,6 @@ async function* detectContentFiles( pattern, })), }) - console.log( - { - base, - sources: inputGlobs.map((pattern) => ({ - base: path.dirname(inputFile), - pattern, - })), - }, - { files, globs, candidates }, - ) for (let file of files) { yield normalizePath(file) diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/tw.css b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/tw.css index 999899d5..9c0a7919 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/tw.css +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/admin/tw.css @@ -1,2 +1,2 @@ @import 'tailwindcss'; -@content './**/*.bin'; +@source './**/*.bin'; diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json index 1c1396f2..4057803c 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "tailwindcss": "file:/Users/philipp/dev/tailwindcss/dist/tailwindcss.tgz" + "tailwindcss": "^4.0.0-alpha.18" } }, "node_modules/tailwindcss": { diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json index 33e8e749..2d53a701 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "tailwindcss": "file:/Users/philipp/dev/tailwindcss/dist/tailwindcss.tgz" + "tailwindcss": "^4.0.0-alpha.18" } } From 52e7930c47782cbcbc057ca215245ce0aedb2291 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 13 Aug 2024 09:58:00 +0200 Subject: [PATCH 06/22] Fix tests --- .../tests/completions/completions.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tailwindcss-language-server/tests/completions/completions.test.js b/packages/tailwindcss-language-server/tests/completions/completions.test.js index 32b283cd..6f44f8b1 100644 --- a/packages/tailwindcss-language-server/tests/completions/completions.test.js +++ b/packages/tailwindcss-language-server/tests/completions/completions.test.js @@ -310,8 +310,8 @@ withFixture('v4/basic', (c) => { let result = await completion({ lang, text, position, settings }) let textEdit = expect.objectContaining({ range: { start: position, end: position } }) - expect(result.items.length).toBe(12376) - expect(result.items.filter((item) => item.label.endsWith(':')).length).toBe(220) + expect(result.items.length).toBe(12400) + expect(result.items.filter((item) => item.label.endsWith(':')).length).toBe(224) expect(result).toEqual({ isIncomplete: false, items: expect.arrayContaining([ From 47a04d6933a06dcd9d871a02520cdeaf04cc8f5a Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 13 Aug 2024 10:11:25 +0200 Subject: [PATCH 07/22] Preload sources as part of the resolving step --- .../src/project-locator.ts | 51 ++++++++++++++----- .../src/projects.ts | 2 - .../src/util/v4/design-system.ts | 19 ------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 0bb38baa..6825ca3c 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -7,7 +7,7 @@ import type { Settings } from '@tailwindcss/language-service/src/util/state' import { CONFIG_GLOB, CSS_GLOB } from './lib/constants' import { readCssFile } from './util/css' import { Graph } from './graph' -import type { Message } from 'postcss' +import type { AtRule, Message } from 'postcss' import { type DocumentSelector, DocumentSelectorPriority } from './projects' import { CacheMap } from './cache-map' import { getPackageRoot } from './util/get-package-root' @@ -15,7 +15,7 @@ import resolveFrom from './util/resolveFrom' import { type Feature, supportedFeatures } from '@tailwindcss/language-service/src/features' import { resolveCssImports } from './resolve-css-imports' import { normalizeDriveLetter, normalizePath, pathToFileURL } from './utils' -import { loadConfig } from './util/v4/design-system' +import postcss from 'postcss' export interface ProjectConfig { /** The folder that contains the project */ @@ -106,7 +106,6 @@ export class ProjectLocator { entries: [], content: [], packageRoot: '', - globs: [], } let tailwind = await this.detectTailwindVersion(config) @@ -130,6 +129,8 @@ export class ProjectLocator { private async createProject(config: ConfigEntry): Promise { let tailwind = await this.detectTailwindVersion(config) + console.log(JSON.stringify({ tailwind })) + // A JS/TS config file was loaded from an `@config`` directive in a CSS file if (config.type === 'js' && config.source === 'css') { // We only allow local versions of Tailwind to use `@config` directives @@ -291,7 +292,6 @@ export class ProjectLocator { entries: [], packageRoot: null, content: [], - globs: [], })), ]) }) @@ -324,7 +324,6 @@ export class ProjectLocator { entries: [], packageRoot: null, content: [], - globs: [], })), ) continue @@ -343,6 +342,9 @@ export class ProjectLocator { // Resolve real paths for all the files in the CSS import graph await Promise.all(imports.map((file) => file.resolveRealpaths())) + // Resolve all @source directives + await Promise.all(imports.map((file) => file.resolveSourceDirectives())) + // Create a graph of all the CSS files that might (indirectly) use Tailwind let graph = new Graph() @@ -381,8 +383,6 @@ export class ProjectLocator { if (indexPath && utilitiesPath) graph.connect(indexPath, utilitiesPath) for (let root of graph.roots()) { - let globs = await loadConfig(root.path, root.content) - let config: ConfigEntry = configs.remember(root.path, () => ({ source: 'css', type: 'css', @@ -390,7 +390,6 @@ export class ProjectLocator { entries: [], packageRoot: null, content: [{ kind: 'auto' }], - globs, })) // The root is a CSS entrypoint so lets use it as the "config" file @@ -505,7 +504,12 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable } } else if (item.kind === 'auto' && !auto) { auto = true - for await (let pattern of detectContentFiles(entry.packageRoot, entry.path, entry.globs)) { + let root = entry.entries[0] + for await (let pattern of detectContentFiles( + entry.packageRoot, + entry.path, + root?.sources ?? [], + )) { yield { pattern, priority: DocumentSelectorPriority.CONTENT_FILE, @@ -518,7 +522,7 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable async function* detectContentFiles( base: string, inputFile, - inputGlobs: string[], + sources: string[], ): AsyncIterable { try { let oxidePath = resolveFrom(path.dirname(base), '@tailwindcss/oxide') @@ -533,7 +537,7 @@ async function* detectContentFiles( let { files, globs, candidates } = oxide.scanDir({ base, - sources: inputGlobs.map((pattern) => ({ + sources: sources.map((pattern) => ({ base: path.dirname(inputFile), pattern, })), @@ -564,13 +568,13 @@ type ConfigEntry = { entries: FileEntry[] packageRoot: string content: ContentItem[] - globs: string[] } class FileEntry { content: string | null deps: FileEntry[] = [] realpath: string | null + sources: string[] = [] constructor( public type: 'js' | 'css', @@ -607,6 +611,29 @@ class FileEntry { await Promise.all(this.deps.map((entry) => entry.resolveRealpaths())) } + async resolveSourceDirectives() { + if (this.sources.length > 0) { + return + } + // Note: This should eventually use the DesignSystem to extract the same + // sources also discovered by tailwind. Since we don't have everything yet + // to initialize the design system though, we set up a simple postcss at + // rule exporter instead for now. + await postcss([ + { + postcssPlugin: 'extract-at-rules', + AtRule: { + source: ({ params }: AtRule) => { + if (params[0] !== '"' && params[0] !== "'") { + return + } + this.sources.push(params.slice(1, -1)) + }, + }, + }, + ]).process(this.content, { from: this.realpath }) + } + /** * Look for `@config` directives in a CSS file and return the path to the config * file that it points to. This path is (possibly) relative to the CSS file so diff --git a/packages/tailwindcss-language-server/src/projects.ts b/packages/tailwindcss-language-server/src/projects.ts index 48261297..6704c871 100644 --- a/packages/tailwindcss-language-server/src/projects.ts +++ b/packages/tailwindcss-language-server/src/projects.ts @@ -750,8 +750,6 @@ export async function createProjectService( css, ) - console.log({ designSystem }) - state.designSystem = designSystem originalConfig = { theme: {} } 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 f3f08484..db9a9aff 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -76,22 +76,3 @@ export async function loadDesignSystem( return design } - -export async function loadConfig(filepath: string, css: string): Promise { - let sourceRules: string[] = [] - await postcss([ - { - postcssPlugin: 'extract-at-rules', - AtRule: { - source({ params }: AtRule) { - if (params[0] !== '"' && params[0] !== "'") { - return - } - sourceRules.push(params.slice(1, -1)) - }, - }, - }, - ]).process(css, { from: filepath }) - - return sourceRules -} From c4d693158e9f9b6d29255afae6a62ca6538af6b4 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 13 Aug 2024 10:12:41 +0200 Subject: [PATCH 08/22] Backward comp --- packages/tailwindcss-language-server/src/project-locator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 6825ca3c..933952cf 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -529,7 +529,7 @@ async function* detectContentFiles( oxidePath = pathToFileURL(oxidePath).href const oxide: typeof import('@tailwindcss/oxide') = await import(oxidePath).then( - (o) => o.default, + (o) => o.default || o, ) // This isn't a v4 project From 6a5f3717a5483c2a80afbc59f3b32cc29d660c57 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 13 Aug 2024 10:14:42 +0200 Subject: [PATCH 09/22] Remove unnecessary import --- .../tailwindcss-language-server/src/util/v4/design-system.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 db9a9aff..818902da 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -1,6 +1,6 @@ import type { DesignSystem } from '@tailwindcss/language-service/src/util/v4' -import postcss, { AtRule } from 'postcss' +import postcss from 'postcss' import { resolveCssImports } from '../../resolve-css-imports' const HAS_V4_IMPORT = /@import\s*(?:'tailwindcss'|"tailwindcss")/ From 9a410f35d3ab5a147e2ec9a5dda79a5c59e39e8e Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 12:48:23 -0400 Subject: [PATCH 10/22] Refactor --- .../tailwindcss-language-server/src/oxide.ts | 112 ++++++++++++++++++ .../src/project-locator.ts | 22 ++-- 2 files changed, 123 insertions(+), 11 deletions(-) create mode 100644 packages/tailwindcss-language-server/src/oxide.ts diff --git a/packages/tailwindcss-language-server/src/oxide.ts b/packages/tailwindcss-language-server/src/oxide.ts new file mode 100644 index 00000000..54df00a0 --- /dev/null +++ b/packages/tailwindcss-language-server/src/oxide.ts @@ -0,0 +1,112 @@ +// This covers the Oxide API from v4.0.0-alpha.1 to v4.0.0-alpha.18 +declare namespace OxideV1 { + interface GlobEntry { + base: string + glob: string + } + + interface ScanOptions { + base: string + globs?: boolean + } + + interface ScanResult { + files: Array + globs: Array + candidates: Array + } +} + +// This covers the Oxide API from v4.0.0-alpha.19+ +declare namespace OxideV2 { + interface GlobEntry { + base: string + pattern: string + } + + interface ScanOptions { + base: string + sources: Array + } + + interface ScanResult { + files: Array + globs: Array + candidates: Array + } +} + +interface Oxide { + scanDir?(options: OxideV1.ScanOptions): OxideV1.ScanResult + scanDir?(options: OxideV2.ScanOptions): OxideV2.ScanResult +} + +async function loadOxideAtPath(id: string): Promise { + let oxide = await import(id).then((o) => o.default || o) + + // This is a much older, unsupport version of Oxide before v4.0.0-alpha.1 + if (!oxide.scanDir) return null + + return oxide +} + +interface GlobEntry { + base: string + pattern: string +} + +interface ScanOptions { + oxidePath: string + basePath: string + sources: Array +} + +interface ScanResult { + files: Array + globs: Array + candidates: Array +} + +/** + * This is a helper function that leverages the Oxide API to scan a directory + * and a set of sources and turn them into files and globs. + * + * Because the Oxide API has changed over time this function presents a unified + * interface that works with all versions of the Oxide API but the results may + * be different depending on the version of Oxide that is being used. + * + * For example, the `sources` option is ignored before v4.0.0-alpha.19. + */ +export async function scan(options: ScanOptions): Promise { + const oxide = await loadOxideAtPath(options.oxidePath) + if (!oxide) return null + + let resultV1: OxideV1.ScanResult | null = null + let resultV2: OxideV2.ScanResult | null = null + + try { + resultV2 = oxide.scanDir({ + base: options.basePath, + sources: options.sources, + }) + } catch { + resultV1 = oxide.scanDir({ + base: options.basePath, + globs: true, + }) + } + + if (resultV2) { + return { + files: resultV2.files, + globs: resultV2.globs, + candidates: resultV2.candidates, + } + } + + return { + files: resultV1.files, + globs: resultV1.globs.map((g) => ({ base: g.base, pattern: g.glob })), + candidates: resultV1.candidates, + } +} diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 933952cf..f0815423 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -16,6 +16,7 @@ import { type Feature, supportedFeatures } from '@tailwindcss/language-service/s import { resolveCssImports } from './resolve-css-imports' import { normalizeDriveLetter, normalizePath, pathToFileURL } from './utils' import postcss from 'postcss' +import * as oxide from './oxide' export interface ProjectConfig { /** The folder that contains the project */ @@ -519,6 +520,8 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable } } +function scan() {} + async function* detectContentFiles( base: string, inputFile, @@ -528,26 +531,23 @@ async function* detectContentFiles( let oxidePath = resolveFrom(path.dirname(base), '@tailwindcss/oxide') oxidePath = pathToFileURL(oxidePath).href - const oxide: typeof import('@tailwindcss/oxide') = await import(oxidePath).then( - (o) => o.default || o, - ) - - // This isn't a v4 project - if (!oxide.scanDir) return - - let { files, globs, candidates } = oxide.scanDir({ - base, + let result = await oxide.scan({ + oxidePath, + basePath: base, sources: sources.map((pattern) => ({ base: path.dirname(inputFile), pattern, })), }) - for (let file of files) { + // This isn't a v4 project + if (!result) return + + for (let file of result.files) { yield normalizePath(file) } - for (let { base, pattern } of globs) { + for (let { base, pattern } of result.globs) { // Do not normalize the glob itself as it may contain escape sequences yield normalizePath(base) + '/' + pattern } From 2dac76ac9b72e3b8baf79b25f9f26da96b92607d Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 12:51:46 -0400 Subject: [PATCH 11/22] wip --- .../tests/fixtures/v4/custom-source/package-lock.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json index 4057803c..a029cc58 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json @@ -9,9 +9,7 @@ } }, "node_modules/tailwindcss": { - "version": "4.0.0-alpha.18", - "resolved": "file:../../../../../../../tailwindcss/dist/tailwindcss.tgz", - "integrity": "sha512-AQnvDDzGzMBGT4gfMabcL+x4OEY5jbuRnndx5Kb5hsaE1jXERvGx/RHNwOo3pDdAJbowZko4dZTWFkLnFbcdtQ==", + "version": "4.0.0-alpha.19", "license": "MIT" } } From e3f941bcdbf275cb6b1a969495c140a21a4a0dff Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 12:58:12 -0400 Subject: [PATCH 12/22] wip --- packages/tailwindcss-language-server/src/project-locator.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index f0815423..7a0a6b27 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -520,11 +520,9 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable } } -function scan() {} - async function* detectContentFiles( base: string, - inputFile, + inputFile: string, sources: string[], ): AsyncIterable { try { From 2b3e341135f1a9d12095166338f2d3198275b6cc Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 13:11:33 -0400 Subject: [PATCH 13/22] Refactor --- .../src/css/fix-relative-paths.ts | 69 +++++++++ .../src/css/index.ts | 1 + .../src/css/resolve-css-imports.ts | 24 +++ .../tailwindcss-language-server/src/oxide.ts | 2 + .../src/project-locator.ts | 2 +- .../src/resolve-css-imports.ts | 146 ------------------ .../src/util/v4/design-system.ts | 2 +- 7 files changed, 98 insertions(+), 148 deletions(-) create mode 100644 packages/tailwindcss-language-server/src/css/fix-relative-paths.ts create mode 100644 packages/tailwindcss-language-server/src/css/index.ts create mode 100644 packages/tailwindcss-language-server/src/css/resolve-css-imports.ts delete mode 100644 packages/tailwindcss-language-server/src/resolve-css-imports.ts diff --git a/packages/tailwindcss-language-server/src/css/fix-relative-paths.ts b/packages/tailwindcss-language-server/src/css/fix-relative-paths.ts new file mode 100644 index 00000000..46d5d169 --- /dev/null +++ b/packages/tailwindcss-language-server/src/css/fix-relative-paths.ts @@ -0,0 +1,69 @@ +import path from 'node:path' +import type { AtRule, Plugin } from 'postcss' +import { normalizePath } from '../utils' + +const SINGLE_QUOTE = "'" +const DOUBLE_QUOTE = '"' + +export function fixRelativePaths(): Plugin { + // Retain a list of touched at-rules to avoid infinite loops + let touched: WeakSet = new WeakSet() + + function fixRelativePath(atRule: AtRule) { + if (touched.has(atRule)) return + + let rootPath = atRule.root().source?.input.file + if (!rootPath) return + + let inputFilePath = atRule.source?.input.file + if (!inputFilePath) return + + let value = atRule.params[0] + + let quote = + value[0] === DOUBLE_QUOTE && value[value.length - 1] === DOUBLE_QUOTE + ? DOUBLE_QUOTE + : value[0] === SINGLE_QUOTE && value[value.length - 1] === SINGLE_QUOTE + ? SINGLE_QUOTE + : null + + if (!quote) return + + let glob = atRule.params.slice(1, -1) + + // Handle eventual negative rules. We only support one level of negation. + let negativePrefix = '' + if (glob.startsWith('!')) { + glob = glob.slice(1) + negativePrefix = '!' + } + + // We only want to rewrite relative paths. + if (!glob.startsWith('./') && !glob.startsWith('../')) { + return + } + + let absoluteGlob = path.posix.join(normalizePath(path.dirname(inputFilePath)), glob) + let absoluteRootPosixPath = path.posix.dirname(normalizePath(rootPath)) + + let relative = path.posix.relative(absoluteRootPosixPath, absoluteGlob) + + // If the path points to a file in the same directory, `path.relative` will + // remove the leading `./` and we need to add it back in order to still + // consider the path relative + if (!relative.startsWith('.')) { + relative = './' + relative + } + + atRule.params = quote + negativePrefix + relative + quote + touched.add(atRule) + } + + return { + postcssPlugin: 'tailwindcss-postcss-fix-relative-paths', + AtRule: { + source: fixRelativePath, + plugin: fixRelativePath, + }, + } +} diff --git a/packages/tailwindcss-language-server/src/css/index.ts b/packages/tailwindcss-language-server/src/css/index.ts new file mode 100644 index 00000000..6c1ff043 --- /dev/null +++ b/packages/tailwindcss-language-server/src/css/index.ts @@ -0,0 +1 @@ +export * from './resolve-css-imports' diff --git a/packages/tailwindcss-language-server/src/css/resolve-css-imports.ts b/packages/tailwindcss-language-server/src/css/resolve-css-imports.ts new file mode 100644 index 00000000..cf0e130a --- /dev/null +++ b/packages/tailwindcss-language-server/src/css/resolve-css-imports.ts @@ -0,0 +1,24 @@ +import postcss from 'postcss' +import postcssImport from 'postcss-import' +import { createResolver } from '../util/resolve' +import { fixRelativePaths } from './fix-relative-paths' + +const resolver = createResolver({ + extensions: ['.css'], + mainFields: ['style'], + conditionNames: ['style'], +}) + +const resolveImports = postcss([ + postcssImport({ + resolve(id, basedir) { + let paths = resolver.resolveSync({}, basedir, id) + return paths ? paths : id + }, + }), + fixRelativePaths(), +]) + +export function resolveCssImports() { + return resolveImports +} diff --git a/packages/tailwindcss-language-server/src/oxide.ts b/packages/tailwindcss-language-server/src/oxide.ts index 54df00a0..c9f9dadf 100644 --- a/packages/tailwindcss-language-server/src/oxide.ts +++ b/packages/tailwindcss-language-server/src/oxide.ts @@ -84,6 +84,8 @@ export async function scan(options: ScanOptions): Promise { let resultV1: OxideV1.ScanResult | null = null let resultV2: OxideV2.ScanResult | null = null + console.log(options) + try { resultV2 = oxide.scanDir({ base: options.basePath, diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 7a0a6b27..7289706c 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -13,7 +13,7 @@ import { CacheMap } from './cache-map' import { getPackageRoot } from './util/get-package-root' import resolveFrom from './util/resolveFrom' import { type Feature, supportedFeatures } from '@tailwindcss/language-service/src/features' -import { resolveCssImports } from './resolve-css-imports' +import { resolveCssImports } from './css' import { normalizeDriveLetter, normalizePath, pathToFileURL } from './utils' import postcss from 'postcss' import * as oxide from './oxide' diff --git a/packages/tailwindcss-language-server/src/resolve-css-imports.ts b/packages/tailwindcss-language-server/src/resolve-css-imports.ts deleted file mode 100644 index d347b6ed..00000000 --- a/packages/tailwindcss-language-server/src/resolve-css-imports.ts +++ /dev/null @@ -1,146 +0,0 @@ -import postcss from 'postcss' -import postcssImport from 'postcss-import' -import { createResolver } from './util/resolve' - -import path from 'node:path' -import type { AtRule, Plugin } from 'postcss' - -const resolver = createResolver({ - extensions: ['.css'], - mainFields: ['style'], - conditionNames: ['style'], -}) - -const resolveImports = postcss([ - postcssImport({ - resolve(id, basedir) { - let paths = resolver.resolveSync({}, basedir, id) - return paths ? paths : id - }, - }), - fixRelativePathsPlugin(), -]) - -export function resolveCssImports() { - return resolveImports -} - -const SINGLE_QUOTE = "'" -const DOUBLE_QUOTE = '"' - -export default function fixRelativePathsPlugin(): Plugin { - // Retain a list of touched at-rules to avoid infinite loops - let touched: WeakSet = new WeakSet() - - function fixRelativePath(atRule: AtRule) { - let rootPath = atRule.root().source?.input.file - if (!rootPath) { - return - } - - let inputFilePath = atRule.source?.input.file - if (!inputFilePath) { - return - } - - if (touched.has(atRule)) { - return - } - - let value = atRule.params[0] - - let quote = - value[0] === DOUBLE_QUOTE && value[value.length - 1] === DOUBLE_QUOTE - ? DOUBLE_QUOTE - : value[0] === SINGLE_QUOTE && value[value.length - 1] === SINGLE_QUOTE - ? SINGLE_QUOTE - : null - if (!quote) { - return - } - let glob = atRule.params.slice(1, -1) - - // Handle eventual negative rules. We only support one level of negation. - let negativePrefix = '' - if (glob.startsWith('!')) { - glob = glob.slice(1) - negativePrefix = '!' - } - - // We only want to rewrite relative paths. - if (!glob.startsWith('./') && !glob.startsWith('../')) { - return - } - - let absoluteGlob = path.posix.join(normalizePath(path.dirname(inputFilePath)), glob) - let absoluteRootPosixPath = path.posix.dirname(normalizePath(rootPath)) - - let relative = path.posix.relative(absoluteRootPosixPath, absoluteGlob) - - // If the path points to a file in the same directory, `path.relative` will - // remove the leading `./` and we need to add it back in order to still - // consider the path relative - if (!relative.startsWith('.')) { - relative = './' + relative - } - - atRule.params = quote + negativePrefix + relative + quote - touched.add(atRule) - } - - return { - postcssPlugin: 'tailwindcss-postcss-fix-relative-paths', - AtRule: { - source: fixRelativePath, - plugin: fixRelativePath, - }, - } -} - -// Inlined version of `normalize-path` -// Copyright (c) 2014-2018, Jon Schlinkert. -// Released under the MIT License. -function normalizePathBase(path: string, stripTrailing?: boolean) { - if (typeof path !== 'string') { - throw new TypeError('expected path to be a string') - } - - if (path === '\\' || path === '/') return '/' - - var len = path.length - if (len <= 1) return path - - // ensure that win32 namespaces has two leading slashes, so that the path is - // handled properly by the win32 version of path.parse() after being normalized - // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces - var prefix = '' - if (len > 4 && path[3] === '\\') { - var ch = path[2] - if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { - path = path.slice(2) - prefix = '//' - } - } - - var segs = path.split(/[/\\]+/) - if (stripTrailing !== false && segs[segs.length - 1] === '') { - segs.pop() - } - return prefix + segs.join('/') -} - -export function normalizePath(originalPath: string) { - let normalized = normalizePathBase(originalPath) - - // Make sure Windows network share paths are normalized properly - // They have to begin with two slashes or they won't resolve correctly - if ( - originalPath.startsWith('\\\\') && - normalized.startsWith('/') && - !normalized.startsWith('//') - ) { - return `/${normalized}` - } - - return normalized -} 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 818902da..07cc3766 100644 --- a/packages/tailwindcss-language-server/src/util/v4/design-system.ts +++ b/packages/tailwindcss-language-server/src/util/v4/design-system.ts @@ -1,7 +1,7 @@ import type { DesignSystem } from '@tailwindcss/language-service/src/util/v4' import postcss from 'postcss' -import { resolveCssImports } from '../../resolve-css-imports' +import { resolveCssImports } from '../../css' const HAS_V4_IMPORT = /@import\s*(?:'tailwindcss'|"tailwindcss")/ const HAS_V4_THEME = /@theme\s*\{/ From 2748325002f591770416e1061a9da8da0df911db Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 13:19:16 -0400 Subject: [PATCH 14/22] Refactor --- .../src/css/extract-source-directives.ts | 15 +++++++++++++++ .../src/css/index.ts | 1 + .../src/project-locator.ts | 19 +++++-------------- 3 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 packages/tailwindcss-language-server/src/css/extract-source-directives.ts diff --git a/packages/tailwindcss-language-server/src/css/extract-source-directives.ts b/packages/tailwindcss-language-server/src/css/extract-source-directives.ts new file mode 100644 index 00000000..52887daf --- /dev/null +++ b/packages/tailwindcss-language-server/src/css/extract-source-directives.ts @@ -0,0 +1,15 @@ +import type { Plugin } from 'postcss' + +export function extractSourceDirectives(sources: string[]): Plugin { + return { + postcssPlugin: 'extract-at-rules', + AtRule: { + source: (node) => { + if (node.params[0] !== '"' && node.params[0] !== "'") return + sources.push(node.params.slice(1, -1)) + + console.log(node.toString()) + }, + }, + } +} diff --git a/packages/tailwindcss-language-server/src/css/index.ts b/packages/tailwindcss-language-server/src/css/index.ts index 6c1ff043..9028d9de 100644 --- a/packages/tailwindcss-language-server/src/css/index.ts +++ b/packages/tailwindcss-language-server/src/css/index.ts @@ -1 +1,2 @@ export * from './resolve-css-imports' +export * from './extract-source-directives' diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 7289706c..46294070 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -13,7 +13,7 @@ import { CacheMap } from './cache-map' import { getPackageRoot } from './util/get-package-root' import resolveFrom from './util/resolveFrom' import { type Feature, supportedFeatures } from '@tailwindcss/language-service/src/features' -import { resolveCssImports } from './css' +import { extractSourceDirectives, resolveCssImports } from './css' import { normalizeDriveLetter, normalizePath, pathToFileURL } from './utils' import postcss from 'postcss' import * as oxide from './oxide' @@ -613,23 +613,14 @@ class FileEntry { if (this.sources.length > 0) { return } + // Note: This should eventually use the DesignSystem to extract the same // sources also discovered by tailwind. Since we don't have everything yet // to initialize the design system though, we set up a simple postcss at // rule exporter instead for now. - await postcss([ - { - postcssPlugin: 'extract-at-rules', - AtRule: { - source: ({ params }: AtRule) => { - if (params[0] !== '"' && params[0] !== "'") { - return - } - this.sources.push(params.slice(1, -1)) - }, - }, - }, - ]).process(this.content, { from: this.realpath }) + await postcss([extractSourceDirectives(this.sources)]).process(this.content, { + from: this.realpath, + }) } /** From a71246276fad0c50cea6f806b38560aff5ebaed6 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 13:35:51 -0400 Subject: [PATCH 15/22] Fix comment replacement in CSS --- .../src/util/doc.ts | 70 ++++++++++++++++++- .../src/util/splice-changes-into-string.ts | 42 +++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 packages/tailwindcss-language-service/src/util/splice-changes-into-string.ts diff --git a/packages/tailwindcss-language-service/src/util/doc.ts b/packages/tailwindcss-language-service/src/util/doc.ts index 4975ec46..770612d7 100644 --- a/packages/tailwindcss-language-service/src/util/doc.ts +++ b/packages/tailwindcss-language-service/src/util/doc.ts @@ -1,6 +1,7 @@ import type { Range } from 'vscode-languageserver' import type { TextDocument } from 'vscode-languageserver-textdocument' import moo from 'moo' +import { spliceChangesIntoString, StringChange } from './splice-changes-into-string' export function getTextWithoutComments( doc: TextDocument, @@ -8,6 +9,7 @@ export function getTextWithoutComments( range?: Range, ): string export function getTextWithoutComments(text: string, type: 'html' | 'js' | 'jsx' | 'css'): string + export function getTextWithoutComments( docOrText: TextDocument | string, type: 'html' | 'js' | 'jsx' | 'css', @@ -20,12 +22,78 @@ export function getTextWithoutComments( } if (type === 'css') { - return text.replace(/\/\*.*?\*\//gs, replace) + return getCssWithoutComments(text) } return text.replace(//gs, replace) } +function getCssWithoutComments(input: string) { + const DOUBLE_QUOTE = 0x22 // " + const SINGLE_QUOTE = 0x27 // ' + const BACKSLASH = 0x5c // \ + const SLASH = 0x2f // / + const ASTERISK = 0x2a // * + const LINE_BREAK = 0x0a // \n + + let changes: StringChange[] = [] + + // Collect ranges for every comment in the input. + for (let i = 0; i < input.length; ++i) { + let currentChar = input.charCodeAt(i) + + if (currentChar === BACKSLASH) { + i += 1 + } + + // Skip over strings — they are to be left untouched + else if (currentChar === SINGLE_QUOTE || currentChar === DOUBLE_QUOTE) { + for (let j = i + 1; j < input.length; ++j) { + let peekChar = input.charCodeAt(j) + + // Current character is a `\` therefore the next character is escaped. + if (peekChar === BACKSLASH) { + j += 1 + } + + // End of the string. + else if (peekChar === currentChar) { + i = j + break + } else if (peekChar === LINE_BREAK) { + i = j + break + } + } + } else if (currentChar === SLASH && input.charCodeAt(i + 1) === ASTERISK) { + let start = i + + for (let j = i + 2; j < input.length; j++) { + let peekChar = input.charCodeAt(j) + + // Current character is a `\` therefore the next character is escaped. + if (peekChar === BACKSLASH) { + j += 1 + } + + // End of the comment + else if (peekChar === ASTERISK && input.charCodeAt(j + 1) === SLASH) { + i = j + 1 + break + } + } + + changes.push({ + start, + end: i + 1, + replacement: replace(input.slice(start, i + 1)), + }) + } + } + + return spliceChangesIntoString(input, changes) +} + function replace(match: string): string { return match.replace(/./gs, (char) => (char === '\n' ? '\n' : ' ')) } diff --git a/packages/tailwindcss-language-service/src/util/splice-changes-into-string.ts b/packages/tailwindcss-language-service/src/util/splice-changes-into-string.ts new file mode 100644 index 00000000..e1e6f168 --- /dev/null +++ b/packages/tailwindcss-language-service/src/util/splice-changes-into-string.ts @@ -0,0 +1,42 @@ +export interface StringChange { + start: number + end: number + replacement: string +} + +/** + * Apply the changes to the string such that a change in the length + * of the string does not break the indexes of the subsequent changes. + */ +export function spliceChangesIntoString(str: string, changes: StringChange[]) { + // If there are no changes, return the original string + if (!changes[0]) return str + + // Sort all changes in order to make it easier to apply them + changes.sort((a, b) => { + return a.end - b.end || a.start - b.start + }) + + // Append original string between each chunk, and then the chunk itself + // This is sort of a String Builder pattern, thus creating less memory pressure + let result = '' + + let previous = changes[0] + + result += str.slice(0, previous.start) + result += previous.replacement + + for (let i = 1; i < changes.length; ++i) { + let change = changes[i] + + result += str.slice(previous.end, change.start) + result += change.replacement + + previous = change + } + + // Add leftover string from last chunk to end + result += str.slice(previous.end) + + return result +} From a38f0bfe7c06d2f8df843ac26327b073569e1a04 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 13:55:37 -0400 Subject: [PATCH 16/22] Add todo --- packages/tailwindcss-language-server/src/project-locator.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 46294070..ad4159c4 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -599,7 +599,8 @@ class FileEntry { // Replace the file content with the processed CSS this.content = result.css } catch { - // + // TODO: Errors here should be surfaced in tests and possibly the user in + // `trace` logs or something like that } } From 05062be262c87b8dbcb997aee039b8b9e83fe39b Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 13:55:40 -0400 Subject: [PATCH 17/22] wip --- .../src/css/extract-source-directives.ts | 8 +++----- packages/tailwindcss-language-server/src/oxide.ts | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/tailwindcss-language-server/src/css/extract-source-directives.ts b/packages/tailwindcss-language-server/src/css/extract-source-directives.ts index 52887daf..9de33a9b 100644 --- a/packages/tailwindcss-language-server/src/css/extract-source-directives.ts +++ b/packages/tailwindcss-language-server/src/css/extract-source-directives.ts @@ -4,11 +4,9 @@ export function extractSourceDirectives(sources: string[]): Plugin { return { postcssPlugin: 'extract-at-rules', AtRule: { - source: (node) => { - if (node.params[0] !== '"' && node.params[0] !== "'") return - sources.push(node.params.slice(1, -1)) - - console.log(node.toString()) + source: ({ params }) => { + if (params[0] !== '"' && params[0] !== "'") return + sources.push(params.slice(1, -1)) }, }, } diff --git a/packages/tailwindcss-language-server/src/oxide.ts b/packages/tailwindcss-language-server/src/oxide.ts index c9f9dadf..54df00a0 100644 --- a/packages/tailwindcss-language-server/src/oxide.ts +++ b/packages/tailwindcss-language-server/src/oxide.ts @@ -84,8 +84,6 @@ export async function scan(options: ScanOptions): Promise { let resultV1: OxideV1.ScanResult | null = null let resultV2: OxideV2.ScanResult | null = null - console.log(options) - try { resultV2 = oxide.scanDir({ base: options.basePath, From c5892bd2affbbd415fc67d86769ee21e36a10bb3 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 13:55:48 -0400 Subject: [PATCH 18/22] Update Tailwind version in test --- .../tests/fixtures/v4/custom-source/package-lock.json | 2 +- .../tests/fixtures/v4/custom-source/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json index a029cc58..2bc33989 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "tailwindcss": "^4.0.0-alpha.18" + "tailwindcss": "^4.0.0-alpha.19" } }, "node_modules/tailwindcss": { diff --git a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json index 2d53a701..efa461d1 100644 --- a/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json +++ b/packages/tailwindcss-language-server/tests/fixtures/v4/custom-source/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "tailwindcss": "^4.0.0-alpha.18" + "tailwindcss": "^4.0.0-alpha.19" } } From f801cf8882a6558d1f95b03233de772887839837 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 14:02:07 -0400 Subject: [PATCH 19/22] Pull sources from all config entry files --- .../src/project-locator.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index ad4159c4..d9a912c4 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -505,12 +505,13 @@ async function* contentSelectorsFromCssConfig(entry: ConfigEntry): AsyncIterable } } else if (item.kind === 'auto' && !auto) { auto = true - let root = entry.entries[0] - for await (let pattern of detectContentFiles( - entry.packageRoot, - entry.path, - root?.sources ?? [], - )) { + + // Note: the file representing `entry` is not guaranteed to be the first + // file so we use `flatMap`` here to simplify the logic but none of the + // other entries should have sources. + let sources = entry.entries.flatMap((entry) => entry.sources) + + for await (let pattern of detectContentFiles(entry.packageRoot, entry.path, sources)) { yield { pattern, priority: DocumentSelectorPriority.CONTENT_FILE, From 9e1ce45df1f4108bdbf5e2185879279b52ec92a0 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 15 Aug 2024 14:03:43 -0400 Subject: [PATCH 20/22] Remove use of `.default` it should not be necessary The ESM version of Oxide has never had a default export --- packages/tailwindcss-language-server/src/oxide.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/src/oxide.ts b/packages/tailwindcss-language-server/src/oxide.ts index 54df00a0..8ed762a8 100644 --- a/packages/tailwindcss-language-server/src/oxide.ts +++ b/packages/tailwindcss-language-server/src/oxide.ts @@ -42,7 +42,7 @@ interface Oxide { } async function loadOxideAtPath(id: string): Promise { - let oxide = await import(id).then((o) => o.default || o) + let oxide = await import(id) // This is a much older, unsupport version of Oxide before v4.0.0-alpha.1 if (!oxide.scanDir) return null From 86b666cb31a15e4a70f099eaa43ed9dbce30a2b8 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Fri, 16 Aug 2024 15:45:39 +0200 Subject: [PATCH 21/22] Add support for new oxide API and version API based on package.json --- .../tailwindcss-language-server/src/oxide.ts | 73 +++++++++++++------ .../src/project-locator.ts | 3 + 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/packages/tailwindcss-language-server/src/oxide.ts b/packages/tailwindcss-language-server/src/oxide.ts index 8ed762a8..3f67036d 100644 --- a/packages/tailwindcss-language-server/src/oxide.ts +++ b/packages/tailwindcss-language-server/src/oxide.ts @@ -1,3 +1,5 @@ +import { lte } from 'tailwindcss-language-service/src/util/semver' + // This covers the Oxide API from v4.0.0-alpha.1 to v4.0.0-alpha.18 declare namespace OxideV1 { interface GlobEntry { @@ -13,7 +15,6 @@ declare namespace OxideV1 { interface ScanResult { files: Array globs: Array - candidates: Array } } @@ -32,19 +33,41 @@ declare namespace OxideV2 { interface ScanResult { files: Array globs: Array - candidates: Array + } +} + +// This covers the Oxide API from v4.0.0-alpha.20+ +declare namespace OxideV3 { + interface GlobEntry { + base: string + pattern: string + } + + interface ScannerOptions { + detectSources?: { base: string } + sources: Array + } + + interface ScannerConstructor { + new (options: ScannerOptions): Scanner + } + + interface Scanner { + files: Array + globs: Array } } interface Oxide { scanDir?(options: OxideV1.ScanOptions): OxideV1.ScanResult scanDir?(options: OxideV2.ScanOptions): OxideV2.ScanResult + Scanner?: OxideV3.ScannerConstructor } async function loadOxideAtPath(id: string): Promise { let oxide = await import(id) - // This is a much older, unsupport version of Oxide before v4.0.0-alpha.1 + // This is a much older, unsupported version of Oxide before v4.0.0-alpha.1 if (!oxide.scanDir) return null return oxide @@ -57,6 +80,7 @@ interface GlobEntry { interface ScanOptions { oxidePath: string + oxideVersion: string basePath: string sources: Array } @@ -64,7 +88,6 @@ interface ScanOptions { interface ScanResult { files: Array globs: Array - candidates: Array } /** @@ -81,32 +104,40 @@ export async function scan(options: ScanOptions): Promise { const oxide = await loadOxideAtPath(options.oxidePath) if (!oxide) return null - let resultV1: OxideV1.ScanResult | null = null - let resultV2: OxideV2.ScanResult | null = null - - try { - resultV2 = oxide.scanDir({ - base: options.basePath, - sources: options.sources, - }) - } catch { - resultV1 = oxide.scanDir({ + // V1 + if (lte(options.oxideVersion, '4.0.0-alpha.18')) { + let result = oxide.scanDir?.({ base: options.basePath, globs: true, }) + + return { + files: result.files, + globs: result.globs.map((g) => ({ base: g.base, pattern: g.glob })), + } } - if (resultV2) { + // V2 + if (lte(options.oxideVersion, '4.0.0-alpha.19')) { + let result = oxide.scanDir({ + base: options.basePath, + sources: options.sources, + }) + return { - files: resultV2.files, - globs: resultV2.globs, - candidates: resultV2.candidates, + files: result.files, + globs: result.globs, } } + // V3 + let scanner = new oxide.Scanner({ + detectSources: { base: options.basePath }, + sources: options.sources, + }) + return { - files: resultV1.files, - globs: resultV1.globs.map((g) => ({ base: g.base, pattern: g.glob })), - candidates: resultV1.candidates, + files: scanner.files, + globs: scanner.globs, } } diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index d9a912c4..50c3d426 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -529,9 +529,12 @@ async function* detectContentFiles( try { let oxidePath = resolveFrom(path.dirname(base), '@tailwindcss/oxide') oxidePath = pathToFileURL(oxidePath).href + let oxidePackageJsonPath = resolveFrom(path.dirname(base), '@tailwindcss/oxide/package.json') + let oxidePackageJson = JSON.parse(await fs.readFile(oxidePackageJsonPath, 'utf8')) let result = await oxide.scan({ oxidePath, + oxideVersion: oxidePackageJson.version, basePath: base, sources: sources.map((pattern) => ({ base: path.dirname(inputFile), From 9918c2218972cc3ee31e012e94d9239ab5f1e5b0 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Fri, 16 Aug 2024 15:49:46 +0200 Subject: [PATCH 22/22] Fix version for V2 oxide API --- packages/tailwindcss-language-server/src/oxide.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/src/oxide.ts b/packages/tailwindcss-language-server/src/oxide.ts index 3f67036d..ba9f2b5d 100644 --- a/packages/tailwindcss-language-server/src/oxide.ts +++ b/packages/tailwindcss-language-server/src/oxide.ts @@ -18,7 +18,7 @@ declare namespace OxideV1 { } } -// This covers the Oxide API from v4.0.0-alpha.19+ +// This covers the Oxide API from v4.0.0-alpha.19 declare namespace OxideV2 { interface GlobEntry { base: string