diff --git a/packages/@tailwindcss-cli/package.json b/packages/@tailwindcss-cli/package.json index 53344e308..d8b3ce970 100644 --- a/packages/@tailwindcss-cli/package.json +++ b/packages/@tailwindcss-cli/package.json @@ -12,7 +12,7 @@ "homepage": "https://tailwindcss.com", "scripts": { "lint": "tsc --noEmit", - "build": "tsup-node ./src/index.ts --format esm --minify --clean", + "build": "tsup-node", "dev": "pnpm run build -- --watch" }, "bin": { @@ -36,7 +36,8 @@ "picocolors": "^1.0.1", "postcss": "8.4.24", "postcss-import": "^16.1.0", - "tailwindcss": "workspace:^" + "tailwindcss": "workspace:^", + "internal-postcss-fix-relative-paths": "workspace:^" }, "devDependencies": { "@types/postcss-import": "^14.0.3" diff --git a/packages/@tailwindcss-cli/src/commands/build/index.ts b/packages/@tailwindcss-cli/src/commands/build/index.ts index 62084ec45..07f53fcc4 100644 --- a/packages/@tailwindcss-cli/src/commands/build/index.ts +++ b/packages/@tailwindcss-cli/src/commands/build/index.ts @@ -1,5 +1,6 @@ import watcher from '@parcel/watcher' import { IO, Parsing, scanDir, scanFiles, type ChangedContent } from '@tailwindcss/oxide' +import fixRelativePathsPlugin from 'internal-postcss-fix-relative-paths' import { Features, transform } from 'lightningcss' import { existsSync } from 'node:fs' import fs from 'node:fs/promises' @@ -259,6 +260,7 @@ function handleImports( return postcss() .use(atImport()) + .use(fixRelativePathsPlugin()) .process(input, { from: file }) .then((result) => [ result.css, diff --git a/packages/@tailwindcss-cli/tsup.config.ts b/packages/@tailwindcss-cli/tsup.config.ts new file mode 100644 index 000000000..236281270 --- /dev/null +++ b/packages/@tailwindcss-cli/tsup.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + format: ['esm'], + clean: true, + minify: true, + entry: ['src/index.ts'], + noExternal: ['internal-postcss-fix-relative-paths'], +}) diff --git a/packages/@tailwindcss-postcss/package.json b/packages/@tailwindcss-postcss/package.json index e9a6bc951..321aa5c19 100644 --- a/packages/@tailwindcss-postcss/package.json +++ b/packages/@tailwindcss-postcss/package.json @@ -12,7 +12,7 @@ "homepage": "https://tailwindcss.com", "scripts": { "lint": "tsc --noEmit", - "build": "tsup-node ./src/index.ts --format cjs,esm --dts --cjsInterop --splitting --minify --clean", + "build": "tsup-node", "dev": "pnpm run build -- --watch" }, "files": [ @@ -33,7 +33,8 @@ "@tailwindcss/oxide": "workspace:^", "lightningcss": "^1.25.1", "postcss-import": "^16.1.0", - "tailwindcss": "workspace:^" + "tailwindcss": "workspace:^", + "internal-postcss-fix-relative-paths": "workspace:^" }, "devDependencies": { "@types/node": "^20.12.12", diff --git a/packages/@tailwindcss-postcss/src/fixtures/example-project/src/relative-import.css b/packages/@tailwindcss-postcss/src/fixtures/example-project/src/relative-import.css new file mode 100644 index 000000000..48a30ab4d --- /dev/null +++ b/packages/@tailwindcss-postcss/src/fixtures/example-project/src/relative-import.css @@ -0,0 +1 @@ +@plugin '../plugin.js'; diff --git a/packages/@tailwindcss-postcss/src/index.test.ts b/packages/@tailwindcss-postcss/src/index.test.ts index 4d376db9a..07c674da0 100644 --- a/packages/@tailwindcss-postcss/src/index.test.ts +++ b/packages/@tailwindcss-postcss/src/index.test.ts @@ -144,7 +144,7 @@ describe('plugins', () => { let result = await processor.process( css` @import 'tailwindcss/utilities'; - @plugin 'internal-example-plugin'; + @plugin './plugin.js'; `, { from: INPUT_CSS_PATH }, ) @@ -166,6 +166,36 @@ describe('plugins', () => { `) }) + test('local CJS plugin from `@import`-ed file', async () => { + let processor = postcss([ + tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }), + ]) + + let result = await processor.process( + css` + @import 'tailwindcss/utilities'; + @import '../example-project/src/relative-import.css'; + `, + { from: `${__dirname}/fixtures/another-project/input.css` }, + ) + + expect(result.css.trim()).toMatchInlineSnapshot(` + ".underline { + text-decoration-line: underline; + } + + @media (inverted-colors: inverted) { + .inverted\\:flex { + display: flex; + } + } + + .hocus\\:underline:focus, .hocus\\:underline:hover { + text-decoration-line: underline; + }" + `) + }) + test('published CJS plugin', async () => { let processor = postcss([ tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }), diff --git a/packages/@tailwindcss-postcss/src/index.ts b/packages/@tailwindcss-postcss/src/index.ts index 30a0828a2..1d85d1268 100644 --- a/packages/@tailwindcss-postcss/src/index.ts +++ b/packages/@tailwindcss-postcss/src/index.ts @@ -2,9 +2,10 @@ import { scanDir } from '@tailwindcss/oxide' import fs from 'fs' import { Features, transform } from 'lightningcss' import path from 'path' -import postcss, { type AcceptedPlugin, type PluginCreator } from 'postcss' +import postcss, { AtRule, type AcceptedPlugin, type PluginCreator } from 'postcss' import postcssImport from 'postcss-import' import { compile } from 'tailwindcss' +import fixRelativePathsPlugin from '../../internal-postcss-fix-relative-paths/src' /** * A Map that can generate default values for keys that don't exist. @@ -48,114 +49,118 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin { } }) + let hasApply: boolean, hasTailwind: boolean + return { postcssPlugin: '@tailwindcss/postcss', plugins: [ // We need to run `postcss-import` first to handle `@import` rules. postcssImport(), + fixRelativePathsPlugin(), - (root, result) => { - let inputFile = result.opts.from ?? '' - let context = cache.get(inputFile) - - let rebuildStrategy: 'full' | 'incremental' = 'incremental' - - // Track file modification times to CSS files - { - let files = result.messages.flatMap((message) => { - if (message.type !== 'dependency') return [] - return message.file - }) - files.push(inputFile) - for (let file of files) { - let changedTime = fs.statSync(file, { throwIfNoEntry: false })?.mtimeMs ?? null - if (changedTime === null) { - if (file === inputFile) { - rebuildStrategy = 'full' - } - continue - } - - let prevTime = context.mtimes.get(file) - if (prevTime === changedTime) continue - - rebuildStrategy = 'full' - context.mtimes.set(file, changedTime) - } - } - - let hasApply = false - let hasTailwind = false - - root.walkAtRules((rule) => { + { + postcssPlugin: 'tailwindcss', + Once() { + // Reset some state between builds + hasApply = false + hasTailwind = false + }, + AtRule(rule: AtRule) { if (rule.name === 'apply') { hasApply = true } else if (rule.name === 'tailwind') { hasApply = true hasTailwind = true - // If we've found `@tailwind` then we already - // know we have to run a "full" build - return false } - }) + }, + OnceExit(root, { result }) { + let inputFile = result.opts.from ?? '' + let context = cache.get(inputFile) - // Do nothing if neither `@tailwind` nor `@apply` is used - if (!hasTailwind && !hasApply) return + let rebuildStrategy: 'full' | 'incremental' = 'incremental' - let css = '' - - // Look for candidates used to generate the CSS - let { candidates, files, globs } = scanDir({ base, globs: true }) - - // Add all found files as direct dependencies - for (let file of files) { - result.messages.push({ - type: 'dependency', - plugin: '@tailwindcss/postcss', - file, - parent: result.opts.from, - }) - } - - // Register dependencies so changes in `base` cause a rebuild while - // giving tools like Vite or Parcel a glob that can be used to limit - // the files that cause a rebuild to only those that match it. - for (let { base, glob } of globs) { - result.messages.push({ - type: 'dir-dependency', - plugin: '@tailwindcss/postcss', - dir: base, - glob, - parent: result.opts.from, - }) - } - - if (rebuildStrategy === 'full') { - let basePath = path.dirname(path.resolve(inputFile)) - let { build } = compile(root.toString(), { - loadPlugin: (pluginPath) => { - if (pluginPath[0] === '.') { - return require(path.resolve(basePath, pluginPath)) + // Track file modification times to CSS files + { + let files = result.messages.flatMap((message) => { + if (message.type !== 'dependency') return [] + return message.file + }) + files.push(inputFile) + for (let file of files) { + let changedTime = fs.statSync(file, { throwIfNoEntry: false })?.mtimeMs ?? null + if (changedTime === null) { + if (file === inputFile) { + rebuildStrategy = 'full' + } + continue } - return require(pluginPath) - }, - }) - context.build = build - css = build(hasTailwind ? candidates : []) - } else if (rebuildStrategy === 'incremental') { - css = context.build!(candidates) - } + let prevTime = context.mtimes.get(file) + if (prevTime === changedTime) continue - // Replace CSS - if (css !== context.css && optimize) { - context.optimizedCss = optimizeCss(css, { - minify: typeof optimize === 'object' ? optimize.minify : true, - }) - } - context.css = css - root.removeAll() - root.append(postcss.parse(optimize ? context.optimizedCss : context.css, result.opts)) + rebuildStrategy = 'full' + context.mtimes.set(file, changedTime) + } + } + + // Do nothing if neither `@tailwind` nor `@apply` is used + if (!hasTailwind && !hasApply) return + + let css = '' + + // Look for candidates used to generate the CSS + let { candidates, files, globs } = scanDir({ base, globs: true }) + + // Add all found files as direct dependencies + for (let file of files) { + result.messages.push({ + type: 'dependency', + plugin: '@tailwindcss/postcss', + file, + parent: result.opts.from, + }) + } + + // Register dependencies so changes in `base` cause a rebuild while + // giving tools like Vite or Parcel a glob that can be used to limit + // the files that cause a rebuild to only those that match it. + for (let { base, glob } of globs) { + result.messages.push({ + type: 'dir-dependency', + plugin: '@tailwindcss/postcss', + dir: base, + glob, + parent: result.opts.from, + }) + } + + if (rebuildStrategy === 'full') { + let basePath = path.dirname(path.resolve(inputFile)) + let { build } = compile(root.toString(), { + loadPlugin: (pluginPath) => { + if (pluginPath[0] === '.') { + return require(path.resolve(basePath, pluginPath)) + } + + return require(pluginPath) + }, + }) + context.build = build + css = build(hasTailwind ? candidates : []) + } else if (rebuildStrategy === 'incremental') { + css = context.build!(candidates) + } + + // Replace CSS + if (css !== context.css && optimize) { + context.optimizedCss = optimizeCss(css, { + minify: typeof optimize === 'object' ? optimize.minify : true, + }) + } + context.css = css + root.removeAll() + root.append(postcss.parse(optimize ? context.optimizedCss : context.css, result.opts)) + }, }, ], } diff --git a/packages/@tailwindcss-postcss/tsup.config.ts b/packages/@tailwindcss-postcss/tsup.config.ts new file mode 100644 index 000000000..08ec8092a --- /dev/null +++ b/packages/@tailwindcss-postcss/tsup.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + format: ['esm', 'cjs'], + clean: true, + minify: true, + splitting: true, + cjsInterop: true, + dts: true, + entry: ['src/index.ts'], + noExternal: ['internal-postcss-fix-relative-paths'], +}) diff --git a/packages/@tailwindcss-vite/package.json b/packages/@tailwindcss-vite/package.json index fbe03c8bd..5d10eecd8 100644 --- a/packages/@tailwindcss-vite/package.json +++ b/packages/@tailwindcss-vite/package.json @@ -11,7 +11,7 @@ "bugs": "https://github.com/tailwindlabs/tailwindcss/issues", "homepage": "https://tailwindcss.com", "scripts": { - "build": "tsup-node ./src/index.ts --format esm --dts --minify --clean", + "build": "tsup-node", "dev": "pnpm run build -- --watch" }, "files": [ @@ -30,10 +30,12 @@ "dependencies": { "@tailwindcss/oxide": "workspace:^", "lightningcss": "^1.25.1", + "postcss-load-config": "^6.0.1", "tailwindcss": "workspace:^" }, "devDependencies": { "@types/node": "^20.12.12", + "internal-postcss-fix-relative-paths": "workspace:^", "vite": "^5.2.11" }, "peerDependencies": { diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index d8a0924c5..a6903b02c 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -1,6 +1,8 @@ import { IO, Parsing, scanFiles } from '@tailwindcss/oxide' +import fixRelativePathsPlugin from 'internal-postcss-fix-relative-paths' import { Features, transform } from 'lightningcss' import path from 'path' +import postcssrc from 'postcss-load-config' import { compile } from 'tailwindcss' import type { Plugin, Rollup, Update, ViteDevServer } from 'vite' @@ -101,7 +103,7 @@ export default function tailwindcss(): Plugin[] { for (let plugin of cssPlugins) { if (!plugin.transform) continue - const transformHandler = + let transformHandler = 'handler' in plugin.transform! ? plugin.transform.handler : plugin.transform! try { @@ -152,6 +154,56 @@ export default function tailwindcss(): Plugin[] { }) }, + // Append the postcss-fix-relative-paths plugin + async config(config) { + let postcssConfig = config.css?.postcss + + if (typeof postcssConfig === 'string') { + // We expand string configs to their PostCSS config object similar to + // how Vite does it. + // See: https://github.com/vitejs/vite/blob/440783953a55c6c63cd09ec8d13728dc4693073d/packages/vite/src/node/plugins/css.ts#L1580 + let searchPath = typeof postcssConfig === 'string' ? postcssConfig : config.root + let parsedConfig = await postcssrc({}, searchPath).catch((e: Error) => { + if (!e.message.includes('No PostCSS Config found')) { + if (e instanceof Error) { + let { name, message, stack } = e + e.name = 'Failed to load PostCSS config' + e.message = `Failed to load PostCSS config (searchPath: ${searchPath}): [${name}] ${message}\n${stack}` + e.stack = '' // add stack to message to retain stack + throw e + } else { + throw new Error(`Failed to load PostCSS config: ${e}`) + } + } + return null + }) + if (parsedConfig !== null) { + postcssConfig = { + options: parsedConfig.options, + plugins: parsedConfig.plugins, + } as any + } else { + postcssConfig = {} + } + config.css = { postcss: postcssConfig } + } + + // postcssConfig is no longer a string after the above. This test is to + // avoid TypeScript errors below. + if (typeof postcssConfig === 'string') { + return + } + + if (!postcssConfig || !postcssConfig?.plugins) { + config.css = config.css || {} + config.css.postcss = postcssConfig || {} + config.css.postcss.plugins = [fixRelativePathsPlugin() as any, fixSvelte() as any] + } else { + postcssConfig.plugins.push(fixRelativePathsPlugin() as any) + postcssConfig.plugins.push(fixSvelte() as any) + } + }, + // Scan index.html for candidates transformIndexHtml(html) { let updated = scan(html, 'html') @@ -244,7 +296,11 @@ function getExtension(id: string) { function isTailwindCssFile(id: string, src: string) { if (id.includes('/.vite/')) return - return getExtension(id) === 'css' && src.includes('@tailwind') + const extension = getExtension(id) + const isTailwind = + (extension === 'css' && src.includes('@tailwind')) || + (extension === 'svelte' && id.endsWith('&lang.css')) + return isTailwind } function optimizeCss( @@ -270,3 +326,18 @@ function optimizeCss( errorRecovery: true, }).code.toString() } + +export function fixSvelte() { + return { + postcssPlugin: 'tailwindcss-postcss-fix-svelte', + OnceExit: (root: any) => { + const filename = root.source.input.file + if (!filename.endsWith('.svelte?svelte&type=style&lang.css')) { + return + } + const content = root.toString() + let compiled = compile(content.replace('@tailwind ', '@failwind '), {}).build(['']) + root.replaceWith(compiled.replace('@failwind ', ' @tailwind ')) + }, + } +} diff --git a/packages/@tailwindcss-vite/tsup.config.ts b/packages/@tailwindcss-vite/tsup.config.ts new file mode 100644 index 000000000..eaf99e82a --- /dev/null +++ b/packages/@tailwindcss-vite/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + format: ['esm'], + clean: true, + minify: true, + dts: true, + entry: ['src/index.ts'], + noExternal: ['internal-postcss-fix-relative-paths'], +}) diff --git a/packages/internal-postcss-fix-relative-paths/package.json b/packages/internal-postcss-fix-relative-paths/package.json new file mode 100644 index 000000000..2ffb3c7dd --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/package.json @@ -0,0 +1,27 @@ +{ + "name": "internal-postcss-fix-relative-paths", + "version": "0.0.0", + "private": true, + "scripts": { + "lint": "tsc --noEmit", + "build": "tsup-node ./src/index.ts --format cjs,esm --dts --cjsInterop --splitting --minify --clean", + "dev": "pnpm run build -- --watch" + }, + "files": [ + "dist/" + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js" + } + }, + "dependencies": {}, + "devDependencies": { + "@types/node": "^20.12.12", + "@types/postcss-import": "^14.0.3", + "postcss": "8.4.24", + "postcss-import": "^16.1.0" + } +} diff --git a/packages/internal-postcss-fix-relative-paths/src/fixtures/example-project/src/index.css b/packages/internal-postcss-fix-relative-paths/src/fixtures/example-project/src/index.css new file mode 100644 index 000000000..112e82e59 --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/fixtures/example-project/src/index.css @@ -0,0 +1,3 @@ +@content "./**/*.ts"; +@plugin "./plugin.js"; +@plugin "./what\"s-this.js"; diff --git a/packages/internal-postcss-fix-relative-paths/src/fixtures/example-project/src/invalid.css b/packages/internal-postcss-fix-relative-paths/src/fixtures/example-project/src/invalid.css new file mode 100644 index 000000000..9eeb9353e --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/fixtures/example-project/src/invalid.css @@ -0,0 +1,4 @@ +@plugin "/absolute/paths"; +@plugin "C:\Program Files\HAL 9000"; +@plugin "\\Media\Pictures\Worth\1000 words"; +@plugin "some-node-dep"; diff --git a/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/index.css b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/index.css new file mode 100644 index 000000000..2c014767b --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/index.css @@ -0,0 +1 @@ +@import '../../example-project/src/index.css'; diff --git a/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/invalid.css b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/invalid.css new file mode 100644 index 000000000..b69d455c0 --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/invalid.css @@ -0,0 +1 @@ +@import '../../example-project/src/invalid.css'; diff --git a/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/plugins-in-root.css b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/plugins-in-root.css new file mode 100644 index 000000000..d6d5f082c --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/plugins-in-root.css @@ -0,0 +1,5 @@ +@import './plugins-in-sibling.css'; + +@plugin './plugin-in-root.ts'; +@plugin '../plugin-in-root.ts'; +@plugin 'plugin-in-root'; diff --git a/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/plugins-in-sibling.css b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/plugins-in-sibling.css new file mode 100644 index 000000000..5df3cb061 --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/fixtures/external-import/src/plugins-in-sibling.css @@ -0,0 +1,3 @@ +@plugin './plugin-in-sibling.ts'; +@plugin '../plugin-in-sibling.ts'; +@plugin 'plugin-in-sibling'; diff --git a/packages/internal-postcss-fix-relative-paths/src/index.test.ts b/packages/internal-postcss-fix-relative-paths/src/index.test.ts new file mode 100644 index 000000000..c66699c65 --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/index.test.ts @@ -0,0 +1,56 @@ +import fs from 'node:fs' +import postcss from 'postcss' +import atImport from 'postcss-import' +import { describe, expect, test } from 'vitest' +import fixRelativePathsPlugin from '.' + +describe('fixRelativePathsPlugin', () => { + test('rewrites @content and @plugin to be relative to the initial css file', async () => { + let cssPath = `${__dirname}/fixtures/external-import/src/index.css` + let css = fs.readFileSync(cssPath, 'utf-8') + + let processor = postcss([atImport(), fixRelativePathsPlugin()]) + + let result = await processor.process(css, { from: cssPath }) + + expect(result.css.trim()).toMatchInlineSnapshot(` + "@content "../../example-project/src/**/*.ts"; + @plugin "../../example-project/src/plugin.js"; + @plugin "../../example-project/src/what\\"s-this.js";" + `) + }) + + test('should not rewrite non-relative paths', async () => { + let cssPath = `${__dirname}/fixtures/external-import/src/invalid.css` + let css = fs.readFileSync(cssPath, 'utf-8') + + let processor = postcss([atImport(), fixRelativePathsPlugin()]) + + let result = await processor.process(css, { from: cssPath }) + + expect(result.css.trim()).toMatchInlineSnapshot(` + "@plugin "/absolute/paths"; + @plugin "C:\\Program Files\\HAL 9000"; + @plugin "\\\\Media\\Pictures\\Worth\\1000 words"; + @plugin "some-node-dep";" + `) + }) + + test('should return relative paths even if the file is resolved in the same basedir as the root stylesheet', async () => { + let cssPath = `${__dirname}/fixtures/external-import/src/plugins-in-root.css` + let css = fs.readFileSync(cssPath, 'utf-8') + + let processor = postcss([atImport(), fixRelativePathsPlugin()]) + + let result = await processor.process(css, { from: cssPath }) + + expect(result.css.trim()).toMatchInlineSnapshot(` + "@plugin './plugin-in-sibling.ts'; + @plugin '../plugin-in-sibling.ts'; + @plugin 'plugin-in-sibling'; + @plugin './plugin-in-root.ts'; + @plugin '../plugin-in-root.ts'; + @plugin 'plugin-in-root';" + `) + }) +}) diff --git a/packages/internal-postcss-fix-relative-paths/src/index.ts b/packages/internal-postcss-fix-relative-paths/src/index.ts new file mode 100644 index 000000000..d16cb2214 --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/src/index.ts @@ -0,0 +1,101 @@ +import path from 'node:path' +import type { AtRule, Container, Plugin } from 'postcss' + +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 = getRoot(atRule)?.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 content = atRule.params.slice(1, -1) + + // We only want to rewrite relative paths. + if (!content.startsWith('./') && !content.startsWith('../')) { + return + } + + let rulePath = path.posix.join(path.posix.dirname(inputFilePath), content) + let relative = path.posix.relative(path.posix.dirname(rootPath), rulePath) + + // 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 + relative + quote + touched.add(atRule) + } + + function getRoot(node: AtRule | Container | undefined): Container | undefined { + if (node?.parent) { + return getRoot(node.parent as Container) + } + return node + } + + return { + postcssPlugin: 'tailwindcss-postcss-fix-relative-paths', + AtRule: { + content: fixRelativePath, + plugin: fixRelativePath, + // theme: function (atRule: AtRule, { postcss }: { postcss: any }) { + // if (touched.has(atRule)) { + // return + // } + // } + // apply: function (atRule: AtRule, { postcss }: { postcss: any }) { + // if (touched.has(atRule)) { + // return + // } + // if(atRule.name) + // if (atRule.params[0] === "'") { + // return + // } + // atRule.params = `'${atRule.params}'` + // touched.add(atRule) + // // Convert atRule to a comment + // // atRule.replaceWith( + // // postcss.rule({ + // // selector: '& .CUSTOM-foo-base476', + // // nodes: [], + // // }), + // // ) + // // atRule.before(postcss.comment({ text: '! custom' + atRule.toString() })) + // // if (atRule.name === 'apply') { + // // atRule.name = 'comment' + // // atRule.params = 'tailwindcss-apply' + // // return + // // } + // }, + }, + } +} diff --git a/packages/internal-postcss-fix-relative-paths/tsconfig.json b/packages/internal-postcss-fix-relative-paths/tsconfig.json new file mode 100644 index 000000000..6ae022f65 --- /dev/null +++ b/packages/internal-postcss-fix-relative-paths/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.base.json", +} diff --git a/packages/tailwindcss/src/index.ts b/packages/tailwindcss/src/index.ts index f324dfad8..28451437f 100644 --- a/packages/tailwindcss/src/index.ts +++ b/packages/tailwindcss/src/index.ts @@ -305,10 +305,15 @@ export function compile( if (css.includes('@apply')) { walk(ast, (node, { replaceWith }) => { if (node.kind === 'rule' && node.selector[0] === '@' && node.selector.startsWith('@apply')) { - let candidates = node.selector + let candidates: any = node.selector .slice(7 /* Ignore `@apply ` when parsing the selector */) .trim() - .split(/\s+/g) + + if (candidates[0] === "'" || candidates[0] === '"') { + candidates = candidates.slice(1, -1) + } + + candidates = candidates.split(/\s+/g) // Replace the `@apply` rule with the actual utility classes { diff --git a/packages/tailwindcss/theme.css b/packages/tailwindcss/theme.css index 190e51f09..bfdc8ebe3 100644 --- a/packages/tailwindcss/theme.css +++ b/packages/tailwindcss/theme.css @@ -435,7 +435,8 @@ --transition-timing-function-in: cubic-bezier(0.4, 0, 1, 1); --transition-timing-function-out: cubic-bezier(0, 0, 0.2, 1); --transition-timing-function-in-out: cubic-bezier(0.4, 0, 0.2, 1); - +} +@theme { @keyframes spin { to { transform: rotate(360deg); diff --git a/playgrounds/vite/package.json b/playgrounds/vite/package.json index 22db622e5..10a3ae499 100644 --- a/playgrounds/vite/package.json +++ b/playgrounds/vite/package.json @@ -9,10 +9,13 @@ "preview": "bun --bun vite preview" }, "dependencies": { + "@sveltejs/vite-plugin-svelte": "^3.1.1", "@tailwindcss/vite": "workspace:^", "@vitejs/plugin-react": "^4.3.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "svelte": "^4.2.18", + "svelte-preprocess": "^6.0.2", "tailwindcss": "workspace:^" }, "devDependencies": { diff --git a/playgrounds/vite/src/App.svelte b/playgrounds/vite/src/App.svelte new file mode 100644 index 000000000..40d883e00 --- /dev/null +++ b/playgrounds/vite/src/App.svelte @@ -0,0 +1,9 @@ + + +

Hello {name}!

+ + diff --git a/playgrounds/vite/src/app.css b/playgrounds/vite/src/app.css index adbd8e19f..e69de29bb 100644 --- a/playgrounds/vite/src/app.css +++ b/playgrounds/vite/src/app.css @@ -1,2 +0,0 @@ -@import 'tailwindcss'; -@plugin "./plugin.js"; diff --git a/playgrounds/vite/src/main.tsx b/playgrounds/vite/src/main.tsx index b8df681f3..fb363569d 100644 --- a/playgrounds/vite/src/main.tsx +++ b/playgrounds/vite/src/main.tsx @@ -1,9 +1,7 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import { App } from './app' +import App from './App.svelte' -ReactDOM.createRoot(document.getElementById('app')!).render( - - - , -) +const app = new App({ + target: document.getElementById('app'), +}) + +export default app diff --git a/playgrounds/vite/vite.config.ts b/playgrounds/vite/vite.config.ts index 888ede112..c2d25bd97 100644 --- a/playgrounds/vite/vite.config.ts +++ b/playgrounds/vite/vite.config.ts @@ -1,7 +1,35 @@ +import { svelte, vitePreprocess } from '@sveltejs/vite-plugin-svelte' import tailwindcss from '@tailwindcss/vite' -import react from '@vitejs/plugin-react' import { defineConfig } from 'vite' export default defineConfig({ - plugins: [react(), tailwindcss()], + plugins: [ + svelte({ + preprocess: [ + // sveltePreprocess({ + // aliases: [ + // ['tailwindcss', 'tailwindcss'], + // ['tailwind', 'tailwindcss'], + // ['postcss', 'tailwindcss'], + // ], + // /** Add a custom language preprocessor */ + // tailwindcss({ content, filename, attributes }) { + // let compiled = compile(content.replace('@tailwind ', '@failwind '), {}).build( + // Array.from(['']), + // ) + // console.log({ compiled, attributes }) + // return Promise.resolve({ + // code: compiled.replace('@failwind ', '@tailwind '), + // map: '', + // attributes, + // }) + // }, + // }), + vitePreprocess(), + ], + }), + tailwindcss(), + ], }) + +// @tailwindcss/svelte diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bcd2c2f73..046dd8cca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,6 +109,9 @@ importers: '@tailwindcss/oxide': specifier: workspace:^ version: link:../../crates/node + internal-postcss-fix-relative-paths: + specifier: workspace:^ + version: link:../internal-postcss-fix-relative-paths lightningcss: specifier: ^1.25.1 version: 1.25.1 @@ -137,6 +140,9 @@ importers: '@tailwindcss/oxide': specifier: workspace:^ version: link:../../crates/node + internal-postcss-fix-relative-paths: + specifier: workspace:^ + version: link:../internal-postcss-fix-relative-paths lightningcss: specifier: ^1.25.1 version: 1.25.1 @@ -168,6 +174,9 @@ importers: lightningcss: specifier: ^1.25.1 version: 1.25.1 + postcss-load-config: + specifier: ^6.0.1 + version: 6.0.1(postcss@8.4.38)(yaml@2.4.2) tailwindcss: specifier: workspace:^ version: link:../tailwindcss @@ -175,12 +184,30 @@ importers: '@types/node': specifier: ^20.12.12 version: 20.12.12 + internal-postcss-fix-relative-paths: + specifier: workspace:^ + version: link:../internal-postcss-fix-relative-paths vite: specifier: ^5.2.11 version: 5.2.11(@types/node@20.12.12)(lightningcss@1.25.1) packages/internal-example-plugin: {} + packages/internal-postcss-fix-relative-paths: + devDependencies: + '@types/node': + specifier: ^20.12.12 + version: 20.12.12 + '@types/postcss-import': + specifier: ^14.0.3 + version: 14.0.3 + postcss: + specifier: 8.4.24 + version: 8.4.24 + postcss-import: + specifier: ^16.1.0 + version: 16.1.0(postcss@8.4.24) + packages/tailwindcss: devDependencies: '@tailwindcss/oxide': @@ -235,6 +262,9 @@ importers: playgrounds/vite: dependencies: + '@sveltejs/vite-plugin-svelte': + specifier: ^3.1.1 + version: 3.1.1(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)) '@tailwindcss/vite': specifier: workspace:^ version: link:../../packages/@tailwindcss-vite @@ -247,6 +277,12 @@ importers: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + svelte: + specifier: ^4.2.18 + version: 4.2.18 + svelte-preprocess: + specifier: ^6.0.2 + version: 6.0.2(@babel/core@7.24.6)(postcss-load-config@6.0.1(postcss@8.4.38))(postcss@8.4.38)(svelte@4.2.18)(typescript@5.4.5) tailwindcss: specifier: workspace:^ version: link:../../packages/tailwindcss @@ -1008,6 +1044,21 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sveltejs/vite-plugin-svelte-inspector@2.1.0': + resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + + '@sveltejs/vite-plugin-svelte@3.1.1': + resolution: {integrity: sha512-rimpFEAboBBHIlzISibg94iP09k/KYdHgVhJlcsTfn7KMBhc70jFX/GRWkRdFCc2fdnk+4+Bdfej23cMDnJS6A==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + '@swc/helpers@0.5.2': resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} @@ -1213,6 +1264,10 @@ packages: axobject-query@3.2.1: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1237,6 +1292,7 @@ packages: bun@1.1.10: resolution: {integrity: sha512-qOJXrQZSzJ5DbJMt47GZGWtUSmIkbwD7fPSN/XS/T46D4cTTnPK46QDHlyC8VD+Anvs6uKNwuwKIyB31kUdHmQ==} + cpu: [arm64, x64] os: [darwin, linux, win32] hasBin: true @@ -1287,6 +1343,9 @@ packages: client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -1317,6 +1376,10 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1359,6 +1422,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -1853,6 +1920,9 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -1973,6 +2043,10 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -2057,6 +2131,9 @@ packages: resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} engines: {node: '>=14'} + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2091,6 +2168,9 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -2288,6 +2368,9 @@ packages: pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -2338,6 +2421,24 @@ packages: ts-node: optional: true + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -2618,6 +2719,53 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svelte-hmr@0.16.0: + resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + + svelte-preprocess@6.0.2: + resolution: {integrity: sha512-OvDTLfaOkkhjprbDKO0SOCkjNYuHy16dbD4SpqbIi6QiabOMHxRT4km5/dzbFFkmW1L0E2INF3MFltG2pgOyKQ==} + engines: {node: '>= 18.0.0'} + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + postcss: ^7 || ^8 + postcss-load-config: '>=3' + pug: ^3.0.0 + sass: ^1.26.8 + stylus: '>=0.55' + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.100 || ^5.0.0 + typescript: ^5.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + + svelte@4.2.18: + resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} + engines: {node: '>=16'} + tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} @@ -2822,6 +2970,14 @@ packages: terser: optional: true + vitefu@0.2.5: + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest@1.6.0: resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -3451,6 +3607,29 @@ snapshots: '@sinclair/typebox@0.27.8': {} + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)))(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1))': + dependencies: + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)) + debug: 4.3.4 + svelte: 4.2.18 + vite: 5.2.11(@types/node@20.12.12)(lightningcss@1.25.1) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)))(svelte@4.2.18)(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)) + debug: 4.3.4 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.10 + svelte: 4.2.18 + svelte-hmr: 0.16.0(svelte@4.2.18) + vite: 5.2.11(@types/node@20.12.12)(lightningcss@1.25.1) + vitefu: 0.2.5(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)) + transitivePeerDependencies: + - supports-color + '@swc/helpers@0.5.2': dependencies: tslib: 2.6.2 @@ -3732,6 +3911,8 @@ snapshots: dependencies: dequal: 2.0.3 + axobject-query@4.1.0: {} + balanced-match@1.0.2: {} binary-extensions@2.3.0: {} @@ -3829,6 +4010,14 @@ snapshots: client-only@0.0.1: {} + code-red@1.0.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + '@types/estree': 1.0.5 + acorn: 8.11.3 + estree-walker: 3.0.3 + periscopic: 3.1.0 + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -3855,6 +4044,11 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.0 + csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} @@ -3891,6 +4085,8 @@ snapshots: deep-is@0.1.4: {} + deepmerge@4.3.1: {} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 @@ -4092,7 +4288,7 @@ snapshots: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.1(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -4116,7 +4312,7 @@ snapshots: enhanced-resolve: 5.16.1 eslint: 8.57.0 eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -4138,7 +4334,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -4584,6 +4780,10 @@ snapshots: is-path-inside@3.0.3: {} + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + is-regex@1.1.4: dependencies: call-bind: 1.0.7 @@ -4702,6 +4902,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kleur@4.1.5: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -4765,6 +4967,8 @@ snapshots: mlly: 1.7.0 pkg-types: 1.1.1 + locate-character@3.0.0: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -4801,6 +5005,8 @@ snapshots: dependencies: semver: 7.6.2 + mdn-data@2.0.30: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -4996,6 +5202,12 @@ snapshots: pathval@1.1.1: {} + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -5034,6 +5246,13 @@ snapshots: optionalDependencies: postcss: 8.4.24 + postcss-load-config@6.0.1(postcss@8.4.38)(yaml@2.4.2): + dependencies: + lilconfig: 3.1.1 + optionalDependencies: + postcss: 8.4.38 + yaml: 2.4.2 + postcss-value-parser@4.2.0: {} postcss@8.4.24: @@ -5335,6 +5554,36 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svelte-hmr@0.16.0(svelte@4.2.18): + dependencies: + svelte: 4.2.18 + + svelte-preprocess@6.0.2(@babel/core@7.24.6)(postcss-load-config@6.0.1(postcss@8.4.38))(postcss@8.4.38)(svelte@4.2.18)(typescript@5.4.5): + dependencies: + svelte: 4.2.18 + optionalDependencies: + '@babel/core': 7.24.6 + postcss: 8.4.38 + postcss-load-config: 6.0.1(postcss@8.4.38)(yaml@2.4.2) + typescript: 5.4.5 + + svelte@4.2.18: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + '@types/estree': 1.0.5 + acorn: 8.11.3 + aria-query: 5.3.0 + axobject-query: 4.1.0 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.10 + periscopic: 3.1.0 + tapable@2.2.1: {} test-exclude@6.0.0: @@ -5542,6 +5791,10 @@ snapshots: fsevents: 2.3.3 lightningcss: 1.25.1 + vitefu@0.2.5(vite@5.2.11(@types/node@20.12.12)(lightningcss@1.25.1)): + optionalDependencies: + vite: 5.2.11(@types/node@20.12.12)(lightningcss@1.25.1) + vitest@1.6.0(@types/node@20.12.12)(lightningcss@1.25.1): dependencies: '@vitest/expect': 1.6.0