feat: init

This commit is contained in:
2026-02-13 22:02:30 +01:00
commit 8f9ff830fb
16711 changed files with 3307340 additions and 0 deletions

21
node_modules/@nuxtjs/tailwindcss/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Nuxt Community
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

113
node_modules/@nuxtjs/tailwindcss/README.md generated vendored Normal file
View File

@@ -0,0 +1,113 @@
[![@nuxtjs/tailwindcss](https://tailwindcss.nuxtjs.org/social-card.png)](https://tailwindcss.nuxtjs.org)
# Nuxt Tailwind
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]
[![Nuxt][nuxt-src]][nuxt-href]
[![Tailwind CSS][tw-src]][tw-href]
[![Volta board][volta-src]][volta-href]
Enable [Tailwind CSS](https://tailwindcss.com) for [Nuxt](https://nuxt.com) ⚡️
[📖  Documentation](https://tailwindcss.nuxtjs.org) | [▶️ Play online](https://stackblitz.com/github/nuxt-modules/tailwindcss) | [✨  Release Notes](https://github.com/nuxt-modules/tailwindcss/releases)
## Features
- 👌  Zero configuration to start
- 🪄  Includes [CSS Nesting](https://drafts.csswg.org/css-nesting-1/) with [postcss-nesting](https://github.com/csstools/postcss-nesting)
- 🎨  Discover your Tailwind Config & Colors *([see video](https://tailwindcss.nuxtjs.org/getting-started/module-options#viewer))*
- ⚙️  [Reference your Tailwind config](https://tailwindcss.nuxtjs.org/tailwindcss/configuration/#referencing-in-the-application) in your app
- 📦  Extendable by [Nuxt modules](https://nuxt.com/modules) using [hooks](https://tailwindcss.nuxtjs.org/tailwindcss/config#hooks)
- 🚀  Supports both [Nuxt 3](https://nuxt.com) and [Nuxt 2](https://v2.nuxt.com/)
## Quick Setup
Add `@nuxtjs/tailwindcss` using the [Nuxt CLI](https://github.com/nuxt/cli) to your project
```bash
npx nuxi@latest module add tailwindcss
```
<details>
<summary>..or install using your dependency manager</summary>
```bash
# Using pnpm
pnpm add --save-dev @nuxtjs/tailwindcss
# Using yarn
yarn add --dev @nuxtjs/tailwindcss
# Using npm
npm install --save-dev @nuxtjs/tailwindcss
```
and then to the `modules` section of `nuxt.config.{ts,js}`
```ts
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss'
]
})
```
</details>
That's it! You can now use Tailwind classes in your Nuxt app ✨
## Contributing
You can contribute to this module online:
[![Edit @nuxtjs/tailwindcss in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/nuxt-modules/tailwindcss/tree/main/?fontsize=14&hidenavigation=1&theme=dark)
[![Edit @nuxtjs/tailwindcss in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https://pr.new/nuxt-modules/tailwindcss)
<details>
<summary>..or locally</summary>
1. Clone this repository
2. Install dependencies using `pnpm i`
3. Prepare for development using `pnpm dev:prepare`
4. Start development server using `pnpm dev`
</details>
### Docs
[![Nuxt UI Pro](https://img.shields.io/badge/Made%20with-Nuxt%20UI%20Pro-00DC82?logo=nuxt.js&labelColor=020420)](https://ui.nuxt.com/pro)
You can run `docs/` locally by using `pnpm docs:dev`, or to run a build:
1. Make sure to add your [Nuxt UI Pro](https://ui.nuxt.com/pro) license in the `.env` file before building the application.
2. Run SSG build using `pnpm docs:build`
3. Review the production build locally using `pnpm docs:preview`
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
## License
[MIT](./LICENSE) - Made with 💚
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/tailwindcss/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-version-href]: https://npmjs.com/package/@nuxtjs/tailwindcss
[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxtjs/tailwindcss.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-downloads-href]: https://npmjs.com/package/@nuxtjs/tailwindcss
[license-src]: https://img.shields.io/npm/l/@nuxtjs/tailwindcss.svg?style=flat&colorA=18181B&colorB=28CF8D
[license-href]: https://npmjs.com/package/@nuxtjs/tailwindcss
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?&logo=nuxt
[nuxt-href]: https://nuxt.com
[tw-src]: https://img.shields.io/badge/tailwindcss-0F172A?&logo=tailwindcss
[tw-href]: https://tailwindcss.com
[volta-src]: https://user-images.githubusercontent.com/904724/209143798-32345f6c-3cf8-4e06-9659-f4ace4a6acde.svg
[volta-href]: https://volta.net/nuxt-modules/tailwindcss?utm_source=nuxt_tailwind_readme

8
node_modules/@nuxtjs/tailwindcss/dist/config-ctx.cjs generated vendored Normal file
View File

@@ -0,0 +1,8 @@
'use strict';
const config = require('./config.cjs');
require('c12');
require('unctx');
require('@nuxt/kit');
config.ctx.set(true);

View File

@@ -0,0 +1,2 @@
export { }

View File

@@ -0,0 +1,2 @@
export { }

View File

@@ -0,0 +1,2 @@
export { }

6
node_modules/@nuxtjs/tailwindcss/dist/config-ctx.mjs generated vendored Normal file
View File

@@ -0,0 +1,6 @@
import { ctx } from './config.mjs';
import 'c12';
import 'unctx';
import '@nuxt/kit';
ctx.set(true);

22
node_modules/@nuxtjs/tailwindcss/dist/config.cjs generated vendored Normal file
View File

@@ -0,0 +1,22 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const c12 = require('c12');
const unctx = require('unctx');
const kit = require('@nuxt/kit');
const ctx = unctx.getContext("tw-config-ctx");
c12.createDefineConfig();
const defineConfig = (config) => {
const isNuxt = !!kit.tryUseNuxt();
if (isNuxt || ctx.tryUse()) {
return config;
}
const nuxtTwConfig = kit.requireModule("./.nuxt/tailwind/postcss.mjs", { paths: [process.cwd()] });
return nuxtTwConfig?.default || nuxtTwConfig;
};
exports.ctx = ctx;
exports.default = defineConfig;
exports.defineConfig = defineConfig;

9
node_modules/@nuxtjs/tailwindcss/dist/config.d.cts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import * as c12 from 'c12';
import * as tailwindcss_types_config from 'tailwindcss/types/config';
import * as unctx from 'unctx';
declare const ctx: unctx.UseContext<boolean>;
declare const _defineConfig: c12.DefineConfig<Partial<tailwindcss_types_config.Config>, c12.ConfigLayerMeta>;
declare const defineConfig: typeof _defineConfig;
export { ctx, defineConfig as default, defineConfig };

9
node_modules/@nuxtjs/tailwindcss/dist/config.d.mts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import * as c12 from 'c12';
import * as tailwindcss_types_config from 'tailwindcss/types/config';
import * as unctx from 'unctx';
declare const ctx: unctx.UseContext<boolean>;
declare const _defineConfig: c12.DefineConfig<Partial<tailwindcss_types_config.Config>, c12.ConfigLayerMeta>;
declare const defineConfig: typeof _defineConfig;
export { ctx, defineConfig as default, defineConfig };

9
node_modules/@nuxtjs/tailwindcss/dist/config.d.ts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import * as c12 from 'c12';
import * as tailwindcss_types_config from 'tailwindcss/types/config';
import * as unctx from 'unctx';
declare const ctx: unctx.UseContext<boolean>;
declare const _defineConfig: c12.DefineConfig<Partial<tailwindcss_types_config.Config>, c12.ConfigLayerMeta>;
declare const defineConfig: typeof _defineConfig;
export { ctx, defineConfig as default, defineConfig };

16
node_modules/@nuxtjs/tailwindcss/dist/config.mjs generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import { createDefineConfig } from 'c12';
import { getContext } from 'unctx';
import { tryUseNuxt, requireModule } from '@nuxt/kit';
const ctx = getContext("tw-config-ctx");
createDefineConfig();
const defineConfig = (config) => {
const isNuxt = !!tryUseNuxt();
if (isNuxt || ctx.tryUse()) {
return config;
}
const nuxtTwConfig = requireModule("./.nuxt/tailwind/postcss.mjs", { paths: [process.cwd()] });
return nuxtTwConfig?.default || nuxtTwConfig;
};
export { ctx, defineConfig as default, defineConfig };

32
node_modules/@nuxtjs/tailwindcss/dist/merger.cjs generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict';
const defu = require('defu');
const klona = require('klona');
const isJSObject = (value) => typeof value === "object" && !Array.isArray(value);
const configMerger = (base, ...defaults) => {
if (!base) {
return klona.klona(defaults[0]);
}
return defu.createDefu((obj, key, value) => {
if (key === "content") {
if (isJSObject(obj[key]) && Array.isArray(value)) {
obj[key] = { ...obj[key], files: [...obj[key]["files"] || [], ...value] };
return true;
} else if (Array.isArray(obj[key]) && isJSObject(value)) {
obj[key] = { ...value, files: [...obj[key], ...value.files || []] };
return true;
}
if (obj[key] && typeof value === "function") {
obj[key] = value(Array.isArray(obj[key]) ? obj[key] : obj[key]["files"]);
return true;
}
if (typeof obj[key] === "function" && value) {
obj[key] = obj[key](Array.isArray(value) ? value : value["files"]);
return true;
}
}
})(klona.klona(base), ...defaults.map(klona.klona));
};
module.exports = configMerger;

14
node_modules/@nuxtjs/tailwindcss/dist/merger.d.cts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import { T as TWConfig } from './shared/tailwindcss.7c01d049.cjs';
import 'tailwindcss/resolveConfig';
import 'tailwindcss';
import 'nuxt/kit';
type Input = Partial<TWConfig> | Record<PropertyKey, any> | null | undefined;
/**
* Merges Tailwind CSS configuration objects. This has special logic to merge Content as Array or Object.
*
* Read <https://tailwindcss.com/docs/content-configuration>.
*/
declare const _default: (base: Input, ...defaults: Input[]) => Partial<TWConfig>;
export { _default as default };

14
node_modules/@nuxtjs/tailwindcss/dist/merger.d.mts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import { T as TWConfig } from './shared/tailwindcss.7c01d049.mjs';
import 'tailwindcss/resolveConfig';
import 'tailwindcss';
import 'nuxt/kit';
type Input = Partial<TWConfig> | Record<PropertyKey, any> | null | undefined;
/**
* Merges Tailwind CSS configuration objects. This has special logic to merge Content as Array or Object.
*
* Read <https://tailwindcss.com/docs/content-configuration>.
*/
declare const _default: (base: Input, ...defaults: Input[]) => Partial<TWConfig>;
export { _default as default };

14
node_modules/@nuxtjs/tailwindcss/dist/merger.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import { T as TWConfig } from './shared/tailwindcss.7c01d049.js';
import 'tailwindcss/resolveConfig';
import 'tailwindcss';
import 'nuxt/kit';
type Input = Partial<TWConfig> | Record<PropertyKey, any> | null | undefined;
/**
* Merges Tailwind CSS configuration objects. This has special logic to merge Content as Array or Object.
*
* Read <https://tailwindcss.com/docs/content-configuration>.
*/
declare const _default: (base: Input, ...defaults: Input[]) => Partial<TWConfig>;
export { _default as default };

30
node_modules/@nuxtjs/tailwindcss/dist/merger.mjs generated vendored Normal file
View File

@@ -0,0 +1,30 @@
import { createDefu } from 'defu';
import { klona } from 'klona';
const isJSObject = (value) => typeof value === "object" && !Array.isArray(value);
const configMerger = (base, ...defaults) => {
if (!base) {
return klona(defaults[0]);
}
return createDefu((obj, key, value) => {
if (key === "content") {
if (isJSObject(obj[key]) && Array.isArray(value)) {
obj[key] = { ...obj[key], files: [...obj[key]["files"] || [], ...value] };
return true;
} else if (Array.isArray(obj[key]) && isJSObject(value)) {
obj[key] = { ...value, files: [...obj[key], ...value.files || []] };
return true;
}
if (obj[key] && typeof value === "function") {
obj[key] = value(Array.isArray(obj[key]) ? obj[key] : obj[key]["files"]);
return true;
}
if (typeof obj[key] === "function" && value) {
obj[key] = obj[key](Array.isArray(value) ? value : value["files"]);
return true;
}
}
})(klona(base), ...defaults.map(klona));
};
export { configMerger as default };

615
node_modules/@nuxtjs/tailwindcss/dist/module.cjs generated vendored Normal file
View File

@@ -0,0 +1,615 @@
'use strict';
const pathe = require('pathe');
const kit = require('@nuxt/kit');
const pkgTypes = require('pkg-types');
const node_fs = require('node:fs');
const defu = require('defu');
const consola = require('consola');
const unctx = require('unctx');
const utils = require('consola/utils');
const h3 = require('h3');
const ufo = require('ufo');
const c12 = require('c12');
const merger = require('./merger.cjs');
const utils$1 = require('ohash/utils');
require('klona');
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
const name = "@nuxtjs/tailwindcss";
const version = "6.14.0";
const configKey = "tailwindcss";
const compatibility = {
nuxt: "^2.9.0 || >=3.0.0-rc.1"
};
async function resolveCSSPath(cssPath, nuxt = kit.useNuxt()) {
if (typeof cssPath === "string") {
const _cssPath = await kit.resolvePath(cssPath, { extensions: [".css", ".sass", ".scss", ".less", ".styl"] });
return node_fs.existsSync(_cssPath) ? [_cssPath, `Using Tailwind CSS from ~/${pathe.relative(nuxt.options.srcDir, _cssPath)}`] : await kit.tryResolveModule("tailwindcss/package.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href))).then((twLocation) => twLocation ? [pathe.join(twLocation, "../tailwind.css"), "Using default Tailwind CSS file"] : Promise.reject("Unable to resolve tailwindcss. Is it installed?"));
} else {
return [
false,
"No Tailwind CSS file found. Skipping..."
];
}
}
const resolveBoolObj = (config, fb) => defu.defu(typeof config === "object" ? config : {}, fb);
const resolveViewerConfig = (config) => resolveBoolObj(config, { endpoint: "/_tailwind", exportViewer: false });
const resolveExposeConfig = (config) => resolveBoolObj(config, { alias: "#tailwind-config", level: 2 });
const resolveEditorSupportConfig = (config) => resolveBoolObj(config, { autocompleteUtil: true, generateConfig: false });
async function resolveInjectPosition(css, position = "first") {
if (typeof position === "number") {
return ~~Math.min(position, css.length + 1);
}
if (typeof position === "string") {
switch (position) {
case "first":
return 0;
case "last":
return css.length;
}
}
if (typeof position === "object") {
const minIndex = "after" in position ? css.indexOf(await kit.resolvePath(position.after)) + 1 : 0;
const maxIndex = "before" in position ? css.indexOf(await kit.resolvePath(position.before)) : css.length;
if ([minIndex, maxIndex].includes(-1) || "after" in position && minIndex === 0) {
throw new Error(`\`injectPosition\` specifies a file which does not exists on CSS stack: ` + JSON.stringify(position));
}
if (minIndex > maxIndex) {
throw new Error(`\`injectPosition\` specifies a relative location \`${minIndex}\` that cannot be resolved (i.e., \`after\` orders \`before\` may be reversed): ` + JSON.stringify(position));
}
return "after" in position ? minIndex : maxIndex;
}
throw new Error("invalid `injectPosition`: " + JSON.stringify(position));
}
const logger = kit.useLogger("nuxt:tailwindcss");
const twCtx = unctx.getContext("twcss");
const { set } = twCtx;
twCtx.set = (instance, replace = true) => {
set(defu.defu(instance, twCtx.tryUse()), replace);
};
const NON_ALPHANUMERIC_RE = /^[0-9a-z]+$/i;
const isJSObject = (value) => typeof value === "object" && !Array.isArray(value);
const createExposeTemplates = (config, nuxt = kit.useNuxt()) => {
const templates = [];
const getTWConfig = (objPath = [], twConfig = twCtx.use().config) => objPath.reduce((prev, curr) => prev?.[curr], twConfig);
const populateMap = (obj = twCtx.use().config, path = [], level = 1) => {
Object.entries(obj).forEach(([key, value = {}]) => {
const subpathComponents = path.concat(key);
const subpath = subpathComponents.join("/");
if (level >= config.level || !isJSObject(value) || Object.keys(value).find((k) => !k.match(NON_ALPHANUMERIC_RE))) {
templates.push(kit.addTemplate({
filename: `tailwind/expose/${subpath}.mjs`,
getContents: () => {
const _value = getTWConfig(subpathComponents);
if (isJSObject(_value)) {
const [validKeys, invalidKeys] = [[], []];
Object.keys(_value).forEach((i) => (NON_ALPHANUMERIC_RE.test(i) ? validKeys : invalidKeys).push(i));
return [
`${validKeys.map((i) => `const _${i} = ${JSON.stringify(_value[i])}`).join("\n")}`,
`const config = { ${validKeys.map((i) => `"${i}": _${i}, `).join("")}${invalidKeys.map((i) => `"${i}": ${JSON.stringify(_value[i])}, `).join("")} }`,
`export { config as default${validKeys.length > 0 ? ", _" : ""}${validKeys.join(", _")} }`
].join("\n");
}
return `export default ${JSON.stringify(_value, null, 2)}`;
},
write: config.write
}));
} else {
populateMap(value, path.concat(key), level + 1);
templates.push(kit.addTemplate({
filename: `tailwind/expose/${subpath}.mjs`,
getContents: () => {
const _value = getTWConfig(subpathComponents);
const values = Object.keys(_value);
return [
`${values.map((v) => `import _${v} from "./${key}/${v}.mjs"`).join("\n")}`,
`const config = { ${values.map((k) => `"${k}": _${k}`).join(", ")} }`,
`export { config as default${values.length > 0 ? ", _" : ""}${values.join(", _")} }`
].join("\n");
},
write: config.write
}));
}
});
};
populateMap();
const entryTemplate = kit.addTemplate({
filename: "tailwind/expose/index.mjs",
getContents: () => {
const _tailwindConfig = getTWConfig();
const configOptions = Object.keys(_tailwindConfig);
return [
`${configOptions.map((v) => `import ${v} from "#build/tailwind/expose/${v}.mjs"`).join("\n")}`,
`const config = { ${configOptions.join(", ")} }`,
`export { config as default, ${configOptions.join(", ")} }`
].join("\n");
},
write: true
});
templates.push(kit.addTypeTemplate({
filename: "types/tailwind.config.d.ts",
getContents: () => {
const _tailwindConfig = getTWConfig();
const declareModule = (obj, path = [], level = 1) => Object.entries(obj).map(([key, value = {}]) => {
const subpath = path.concat(key).join("/");
if (level >= config.level || !isJSObject(value) || Object.keys(value).find((k) => !k.match(NON_ALPHANUMERIC_RE))) {
if (isJSObject(value)) {
const [validKeys, invalidKeys] = [[], []];
Object.keys(value).forEach((i) => (NON_ALPHANUMERIC_RE.test(i) ? validKeys : invalidKeys).push(i));
return `declare module "${config.alias}/${subpath}" { ${validKeys.map((i) => `export const _${i}: ${JSON.stringify(value[i])};`).join("")} const defaultExport: { ${validKeys.map((i) => `"${i}": typeof _${i}, `).join("")}${invalidKeys.map((i) => `"${i}": ${JSON.stringify(value[i])}, `).join("")} }; export default defaultExport; }
`;
}
return `declare module "${config.alias}/${subpath}" { const defaultExport: ${JSON.stringify(value)}; export default defaultExport; }
`;
}
const values = Object.keys(value);
return declareModule(value, path.concat(key), level + 1).join("") + `declare module "${config.alias}/${subpath}" {${Object.keys(value).map((v) => ` export const _${v}: typeof import("${config.alias}/${pathe.join(`${key}/${subpath}`, `../${v}`)}")["default"];`).join("")} const defaultExport: { ${values.map((k) => `"${k}": typeof _${k}`).join(", ")} }; export default defaultExport; }
`;
});
const configOptions = Object.keys(_tailwindConfig);
return declareModule(_tailwindConfig).join("") + `declare module "${config.alias}" {${configOptions.map((v) => ` export const ${v}: typeof import("${pathe.join(config.alias, v)}")["default"];`).join("")} const defaultExport: { ${configOptions.map((v) => `"${v}": typeof ${v}`)} }; export default defaultExport; }`;
}
}));
templates.push(entryTemplate);
nuxt.options.alias[config.alias] = pathe.dirname(entryTemplate.dst);
return templates.map((t) => t.dst);
};
const setupViewer = async (twConfig, config, nuxt = kit.useNuxt()) => {
const route = ufo.joinURL(nuxt.options.app?.baseURL, config.endpoint);
const [routeWithSlash, routeWithoutSlash] = [ufo.withTrailingSlash(route), ufo.withoutTrailingSlash(route)];
const viewerServer = await Promise.all([
// @ts-expect-error untyped package export
import('tailwind-config-viewer/server/index.js').then((r) => r.default || r),
typeof twConfig === "string" ? import('tailwindcss/loadConfig.js').then((r) => r.default || r).then((loadConfig) => () => loadConfig(twConfig)) : () => twConfig
]).then(([server, tailwindConfigProvider]) => server({ tailwindConfigProvider }).asMiddleware());
const viewerDevMiddleware = h3.eventHandler((event) => viewerServer(event.node?.req || event.req, event.node?.res || event.res));
if (!kit.isNuxtMajorVersion(2, nuxt)) {
kit.addDevServerHandler({
handler: h3.eventHandler((event) => {
if (event.path === routeWithoutSlash) {
return h3.sendRedirect(event, routeWithSlash, 301);
}
})
});
kit.addDevServerHandler({ route, handler: viewerDevMiddleware });
} else {
nuxt.options.serverMiddleware.push(
// @ts-expect-error untyped handler parameters
(req, res, next) => {
if (req.url === routeWithoutSlash) {
return h3.sendRedirect(new h3.H3Event(req, res), routeWithSlash, 301);
}
next();
},
// @ts-expect-error untyped handler parameters
{ route, handler: (req, res) => viewerDevMiddleware(new h3.H3Event(req, res)) }
);
}
nuxt.hook("devtools:customTabs", (tabs) => {
tabs?.push({
title: "Tailwind CSS",
name: "tailwindcss",
icon: "logos-tailwindcss-icon",
category: "modules",
view: { type: "iframe", src: route }
});
});
const shouldLogUrl = "devtools" in nuxt.options ? !nuxt.options.devtools.enabled : true;
shouldLogUrl && nuxt.hook("listen", (_, listener) => {
const viewerUrl = ufo.cleanDoubleSlashes(ufo.joinURL(listener.url, config.endpoint));
logger.info(`Tailwind Viewer: ${utils.colors.underline(utils.colors.yellow(ufo.withTrailingSlash(viewerUrl)))}`);
});
};
const exportViewer = async (twConfig, config, nuxt = kit.useNuxt()) => {
if (!config.exportViewer) {
return;
}
const cli = await import('tailwind-config-viewer/cli/export.js').then((r) => r.default || r);
nuxt.hook("nitro:build:public-assets", (nitro) => {
const dir = ufo.joinURL(nitro.options.output.publicDir, config.endpoint);
cli(dir, twConfig);
logger.success(`Exported viewer to ${utils.colors.yellow(pathe.relative(nuxt.options.srcDir, dir))}`);
});
};
const checkUnsafeInlineConfig = (inlineConfig) => {
if (!inlineConfig)
return;
if ("plugins" in inlineConfig && Array.isArray(inlineConfig.plugins) && inlineConfig.plugins.find((p) => typeof p === "function" || typeof p?.handler === "function")) {
return "plugins";
}
if (inlineConfig.content) {
const invalidProperty = ["extract", "transform"].find((i) => i in inlineConfig.content && typeof inlineConfig.content[i] === "function");
if (invalidProperty) {
return `content.${invalidProperty}`;
}
}
if (inlineConfig.safelist) {
const invalidIdx = inlineConfig.safelist.findIndex((s) => typeof s === "object" && s.pattern instanceof RegExp);
if (invalidIdx > -1) {
return `safelist[${invalidIdx}]`;
}
}
};
const UNSUPPORTED_VAL_STR = "UNSUPPORTED_VAL_STR";
const JSONStringifyWithUnsupportedVals = (val) => JSON.stringify(val, (_, v) => ["function"].includes(typeof v) ? UNSUPPORTED_VAL_STR : v);
const JSONStringifyWithRegex = (obj) => JSON.stringify(obj, (_, v) => v instanceof RegExp ? `__REGEXP ${v.toString()}` : v);
const createObjProxy = (configUpdatedHook, meta) => {
return (configPath, oldConfig, newConfig) => utils$1.diff(oldConfig, newConfig).forEach((change) => {
const path = change.key.split(".").map((k) => `[${JSON.stringify(k)}]`).join("");
const newValue = change.newValue?.value;
switch (change.type) {
case "removed":
configUpdatedHook[configPath] += `delete cfg${path};`;
break;
case "added":
case "changed": {
const resultingCode = `cfg${path} = ${JSONStringifyWithRegex(newValue)?.replace(/"__REGEXP (.*)"/g, (_, substr) => substr.replace(/\\"/g, '"')) || `cfg${path}`};`;
if (JSONStringifyWithUnsupportedVals(change.oldValue?.value) === JSONStringifyWithUnsupportedVals(newValue) || configUpdatedHook[configPath].endsWith(resultingCode)) {
return;
}
if (JSONStringifyWithUnsupportedVals(newValue).includes(`"${UNSUPPORTED_VAL_STR}"`) && !meta?.disableHMR) {
logger.warn(
`A hook has injected a non-serializable value in \`config${path}\`, so the Tailwind Config cannot be serialized. Falling back to providing the loaded configuration inlined directly to PostCSS loader..`,
"Please consider using a configuration file/template instead (specifying in `configPath` of the module options) to enable additional support for IntelliSense and HMR."
);
twCtx.set({ meta: { disableHMR: true } });
}
if (JSONStringifyWithRegex(newValue).includes("__REGEXP") && !meta?.disableHMR) {
logger.warn(`A hook is injecting RegExp values in your configuration (check \`config${path}\`) which may be unsafely serialized. Consider moving your safelist to a separate configuration file/template instead (specifying in \`configPath\` of the module options)`);
}
configUpdatedHook[configPath] += resultingCode;
}
}
});
};
const loadConfig = c12.loadConfig;
const pagesContentPath = unctx.getContext("twcss-pages-path");
const componentsContentPath = unctx.getContext("twcss-components-path");
const resolvedConfigsCtx = unctx.getContext("twcss-resolved-configs");
const createInternalContext = async (moduleOptions, nuxt = kit.useNuxt()) => {
const configUpdatedHook = {};
const { meta = { disableHMR: moduleOptions.disableHMR } } = twCtx.tryUse() ?? {};
const trackObjChanges = createObjProxy(configUpdatedHook, meta);
const resolveConfigs = (configs, nuxt2 = kit.useNuxt()) => (Array.isArray(configs) ? configs : [configs]).filter((c) => Boolean(c) && c !== pathe.join(nuxt2.options.rootDir, "tailwind.config")).map(async (config, idx, arr) => {
if (typeof config !== "string") {
const hasUnsafeProperty = checkUnsafeInlineConfig(config);
if (hasUnsafeProperty && !meta.disableHMR) {
logger.warn(
`The provided Tailwind configuration in your \`nuxt.config\` is non-serializable. Check \`${hasUnsafeProperty}\`. Falling back to providing the loaded configuration inlined directly to PostCSS loader..`,
"Please consider using `tailwind.config` or a separate file (specifying in `configPath` of the module options) to enable it with additional support for IntelliSense and HMR. Suppress this warning with `quiet: true` in the module options."
);
meta.disableHMR = true;
twCtx.set({ meta });
}
return { config };
}
const configFile = await (config.startsWith(nuxt2.options.buildDir) ? config : kit.findPath(config, { extensions: [".js", ".cjs", ".mjs", ".ts"] }));
return configFile ? loadConfig({ configFile }).then(async (resolvedConfig) => {
const { configFile: resolvedConfigFile = configFile } = resolvedConfig;
const config2 = merger(void 0, resolvedConfig.config);
configUpdatedHook[resolvedConfigFile] = "";
if (resolvedConfig.config?.purge && !resolvedConfig.config.content) {
configUpdatedHook[resolvedConfigFile] += "cfg.content = cfg.purge;";
}
await nuxt2.callHook("tailwindcss:loadConfig", config2, resolvedConfigFile, idx, arr);
trackObjChanges(resolvedConfigFile, resolvedConfig.config, config2);
return { ...resolvedConfig, config: config2 };
}).catch((e) => {
logger.warn(`Failed to load config \`./${pathe.relative(nuxt2.options.rootDir, configFile)}\` due to the error below. Skipping..
`, e);
return null;
}) : null;
});
const resolveContentConfig = (rootDir, nuxtOptions = kit.useNuxt().options) => {
const r = (p) => pathe.isAbsolute(p) || p.startsWith(rootDir) ? p : pathe.resolve(rootDir, p);
const withSrcDir = (p) => r(nuxtOptions.srcDir && !p.startsWith(nuxtOptions.srcDir) ? pathe.resolve(nuxtOptions.srcDir, p) : p);
const formatExtensions = (s) => s.length > 1 ? `.{${s.join(",")}}` : `.${s.join("") || "vue"}`;
const defaultExtensions = formatExtensions(["js", "ts", "mjs"]);
const sfcExtensions = formatExtensions(Array.from(/* @__PURE__ */ new Set([".vue", ...nuxtOptions.extensions || nuxt.options.extensions])).map((e) => e?.replace(/^\.*/, "")).filter((v) => Boolean(v)));
const importDirs = [...nuxtOptions.imports?.dirs || []].filter((v) => Boolean(v)).map(withSrcDir);
const [composablesDir, utilsDir] = [withSrcDir("composables"), withSrcDir("utils")];
if (!importDirs.includes(composablesDir))
importDirs.push(composablesDir);
if (!importDirs.includes(utilsDir))
importDirs.push(utilsDir);
const isLayer = rootDir !== nuxt.options.rootDir;
const pagePaths = [];
const pageFiles = pagesContentPath.tryUse();
if (moduleOptions.experimental?.strictScanContentPaths && pageFiles && pageFiles.length) {
if (!isLayer)
pagePaths.push(...pageFiles.map((p) => p.replaceAll(/\[(\.+)([^.].*)\]/g, "?$1$2?")));
} else if (nuxtOptions.pages !== false && nuxtOptions.pages?.enabled !== false) {
pagePaths.push(withSrcDir(`${nuxtOptions.dir?.pages || "pages"}/**/*${sfcExtensions}`));
}
const componentPaths = [];
const componentFiles = componentsContentPath.tryUse();
if (moduleOptions.experimental?.strictScanContentPaths && componentFiles && componentFiles.length) {
if (!isLayer)
componentPaths.push(...componentFiles);
} else {
componentPaths.push(
withSrcDir(`components/**/*${sfcExtensions}`),
...(() => {
if (nuxtOptions.components) {
return (Array.isArray(nuxtOptions.components) ? nuxtOptions.components : typeof nuxtOptions.components === "boolean" ? ["components"] : nuxtOptions.components.dirs || []).map((d) => {
const valueToResolve = typeof d === "string" ? d : d?.path;
return valueToResolve ? `${kit.resolveAlias(valueToResolve)}/**/*${sfcExtensions}` : "";
}).filter(Boolean);
}
return [];
})()
);
}
return {
config: {
content: {
files: [
...componentPaths,
nuxtOptions.dir?.layouts && withSrcDir(`${nuxtOptions.dir.layouts}/**/*${sfcExtensions}`),
nuxtOptions.dir?.plugins && withSrcDir(`${nuxtOptions.dir.plugins}/**/*${defaultExtensions}`),
...importDirs.map((d) => `${d}/**/*${defaultExtensions}`),
...pagePaths,
withSrcDir(`{A,a}pp${sfcExtensions}`),
withSrcDir(`{E,e}rror${sfcExtensions}`),
withSrcDir(`app.config${defaultExtensions}`),
!nuxtOptions.ssr && nuxtOptions.spaLoadingTemplate !== false && r(typeof nuxtOptions.spaLoadingTemplate === "string" ? nuxtOptions.spaLoadingTemplate : "app/spa-loading-template.html")
].filter((p) => Boolean(p))
}
}
};
};
const resolvePageFiles = (pages) => {
const filePaths = [];
pages.forEach((page) => {
if (page.file) {
filePaths.push(page.file);
}
if (page.children && page.children.length) {
filePaths.push(...resolvePageFiles(page.children));
}
});
return filePaths;
};
const getModuleConfigs = () => {
const thenCallHook = async (resolvedConfig) => {
const { configFile: resolvedConfigFile } = resolvedConfig;
if (!resolvedConfigFile || !resolvedConfig.config) {
return { ...resolvedConfig, configFile: resolvedConfigFile === "tailwind.config" ? void 0 : resolvedConfigFile };
}
const config = merger(void 0, resolvedConfig.config);
configUpdatedHook[resolvedConfigFile] = "";
if (resolvedConfig.config?.purge && !resolvedConfig.config.content) {
configUpdatedHook[resolvedConfigFile] += "cfg.content = cfg.purge;";
}
await nuxt.callHook("tailwindcss:loadConfig", config, resolvedConfigFile, 0, []);
trackObjChanges(resolvedConfigFile, resolvedConfig.config, config);
return { ...resolvedConfig, config };
};
return Promise.all([
resolveContentConfig(nuxt.options.rootDir, nuxt.options),
...resolveConfigs(moduleOptions.config, nuxt),
loadConfig({ name: "tailwind", cwd: nuxt.options.rootDir, merger: merger, packageJson: true, extend: false }).then(thenCallHook),
...resolveConfigs(moduleOptions.configPath, nuxt),
...(nuxt.options._layers || []).slice(1).flatMap((nuxtLayer) => [
resolveContentConfig(nuxtLayer.config.rootDir || nuxtLayer.cwd, nuxtLayer.config),
...resolveConfigs(nuxtLayer.config.tailwindcss?.config, nuxt),
loadConfig({ name: "tailwind", cwd: nuxtLayer.cwd, merger: merger, packageJson: true, extend: false }).then(thenCallHook),
...resolveConfigs(nuxtLayer.config.tailwindcss?.configPath, nuxt)
])
]);
};
const resolveTWConfig = await import('tailwindcss/resolveConfig.js').then((m) => m.default || m).catch(() => (c) => c);
const loadConfigs = async () => {
const moduleConfigs = await getModuleConfigs();
resolvedConfigsCtx.set(moduleConfigs, true);
const tailwindConfig = moduleConfigs.reduce((acc, curr) => merger(acc, curr?.config ?? {}), {});
const clonedConfig = merger(void 0, tailwindConfig);
configUpdatedHook["main-config"] = "";
await nuxt.callHook("tailwindcss:config", clonedConfig);
trackObjChanges("main-config", tailwindConfig, clonedConfig);
const resolvedConfig = resolveTWConfig(clonedConfig);
await nuxt.callHook("tailwindcss:resolvedConfig", resolvedConfig, twCtx.tryUse()?.config ?? void 0);
twCtx.set({ config: resolvedConfig });
return tailwindConfig;
};
const generateConfig = () => {
const ctx = twCtx.tryUse();
const targetDir = pathe.join(nuxt.options.buildDir, "tailwind");
const template = !meta.disableHMR || !ctx?.meta?.disableHMR ? kit.addTemplate({
filename: "tailwind/postcss.mjs",
write: true,
getContents: () => {
const serializeConfig = (config) => JSON.stringify(
Array.isArray(config.plugins) && config.plugins.length > 0 ? merger({ plugins: (defaultPlugins) => defaultPlugins?.filter((p) => p && typeof p !== "function") }, config) : config,
(_, v) => typeof v === "function" ? `() => (${JSON.stringify(v())})` : v
).replace(/"(\(\) => \(.*\))"/g, (_, substr) => substr.replace(/\\"/g, '"'));
const layerConfigs = resolvedConfigsCtx.use().map((c, idx) => c?.configFile ? [`import cfg${idx} from ${JSON.stringify(/[/\\]node_modules[/\\]/.test(c.configFile) ? c.configFile : "./" + pathe.relative(targetDir, c.configFile))}`, configUpdatedHook[c.configFile] ? `(() => {const cfg=configMerger(undefined, cfg${idx});${configUpdatedHook[c.configFile]};return cfg;})()` : `cfg${idx}`] : [null, c?.config ? serializeConfig(c.config) : null]);
return [
`// generated by the @nuxtjs/tailwindcss <https://github.com/nuxt-modules/tailwindcss> module at ${( new Date()).toLocaleString()}`,
'import "@nuxtjs/tailwindcss/config-ctx"',
`import configMerger from "@nuxtjs/tailwindcss/merger";
`,
layerConfigs.map(([i, _]) => i).filter(Boolean).join(";\n") + ";",
"const config = [",
layerConfigs.map(([_, i]) => i).filter(Boolean).join(",\n"),
`].reduce((acc, curr) => configMerger(acc, curr), {});
`,
`const resolvedConfig = ${configUpdatedHook["main-config"] ? `(() => {const cfg=config;${configUpdatedHook["main-config"]};return cfg;})()` : "config"};
`,
"export default resolvedConfig;"
].join("\n");
}
}) : { dst: "" };
twCtx.set({ dst: template.dst });
return template;
};
const registerHooks = () => {
if (twCtx.use().meta?.disableHMR)
return;
const reloadConfigTemplate = async () => {
const { dst } = twCtx.use();
await loadConfigs();
setTimeout(async () => {
await kit.updateTemplates({ filter: (t) => t.dst === dst || dst?.endsWith(t.filename) || false });
await nuxt.callHook("tailwindcss:internal:regenerateTemplates", { configTemplateUpdated: true });
}, 100);
};
nuxt.hook("app:templatesGenerated", async (_app, templates) => {
if (Array.isArray(templates) && templates?.some((t) => Object.keys(configUpdatedHook).includes(t.dst))) {
await reloadConfigTemplate();
}
});
if (moduleOptions.experimental?.strictScanContentPaths) {
nuxt.hook("pages:extend", async (pages) => {
const newPageFiles = resolvePageFiles(pages);
if (newPageFiles.length !== pagesContentPath.tryUse()?.length) {
pagesContentPath.set(newPageFiles, true);
await reloadConfigTemplate();
}
});
nuxt.hook("components:extend", async (components) => {
const newComponentFiles = components.map((c) => c.filePath);
if (newComponentFiles.length !== componentsContentPath.tryUse()?.length) {
componentsContentPath.set(newComponentFiles, true);
await reloadConfigTemplate();
}
});
} else {
nuxt.hook("pages:extend", () => reloadConfigTemplate());
}
nuxt.hook("vite:serverCreated", (server) => {
nuxt.hook("tailwindcss:internal:regenerateTemplates", (data) => {
if (!data || !data.configTemplateUpdated)
return;
const ctx = twCtx.use();
const configFile = ctx.dst && server.moduleGraph.getModuleById(ctx.dst);
configFile && server.moduleGraph.invalidateModule(configFile);
});
});
moduleOptions.exposeConfig && nuxt.hook("builder:watch", async (_, path) => {
if (Object.keys(configUpdatedHook).includes(pathe.join(nuxt.options.rootDir, path))) {
const ctx = twCtx.use();
setTimeout(async () => {
await import(ctx.dst).then(async (_config) => {
twCtx.set({ config: resolveTWConfig(_config.default ?? _config) });
await nuxt.callHook("tailwindcss:internal:regenerateTemplates");
});
}, 100);
}
});
};
return {
loadConfigs,
generateConfig,
registerHooks
};
};
const defaults = (nuxt = kit.useNuxt()) => ({
configPath: [],
cssPath: pathe.join(nuxt.options.dir.assets, "css/tailwind.css"),
config: {},
viewer: nuxt.options.dev,
exposeConfig: false,
quiet: nuxt.options.logLevel === "silent",
editorSupport: false
});
const module$1 = kit.defineNuxtModule({
meta: { name, version, configKey, compatibility },
defaults,
async setup(moduleOptions, nuxt) {
if (moduleOptions.quiet)
logger.level = consola.LogLevels.silent;
if (Number.parseFloat(kit.getNuxtVersion()) < 2.16) {
await kit.installModule("@nuxt/postcss8").catch((e) => {
logger.error(`Error occurred while loading \`@nuxt/postcss8\` required for Nuxt ${kit.getNuxtVersion()}, is it installed?`);
throw e;
});
}
const isTailwind4 = await pkgTypes.readPackageJSON("tailwindcss", { parent: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href)) }).then((m) => Number.parseFloat(m.version) >= 4);
if (isTailwind4 && !moduleOptions.experimental?.tailwindcss4) {
logger.warn("Tailwind CSS v4 detected. The current version of `@nuxtjs/tailwindcss` supports Tailwind CSS 3 officially and support for v4 is experimental. To suppress this warning, set `tailwindcss.experimental.tailwindcss4` to `true` in your `nuxt.config`.");
}
const ctx = await createInternalContext(moduleOptions, nuxt);
if (moduleOptions.editorSupport) {
const editorSupportConfig = resolveEditorSupportConfig(moduleOptions.editorSupport);
if (editorSupportConfig.autocompleteUtil && !kit.isNuxtMajorVersion(2, nuxt)) {
kit.addImports({
name: "autocompleteUtil",
from: kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href))).resolve("./runtime/utils"),
as: "tw",
...typeof editorSupportConfig.autocompleteUtil === "object" ? editorSupportConfig.autocompleteUtil : {}
});
}
}
const [cssPath, cssPathConfig] = Array.isArray(moduleOptions.cssPath) ? moduleOptions.cssPath : [moduleOptions.cssPath];
const [resolvedCss, loggerInfo] = await resolveCSSPath(cssPath, nuxt).catch((e) => {
if (isTailwind4) {
return [kit.addTemplate({ filename: "tailwind.css", getContents: () => `@import 'tailwindcss';`, write: true }).dst, "Generating default CSS file for Tailwind CSS 4..."];
}
throw e;
});
logger.info(loggerInfo);
nuxt.options.css = nuxt.options.css ?? [];
const resolvedNuxtCss = resolvedCss && await Promise.all(nuxt.options.css.map((p) => kit.resolvePath(p.src ?? p))) || [];
if (resolvedCss && !resolvedNuxtCss.includes(resolvedCss)) {
const injectPosition = await resolveInjectPosition(resolvedNuxtCss, cssPathConfig?.injectPosition);
nuxt.options.css.splice(injectPosition, 0, resolvedCss);
}
const shouldInstallTWVitePlugin = isTailwind4 && nuxt.options.builder === "@nuxt/vite-builder";
if (shouldInstallTWVitePlugin) {
await import('@tailwindcss/vite').then((r) => kit.addVitePlugin(r.default()));
}
let nuxt2ViewerConfig = pathe.join(nuxt.options.buildDir, "tailwind/postcss.mjs");
nuxt.hook("modules:done", async () => {
const _config = await ctx.loadConfigs();
const twConfig = ctx.generateConfig();
ctx.registerHooks();
nuxt2ViewerConfig = twConfig.dst || _config;
if (moduleOptions.exposeConfig) {
const exposeConfig = resolveExposeConfig(moduleOptions.exposeConfig);
const exposeTemplates = createExposeTemplates(exposeConfig);
nuxt.hook("tailwindcss:internal:regenerateTemplates", () => kit.updateTemplates({ filter: (template) => exposeTemplates.includes(template.dst) }));
}
if (!shouldInstallTWVitePlugin) {
const postcssOptions = nuxt.options.postcss || nuxt.options.build.postcss.postcssOptions || nuxt.options.build.postcss;
const pluginsToAdd = isTailwind4 ? { "@tailwindcss/postcss": {} } : {
"tailwindcss/nesting": postcssOptions.plugins?.["tailwindcss/nesting"] ?? {},
"tailwindcss": twConfig.dst || _config
};
postcssOptions.plugins = {
...postcssOptions.plugins || {},
...pluginsToAdd
};
}
if (nuxt.options.dev && !kit.isNuxtMajorVersion(2, nuxt)) {
if (moduleOptions.viewer) {
const viewerConfig = resolveViewerConfig(moduleOptions.viewer);
setupViewer(twConfig.dst || _config, viewerConfig, nuxt);
}
} else {
if (!nuxt.options.dev)
return;
if (moduleOptions.viewer) {
const viewerConfig = resolveViewerConfig(moduleOptions.viewer);
exportViewer(twConfig.dst || kit.addTemplate({ filename: "tailwind.config/viewer-config.cjs", getContents: () => `module.exports = ${JSON.stringify(_config)}`, write: true }).dst, viewerConfig);
}
}
});
if (nuxt.options.dev && moduleOptions.viewer && kit.isNuxtMajorVersion(2, nuxt)) {
const viewerConfig = resolveViewerConfig(moduleOptions.viewer);
setupViewer(nuxt2ViewerConfig, viewerConfig, nuxt);
}
}
});
module.exports = module$1;

24
node_modules/@nuxtjs/tailwindcss/dist/module.d.cts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import * as _nuxt_schema from '@nuxt/schema';
import { M as ModuleHooks, a as ModuleOptions } from './shared/tailwindcss.7c01d049.cjs';
import 'tailwindcss/resolveConfig';
import 'tailwindcss';
import 'nuxt/kit';
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
declare module 'nuxt/schema' {
interface NuxtHooks extends ModuleHooks {
'tailwindcss:internal:regenerateTemplates': (data?: {
configTemplateUpdated?: boolean;
}) => void | Promise<void>;
}
}
declare module '@nuxt/schema' {
interface NuxtHooks extends ModuleHooks {
'tailwindcss:internal:regenerateTemplates': (data?: {
configTemplateUpdated?: boolean;
}) => void | Promise<void>;
}
}
export { ModuleHooks, ModuleOptions, _default as default };

24
node_modules/@nuxtjs/tailwindcss/dist/module.d.mts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import * as _nuxt_schema from '@nuxt/schema';
import { M as ModuleHooks, a as ModuleOptions } from './shared/tailwindcss.7c01d049.mjs';
import 'tailwindcss/resolveConfig';
import 'tailwindcss';
import 'nuxt/kit';
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
declare module 'nuxt/schema' {
interface NuxtHooks extends ModuleHooks {
'tailwindcss:internal:regenerateTemplates': (data?: {
configTemplateUpdated?: boolean;
}) => void | Promise<void>;
}
}
declare module '@nuxt/schema' {
interface NuxtHooks extends ModuleHooks {
'tailwindcss:internal:regenerateTemplates': (data?: {
configTemplateUpdated?: boolean;
}) => void | Promise<void>;
}
}
export { ModuleHooks, ModuleOptions, _default as default };

24
node_modules/@nuxtjs/tailwindcss/dist/module.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import * as _nuxt_schema from '@nuxt/schema';
import { M as ModuleHooks, a as ModuleOptions } from './shared/tailwindcss.7c01d049.js';
import 'tailwindcss/resolveConfig';
import 'tailwindcss';
import 'nuxt/kit';
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
declare module 'nuxt/schema' {
interface NuxtHooks extends ModuleHooks {
'tailwindcss:internal:regenerateTemplates': (data?: {
configTemplateUpdated?: boolean;
}) => void | Promise<void>;
}
}
declare module '@nuxt/schema' {
interface NuxtHooks extends ModuleHooks {
'tailwindcss:internal:regenerateTemplates': (data?: {
configTemplateUpdated?: boolean;
}) => void | Promise<void>;
}
}
export { ModuleHooks, ModuleOptions, _default as default };

12
node_modules/@nuxtjs/tailwindcss/dist/module.json generated vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"name": "@nuxtjs/tailwindcss",
"version": "6.14.0",
"configKey": "tailwindcss",
"compatibility": {
"nuxt": "^2.9.0 || >=3.0.0-rc.1"
},
"builder": {
"@nuxt/module-builder": "0.8.4",
"unbuild": "2.0.0"
}
}

612
node_modules/@nuxtjs/tailwindcss/dist/module.mjs generated vendored Normal file
View File

@@ -0,0 +1,612 @@
import { relative, join, dirname, isAbsolute, resolve } from 'pathe';
import { resolvePath, tryResolveModule, useNuxt, useLogger, addTemplate, addTypeTemplate, isNuxtMajorVersion, addDevServerHandler, updateTemplates, findPath, resolveAlias, defineNuxtModule, getNuxtVersion, installModule, addImports, createResolver, addVitePlugin } from '@nuxt/kit';
import { readPackageJSON } from 'pkg-types';
import { existsSync } from 'node:fs';
import { defu } from 'defu';
import { LogLevels } from 'consola';
import { getContext } from 'unctx';
import { colors } from 'consola/utils';
import { eventHandler, sendRedirect, H3Event } from 'h3';
import { joinURL, withTrailingSlash, withoutTrailingSlash, cleanDoubleSlashes } from 'ufo';
import { loadConfig as loadConfig$1 } from 'c12';
import configMerger from './merger.mjs';
import { diff } from 'ohash/utils';
import 'klona';
const name = "@nuxtjs/tailwindcss";
const version = "6.14.0";
const configKey = "tailwindcss";
const compatibility = {
nuxt: "^2.9.0 || >=3.0.0-rc.1"
};
async function resolveCSSPath(cssPath, nuxt = useNuxt()) {
if (typeof cssPath === "string") {
const _cssPath = await resolvePath(cssPath, { extensions: [".css", ".sass", ".scss", ".less", ".styl"] });
return existsSync(_cssPath) ? [_cssPath, `Using Tailwind CSS from ~/${relative(nuxt.options.srcDir, _cssPath)}`] : await tryResolveModule("tailwindcss/package.json", import.meta.url).then((twLocation) => twLocation ? [join(twLocation, "../tailwind.css"), "Using default Tailwind CSS file"] : Promise.reject("Unable to resolve tailwindcss. Is it installed?"));
} else {
return [
false,
"No Tailwind CSS file found. Skipping..."
];
}
}
const resolveBoolObj = (config, fb) => defu(typeof config === "object" ? config : {}, fb);
const resolveViewerConfig = (config) => resolveBoolObj(config, { endpoint: "/_tailwind", exportViewer: false });
const resolveExposeConfig = (config) => resolveBoolObj(config, { alias: "#tailwind-config", level: 2 });
const resolveEditorSupportConfig = (config) => resolveBoolObj(config, { autocompleteUtil: true, generateConfig: false });
async function resolveInjectPosition(css, position = "first") {
if (typeof position === "number") {
return ~~Math.min(position, css.length + 1);
}
if (typeof position === "string") {
switch (position) {
case "first":
return 0;
case "last":
return css.length;
}
}
if (typeof position === "object") {
const minIndex = "after" in position ? css.indexOf(await resolvePath(position.after)) + 1 : 0;
const maxIndex = "before" in position ? css.indexOf(await resolvePath(position.before)) : css.length;
if ([minIndex, maxIndex].includes(-1) || "after" in position && minIndex === 0) {
throw new Error(`\`injectPosition\` specifies a file which does not exists on CSS stack: ` + JSON.stringify(position));
}
if (minIndex > maxIndex) {
throw new Error(`\`injectPosition\` specifies a relative location \`${minIndex}\` that cannot be resolved (i.e., \`after\` orders \`before\` may be reversed): ` + JSON.stringify(position));
}
return "after" in position ? minIndex : maxIndex;
}
throw new Error("invalid `injectPosition`: " + JSON.stringify(position));
}
const logger = useLogger("nuxt:tailwindcss");
const twCtx = getContext("twcss");
const { set } = twCtx;
twCtx.set = (instance, replace = true) => {
set(defu(instance, twCtx.tryUse()), replace);
};
const NON_ALPHANUMERIC_RE = /^[0-9a-z]+$/i;
const isJSObject = (value) => typeof value === "object" && !Array.isArray(value);
const createExposeTemplates = (config, nuxt = useNuxt()) => {
const templates = [];
const getTWConfig = (objPath = [], twConfig = twCtx.use().config) => objPath.reduce((prev, curr) => prev?.[curr], twConfig);
const populateMap = (obj = twCtx.use().config, path = [], level = 1) => {
Object.entries(obj).forEach(([key, value = {}]) => {
const subpathComponents = path.concat(key);
const subpath = subpathComponents.join("/");
if (level >= config.level || !isJSObject(value) || Object.keys(value).find((k) => !k.match(NON_ALPHANUMERIC_RE))) {
templates.push(addTemplate({
filename: `tailwind/expose/${subpath}.mjs`,
getContents: () => {
const _value = getTWConfig(subpathComponents);
if (isJSObject(_value)) {
const [validKeys, invalidKeys] = [[], []];
Object.keys(_value).forEach((i) => (NON_ALPHANUMERIC_RE.test(i) ? validKeys : invalidKeys).push(i));
return [
`${validKeys.map((i) => `const _${i} = ${JSON.stringify(_value[i])}`).join("\n")}`,
`const config = { ${validKeys.map((i) => `"${i}": _${i}, `).join("")}${invalidKeys.map((i) => `"${i}": ${JSON.stringify(_value[i])}, `).join("")} }`,
`export { config as default${validKeys.length > 0 ? ", _" : ""}${validKeys.join(", _")} }`
].join("\n");
}
return `export default ${JSON.stringify(_value, null, 2)}`;
},
write: config.write
}));
} else {
populateMap(value, path.concat(key), level + 1);
templates.push(addTemplate({
filename: `tailwind/expose/${subpath}.mjs`,
getContents: () => {
const _value = getTWConfig(subpathComponents);
const values = Object.keys(_value);
return [
`${values.map((v) => `import _${v} from "./${key}/${v}.mjs"`).join("\n")}`,
`const config = { ${values.map((k) => `"${k}": _${k}`).join(", ")} }`,
`export { config as default${values.length > 0 ? ", _" : ""}${values.join(", _")} }`
].join("\n");
},
write: config.write
}));
}
});
};
populateMap();
const entryTemplate = addTemplate({
filename: "tailwind/expose/index.mjs",
getContents: () => {
const _tailwindConfig = getTWConfig();
const configOptions = Object.keys(_tailwindConfig);
return [
`${configOptions.map((v) => `import ${v} from "#build/tailwind/expose/${v}.mjs"`).join("\n")}`,
`const config = { ${configOptions.join(", ")} }`,
`export { config as default, ${configOptions.join(", ")} }`
].join("\n");
},
write: true
});
templates.push(addTypeTemplate({
filename: "types/tailwind.config.d.ts",
getContents: () => {
const _tailwindConfig = getTWConfig();
const declareModule = (obj, path = [], level = 1) => Object.entries(obj).map(([key, value = {}]) => {
const subpath = path.concat(key).join("/");
if (level >= config.level || !isJSObject(value) || Object.keys(value).find((k) => !k.match(NON_ALPHANUMERIC_RE))) {
if (isJSObject(value)) {
const [validKeys, invalidKeys] = [[], []];
Object.keys(value).forEach((i) => (NON_ALPHANUMERIC_RE.test(i) ? validKeys : invalidKeys).push(i));
return `declare module "${config.alias}/${subpath}" { ${validKeys.map((i) => `export const _${i}: ${JSON.stringify(value[i])};`).join("")} const defaultExport: { ${validKeys.map((i) => `"${i}": typeof _${i}, `).join("")}${invalidKeys.map((i) => `"${i}": ${JSON.stringify(value[i])}, `).join("")} }; export default defaultExport; }
`;
}
return `declare module "${config.alias}/${subpath}" { const defaultExport: ${JSON.stringify(value)}; export default defaultExport; }
`;
}
const values = Object.keys(value);
return declareModule(value, path.concat(key), level + 1).join("") + `declare module "${config.alias}/${subpath}" {${Object.keys(value).map((v) => ` export const _${v}: typeof import("${config.alias}/${join(`${key}/${subpath}`, `../${v}`)}")["default"];`).join("")} const defaultExport: { ${values.map((k) => `"${k}": typeof _${k}`).join(", ")} }; export default defaultExport; }
`;
});
const configOptions = Object.keys(_tailwindConfig);
return declareModule(_tailwindConfig).join("") + `declare module "${config.alias}" {${configOptions.map((v) => ` export const ${v}: typeof import("${join(config.alias, v)}")["default"];`).join("")} const defaultExport: { ${configOptions.map((v) => `"${v}": typeof ${v}`)} }; export default defaultExport; }`;
}
}));
templates.push(entryTemplate);
nuxt.options.alias[config.alias] = dirname(entryTemplate.dst);
return templates.map((t) => t.dst);
};
const setupViewer = async (twConfig, config, nuxt = useNuxt()) => {
const route = joinURL(nuxt.options.app?.baseURL, config.endpoint);
const [routeWithSlash, routeWithoutSlash] = [withTrailingSlash(route), withoutTrailingSlash(route)];
const viewerServer = await Promise.all([
// @ts-expect-error untyped package export
import('tailwind-config-viewer/server/index.js').then((r) => r.default || r),
typeof twConfig === "string" ? import('tailwindcss/loadConfig.js').then((r) => r.default || r).then((loadConfig) => () => loadConfig(twConfig)) : () => twConfig
]).then(([server, tailwindConfigProvider]) => server({ tailwindConfigProvider }).asMiddleware());
const viewerDevMiddleware = eventHandler((event) => viewerServer(event.node?.req || event.req, event.node?.res || event.res));
if (!isNuxtMajorVersion(2, nuxt)) {
addDevServerHandler({
handler: eventHandler((event) => {
if (event.path === routeWithoutSlash) {
return sendRedirect(event, routeWithSlash, 301);
}
})
});
addDevServerHandler({ route, handler: viewerDevMiddleware });
} else {
nuxt.options.serverMiddleware.push(
// @ts-expect-error untyped handler parameters
(req, res, next) => {
if (req.url === routeWithoutSlash) {
return sendRedirect(new H3Event(req, res), routeWithSlash, 301);
}
next();
},
// @ts-expect-error untyped handler parameters
{ route, handler: (req, res) => viewerDevMiddleware(new H3Event(req, res)) }
);
}
nuxt.hook("devtools:customTabs", (tabs) => {
tabs?.push({
title: "Tailwind CSS",
name: "tailwindcss",
icon: "logos-tailwindcss-icon",
category: "modules",
view: { type: "iframe", src: route }
});
});
const shouldLogUrl = "devtools" in nuxt.options ? !nuxt.options.devtools.enabled : true;
shouldLogUrl && nuxt.hook("listen", (_, listener) => {
const viewerUrl = cleanDoubleSlashes(joinURL(listener.url, config.endpoint));
logger.info(`Tailwind Viewer: ${colors.underline(colors.yellow(withTrailingSlash(viewerUrl)))}`);
});
};
const exportViewer = async (twConfig, config, nuxt = useNuxt()) => {
if (!config.exportViewer) {
return;
}
const cli = await import('tailwind-config-viewer/cli/export.js').then((r) => r.default || r);
nuxt.hook("nitro:build:public-assets", (nitro) => {
const dir = joinURL(nitro.options.output.publicDir, config.endpoint);
cli(dir, twConfig);
logger.success(`Exported viewer to ${colors.yellow(relative(nuxt.options.srcDir, dir))}`);
});
};
const checkUnsafeInlineConfig = (inlineConfig) => {
if (!inlineConfig)
return;
if ("plugins" in inlineConfig && Array.isArray(inlineConfig.plugins) && inlineConfig.plugins.find((p) => typeof p === "function" || typeof p?.handler === "function")) {
return "plugins";
}
if (inlineConfig.content) {
const invalidProperty = ["extract", "transform"].find((i) => i in inlineConfig.content && typeof inlineConfig.content[i] === "function");
if (invalidProperty) {
return `content.${invalidProperty}`;
}
}
if (inlineConfig.safelist) {
const invalidIdx = inlineConfig.safelist.findIndex((s) => typeof s === "object" && s.pattern instanceof RegExp);
if (invalidIdx > -1) {
return `safelist[${invalidIdx}]`;
}
}
};
const UNSUPPORTED_VAL_STR = "UNSUPPORTED_VAL_STR";
const JSONStringifyWithUnsupportedVals = (val) => JSON.stringify(val, (_, v) => ["function"].includes(typeof v) ? UNSUPPORTED_VAL_STR : v);
const JSONStringifyWithRegex = (obj) => JSON.stringify(obj, (_, v) => v instanceof RegExp ? `__REGEXP ${v.toString()}` : v);
const createObjProxy = (configUpdatedHook, meta) => {
return (configPath, oldConfig, newConfig) => diff(oldConfig, newConfig).forEach((change) => {
const path = change.key.split(".").map((k) => `[${JSON.stringify(k)}]`).join("");
const newValue = change.newValue?.value;
switch (change.type) {
case "removed":
configUpdatedHook[configPath] += `delete cfg${path};`;
break;
case "added":
case "changed": {
const resultingCode = `cfg${path} = ${JSONStringifyWithRegex(newValue)?.replace(/"__REGEXP (.*)"/g, (_, substr) => substr.replace(/\\"/g, '"')) || `cfg${path}`};`;
if (JSONStringifyWithUnsupportedVals(change.oldValue?.value) === JSONStringifyWithUnsupportedVals(newValue) || configUpdatedHook[configPath].endsWith(resultingCode)) {
return;
}
if (JSONStringifyWithUnsupportedVals(newValue).includes(`"${UNSUPPORTED_VAL_STR}"`) && !meta?.disableHMR) {
logger.warn(
`A hook has injected a non-serializable value in \`config${path}\`, so the Tailwind Config cannot be serialized. Falling back to providing the loaded configuration inlined directly to PostCSS loader..`,
"Please consider using a configuration file/template instead (specifying in `configPath` of the module options) to enable additional support for IntelliSense and HMR."
);
twCtx.set({ meta: { disableHMR: true } });
}
if (JSONStringifyWithRegex(newValue).includes("__REGEXP") && !meta?.disableHMR) {
logger.warn(`A hook is injecting RegExp values in your configuration (check \`config${path}\`) which may be unsafely serialized. Consider moving your safelist to a separate configuration file/template instead (specifying in \`configPath\` of the module options)`);
}
configUpdatedHook[configPath] += resultingCode;
}
}
});
};
const loadConfig = loadConfig$1;
const pagesContentPath = getContext("twcss-pages-path");
const componentsContentPath = getContext("twcss-components-path");
const resolvedConfigsCtx = getContext("twcss-resolved-configs");
const createInternalContext = async (moduleOptions, nuxt = useNuxt()) => {
const configUpdatedHook = {};
const { meta = { disableHMR: moduleOptions.disableHMR } } = twCtx.tryUse() ?? {};
const trackObjChanges = createObjProxy(configUpdatedHook, meta);
const resolveConfigs = (configs, nuxt2 = useNuxt()) => (Array.isArray(configs) ? configs : [configs]).filter((c) => Boolean(c) && c !== join(nuxt2.options.rootDir, "tailwind.config")).map(async (config, idx, arr) => {
if (typeof config !== "string") {
const hasUnsafeProperty = checkUnsafeInlineConfig(config);
if (hasUnsafeProperty && !meta.disableHMR) {
logger.warn(
`The provided Tailwind configuration in your \`nuxt.config\` is non-serializable. Check \`${hasUnsafeProperty}\`. Falling back to providing the loaded configuration inlined directly to PostCSS loader..`,
"Please consider using `tailwind.config` or a separate file (specifying in `configPath` of the module options) to enable it with additional support for IntelliSense and HMR. Suppress this warning with `quiet: true` in the module options."
);
meta.disableHMR = true;
twCtx.set({ meta });
}
return { config };
}
const configFile = await (config.startsWith(nuxt2.options.buildDir) ? config : findPath(config, { extensions: [".js", ".cjs", ".mjs", ".ts"] }));
return configFile ? loadConfig({ configFile }).then(async (resolvedConfig) => {
const { configFile: resolvedConfigFile = configFile } = resolvedConfig;
const config2 = configMerger(void 0, resolvedConfig.config);
configUpdatedHook[resolvedConfigFile] = "";
if (resolvedConfig.config?.purge && !resolvedConfig.config.content) {
configUpdatedHook[resolvedConfigFile] += "cfg.content = cfg.purge;";
}
await nuxt2.callHook("tailwindcss:loadConfig", config2, resolvedConfigFile, idx, arr);
trackObjChanges(resolvedConfigFile, resolvedConfig.config, config2);
return { ...resolvedConfig, config: config2 };
}).catch((e) => {
logger.warn(`Failed to load config \`./${relative(nuxt2.options.rootDir, configFile)}\` due to the error below. Skipping..
`, e);
return null;
}) : null;
});
const resolveContentConfig = (rootDir, nuxtOptions = useNuxt().options) => {
const r = (p) => isAbsolute(p) || p.startsWith(rootDir) ? p : resolve(rootDir, p);
const withSrcDir = (p) => r(nuxtOptions.srcDir && !p.startsWith(nuxtOptions.srcDir) ? resolve(nuxtOptions.srcDir, p) : p);
const formatExtensions = (s) => s.length > 1 ? `.{${s.join(",")}}` : `.${s.join("") || "vue"}`;
const defaultExtensions = formatExtensions(["js", "ts", "mjs"]);
const sfcExtensions = formatExtensions(Array.from(/* @__PURE__ */ new Set([".vue", ...nuxtOptions.extensions || nuxt.options.extensions])).map((e) => e?.replace(/^\.*/, "")).filter((v) => Boolean(v)));
const importDirs = [...nuxtOptions.imports?.dirs || []].filter((v) => Boolean(v)).map(withSrcDir);
const [composablesDir, utilsDir] = [withSrcDir("composables"), withSrcDir("utils")];
if (!importDirs.includes(composablesDir))
importDirs.push(composablesDir);
if (!importDirs.includes(utilsDir))
importDirs.push(utilsDir);
const isLayer = rootDir !== nuxt.options.rootDir;
const pagePaths = [];
const pageFiles = pagesContentPath.tryUse();
if (moduleOptions.experimental?.strictScanContentPaths && pageFiles && pageFiles.length) {
if (!isLayer)
pagePaths.push(...pageFiles.map((p) => p.replaceAll(/\[(\.+)([^.].*)\]/g, "?$1$2?")));
} else if (nuxtOptions.pages !== false && nuxtOptions.pages?.enabled !== false) {
pagePaths.push(withSrcDir(`${nuxtOptions.dir?.pages || "pages"}/**/*${sfcExtensions}`));
}
const componentPaths = [];
const componentFiles = componentsContentPath.tryUse();
if (moduleOptions.experimental?.strictScanContentPaths && componentFiles && componentFiles.length) {
if (!isLayer)
componentPaths.push(...componentFiles);
} else {
componentPaths.push(
withSrcDir(`components/**/*${sfcExtensions}`),
...(() => {
if (nuxtOptions.components) {
return (Array.isArray(nuxtOptions.components) ? nuxtOptions.components : typeof nuxtOptions.components === "boolean" ? ["components"] : nuxtOptions.components.dirs || []).map((d) => {
const valueToResolve = typeof d === "string" ? d : d?.path;
return valueToResolve ? `${resolveAlias(valueToResolve)}/**/*${sfcExtensions}` : "";
}).filter(Boolean);
}
return [];
})()
);
}
return {
config: {
content: {
files: [
...componentPaths,
nuxtOptions.dir?.layouts && withSrcDir(`${nuxtOptions.dir.layouts}/**/*${sfcExtensions}`),
nuxtOptions.dir?.plugins && withSrcDir(`${nuxtOptions.dir.plugins}/**/*${defaultExtensions}`),
...importDirs.map((d) => `${d}/**/*${defaultExtensions}`),
...pagePaths,
withSrcDir(`{A,a}pp${sfcExtensions}`),
withSrcDir(`{E,e}rror${sfcExtensions}`),
withSrcDir(`app.config${defaultExtensions}`),
!nuxtOptions.ssr && nuxtOptions.spaLoadingTemplate !== false && r(typeof nuxtOptions.spaLoadingTemplate === "string" ? nuxtOptions.spaLoadingTemplate : "app/spa-loading-template.html")
].filter((p) => Boolean(p))
}
}
};
};
const resolvePageFiles = (pages) => {
const filePaths = [];
pages.forEach((page) => {
if (page.file) {
filePaths.push(page.file);
}
if (page.children && page.children.length) {
filePaths.push(...resolvePageFiles(page.children));
}
});
return filePaths;
};
const getModuleConfigs = () => {
const thenCallHook = async (resolvedConfig) => {
const { configFile: resolvedConfigFile } = resolvedConfig;
if (!resolvedConfigFile || !resolvedConfig.config) {
return { ...resolvedConfig, configFile: resolvedConfigFile === "tailwind.config" ? void 0 : resolvedConfigFile };
}
const config = configMerger(void 0, resolvedConfig.config);
configUpdatedHook[resolvedConfigFile] = "";
if (resolvedConfig.config?.purge && !resolvedConfig.config.content) {
configUpdatedHook[resolvedConfigFile] += "cfg.content = cfg.purge;";
}
await nuxt.callHook("tailwindcss:loadConfig", config, resolvedConfigFile, 0, []);
trackObjChanges(resolvedConfigFile, resolvedConfig.config, config);
return { ...resolvedConfig, config };
};
return Promise.all([
resolveContentConfig(nuxt.options.rootDir, nuxt.options),
...resolveConfigs(moduleOptions.config, nuxt),
loadConfig({ name: "tailwind", cwd: nuxt.options.rootDir, merger: configMerger, packageJson: true, extend: false }).then(thenCallHook),
...resolveConfigs(moduleOptions.configPath, nuxt),
...(nuxt.options._layers || []).slice(1).flatMap((nuxtLayer) => [
resolveContentConfig(nuxtLayer.config.rootDir || nuxtLayer.cwd, nuxtLayer.config),
...resolveConfigs(nuxtLayer.config.tailwindcss?.config, nuxt),
loadConfig({ name: "tailwind", cwd: nuxtLayer.cwd, merger: configMerger, packageJson: true, extend: false }).then(thenCallHook),
...resolveConfigs(nuxtLayer.config.tailwindcss?.configPath, nuxt)
])
]);
};
const resolveTWConfig = await import('tailwindcss/resolveConfig.js').then((m) => m.default || m).catch(() => (c) => c);
const loadConfigs = async () => {
const moduleConfigs = await getModuleConfigs();
resolvedConfigsCtx.set(moduleConfigs, true);
const tailwindConfig = moduleConfigs.reduce((acc, curr) => configMerger(acc, curr?.config ?? {}), {});
const clonedConfig = configMerger(void 0, tailwindConfig);
configUpdatedHook["main-config"] = "";
await nuxt.callHook("tailwindcss:config", clonedConfig);
trackObjChanges("main-config", tailwindConfig, clonedConfig);
const resolvedConfig = resolveTWConfig(clonedConfig);
await nuxt.callHook("tailwindcss:resolvedConfig", resolvedConfig, twCtx.tryUse()?.config ?? void 0);
twCtx.set({ config: resolvedConfig });
return tailwindConfig;
};
const generateConfig = () => {
const ctx = twCtx.tryUse();
const targetDir = join(nuxt.options.buildDir, "tailwind");
const template = !meta.disableHMR || !ctx?.meta?.disableHMR ? addTemplate({
filename: "tailwind/postcss.mjs",
write: true,
getContents: () => {
const serializeConfig = (config) => JSON.stringify(
Array.isArray(config.plugins) && config.plugins.length > 0 ? configMerger({ plugins: (defaultPlugins) => defaultPlugins?.filter((p) => p && typeof p !== "function") }, config) : config,
(_, v) => typeof v === "function" ? `() => (${JSON.stringify(v())})` : v
).replace(/"(\(\) => \(.*\))"/g, (_, substr) => substr.replace(/\\"/g, '"'));
const layerConfigs = resolvedConfigsCtx.use().map((c, idx) => c?.configFile ? [`import cfg${idx} from ${JSON.stringify(/[/\\]node_modules[/\\]/.test(c.configFile) ? c.configFile : "./" + relative(targetDir, c.configFile))}`, configUpdatedHook[c.configFile] ? `(() => {const cfg=configMerger(undefined, cfg${idx});${configUpdatedHook[c.configFile]};return cfg;})()` : `cfg${idx}`] : [null, c?.config ? serializeConfig(c.config) : null]);
return [
`// generated by the @nuxtjs/tailwindcss <https://github.com/nuxt-modules/tailwindcss> module at ${( new Date()).toLocaleString()}`,
'import "@nuxtjs/tailwindcss/config-ctx"',
`import configMerger from "@nuxtjs/tailwindcss/merger";
`,
layerConfigs.map(([i, _]) => i).filter(Boolean).join(";\n") + ";",
"const config = [",
layerConfigs.map(([_, i]) => i).filter(Boolean).join(",\n"),
`].reduce((acc, curr) => configMerger(acc, curr), {});
`,
`const resolvedConfig = ${configUpdatedHook["main-config"] ? `(() => {const cfg=config;${configUpdatedHook["main-config"]};return cfg;})()` : "config"};
`,
"export default resolvedConfig;"
].join("\n");
}
}) : { dst: "" };
twCtx.set({ dst: template.dst });
return template;
};
const registerHooks = () => {
if (twCtx.use().meta?.disableHMR)
return;
const reloadConfigTemplate = async () => {
const { dst } = twCtx.use();
await loadConfigs();
setTimeout(async () => {
await updateTemplates({ filter: (t) => t.dst === dst || dst?.endsWith(t.filename) || false });
await nuxt.callHook("tailwindcss:internal:regenerateTemplates", { configTemplateUpdated: true });
}, 100);
};
nuxt.hook("app:templatesGenerated", async (_app, templates) => {
if (Array.isArray(templates) && templates?.some((t) => Object.keys(configUpdatedHook).includes(t.dst))) {
await reloadConfigTemplate();
}
});
if (moduleOptions.experimental?.strictScanContentPaths) {
nuxt.hook("pages:extend", async (pages) => {
const newPageFiles = resolvePageFiles(pages);
if (newPageFiles.length !== pagesContentPath.tryUse()?.length) {
pagesContentPath.set(newPageFiles, true);
await reloadConfigTemplate();
}
});
nuxt.hook("components:extend", async (components) => {
const newComponentFiles = components.map((c) => c.filePath);
if (newComponentFiles.length !== componentsContentPath.tryUse()?.length) {
componentsContentPath.set(newComponentFiles, true);
await reloadConfigTemplate();
}
});
} else {
nuxt.hook("pages:extend", () => reloadConfigTemplate());
}
nuxt.hook("vite:serverCreated", (server) => {
nuxt.hook("tailwindcss:internal:regenerateTemplates", (data) => {
if (!data || !data.configTemplateUpdated)
return;
const ctx = twCtx.use();
const configFile = ctx.dst && server.moduleGraph.getModuleById(ctx.dst);
configFile && server.moduleGraph.invalidateModule(configFile);
});
});
moduleOptions.exposeConfig && nuxt.hook("builder:watch", async (_, path) => {
if (Object.keys(configUpdatedHook).includes(join(nuxt.options.rootDir, path))) {
const ctx = twCtx.use();
setTimeout(async () => {
await import(ctx.dst).then(async (_config) => {
twCtx.set({ config: resolveTWConfig(_config.default ?? _config) });
await nuxt.callHook("tailwindcss:internal:regenerateTemplates");
});
}, 100);
}
});
};
return {
loadConfigs,
generateConfig,
registerHooks
};
};
const defaults = (nuxt = useNuxt()) => ({
configPath: [],
cssPath: join(nuxt.options.dir.assets, "css/tailwind.css"),
config: {},
viewer: nuxt.options.dev,
exposeConfig: false,
quiet: nuxt.options.logLevel === "silent",
editorSupport: false
});
const module = defineNuxtModule({
meta: { name, version, configKey, compatibility },
defaults,
async setup(moduleOptions, nuxt) {
if (moduleOptions.quiet)
logger.level = LogLevels.silent;
if (Number.parseFloat(getNuxtVersion()) < 2.16) {
await installModule("@nuxt/postcss8").catch((e) => {
logger.error(`Error occurred while loading \`@nuxt/postcss8\` required for Nuxt ${getNuxtVersion()}, is it installed?`);
throw e;
});
}
const isTailwind4 = await readPackageJSON("tailwindcss", { parent: import.meta.url }).then((m) => Number.parseFloat(m.version) >= 4);
if (isTailwind4 && !moduleOptions.experimental?.tailwindcss4) {
logger.warn("Tailwind CSS v4 detected. The current version of `@nuxtjs/tailwindcss` supports Tailwind CSS 3 officially and support for v4 is experimental. To suppress this warning, set `tailwindcss.experimental.tailwindcss4` to `true` in your `nuxt.config`.");
}
const ctx = await createInternalContext(moduleOptions, nuxt);
if (moduleOptions.editorSupport) {
const editorSupportConfig = resolveEditorSupportConfig(moduleOptions.editorSupport);
if (editorSupportConfig.autocompleteUtil && !isNuxtMajorVersion(2, nuxt)) {
addImports({
name: "autocompleteUtil",
from: createResolver(import.meta.url).resolve("./runtime/utils"),
as: "tw",
...typeof editorSupportConfig.autocompleteUtil === "object" ? editorSupportConfig.autocompleteUtil : {}
});
}
}
const [cssPath, cssPathConfig] = Array.isArray(moduleOptions.cssPath) ? moduleOptions.cssPath : [moduleOptions.cssPath];
const [resolvedCss, loggerInfo] = await resolveCSSPath(cssPath, nuxt).catch((e) => {
if (isTailwind4) {
return [addTemplate({ filename: "tailwind.css", getContents: () => `@import 'tailwindcss';`, write: true }).dst, "Generating default CSS file for Tailwind CSS 4..."];
}
throw e;
});
logger.info(loggerInfo);
nuxt.options.css = nuxt.options.css ?? [];
const resolvedNuxtCss = resolvedCss && await Promise.all(nuxt.options.css.map((p) => resolvePath(p.src ?? p))) || [];
if (resolvedCss && !resolvedNuxtCss.includes(resolvedCss)) {
const injectPosition = await resolveInjectPosition(resolvedNuxtCss, cssPathConfig?.injectPosition);
nuxt.options.css.splice(injectPosition, 0, resolvedCss);
}
const shouldInstallTWVitePlugin = isTailwind4 && nuxt.options.builder === "@nuxt/vite-builder";
if (shouldInstallTWVitePlugin) {
await import('@tailwindcss/vite').then((r) => addVitePlugin(r.default()));
}
let nuxt2ViewerConfig = join(nuxt.options.buildDir, "tailwind/postcss.mjs");
nuxt.hook("modules:done", async () => {
const _config = await ctx.loadConfigs();
const twConfig = ctx.generateConfig();
ctx.registerHooks();
nuxt2ViewerConfig = twConfig.dst || _config;
if (moduleOptions.exposeConfig) {
const exposeConfig = resolveExposeConfig(moduleOptions.exposeConfig);
const exposeTemplates = createExposeTemplates(exposeConfig);
nuxt.hook("tailwindcss:internal:regenerateTemplates", () => updateTemplates({ filter: (template) => exposeTemplates.includes(template.dst) }));
}
if (!shouldInstallTWVitePlugin) {
const postcssOptions = nuxt.options.postcss || nuxt.options.build.postcss.postcssOptions || nuxt.options.build.postcss;
const pluginsToAdd = isTailwind4 ? { "@tailwindcss/postcss": {} } : {
"tailwindcss/nesting": postcssOptions.plugins?.["tailwindcss/nesting"] ?? {},
"tailwindcss": twConfig.dst || _config
};
postcssOptions.plugins = {
...postcssOptions.plugins || {},
...pluginsToAdd
};
}
if (nuxt.options.dev && !isNuxtMajorVersion(2, nuxt)) {
if (moduleOptions.viewer) {
const viewerConfig = resolveViewerConfig(moduleOptions.viewer);
setupViewer(twConfig.dst || _config, viewerConfig, nuxt);
}
} else {
if (!nuxt.options.dev)
return;
if (moduleOptions.viewer) {
const viewerConfig = resolveViewerConfig(moduleOptions.viewer);
exportViewer(twConfig.dst || addTemplate({ filename: "tailwind.config/viewer-config.cjs", getContents: () => `module.exports = ${JSON.stringify(_config)}`, write: true }).dst, viewerConfig);
}
}
});
if (nuxt.options.dev && moduleOptions.viewer && isNuxtMajorVersion(2, nuxt)) {
const viewerConfig = resolveViewerConfig(moduleOptions.viewer);
setupViewer(nuxt2ViewerConfig, viewerConfig, nuxt);
}
}
});
export { module as default };

View File

@@ -0,0 +1 @@
export declare const autocompleteUtil: <T extends TemplateStringsArray | string>(tailwindClasses: T) => T;

View File

@@ -0,0 +1 @@
export const autocompleteUtil = (tailwindClasses) => tailwindClasses;

View File

@@ -0,0 +1,181 @@
import * as tailwindcss_resolveConfig from 'tailwindcss/resolveConfig';
import * as tailwindcss from 'tailwindcss';
import * as nuxt_kit from 'nuxt/kit';
type Import = Exclude<Parameters<typeof nuxt_kit['addImports']>[0], any[]>;
type TWConfig = tailwindcss.Config;
type InjectPosition = 'first' | 'last' | number | {
after: string;
};
type _Omit<T, K extends PropertyKey> = {
[P in keyof T as Exclude<P, K>]: T[P];
};
type InlineTWConfig = _Omit<TWConfig, 'content' | 'plugins' | 'safelist'> & {
content?: (Extract<TWConfig['content'], any[]> | _Omit<Extract<TWConfig['content'], Record<string, any>>, 'extract' | 'transform'>);
safelist?: Exclude<NonNullable<TWConfig['safelist']>[number], Record<string, any>>[];
};
type BoolObj<T extends Record<string, any>> = boolean | Partial<T>;
type Arrayable<T> = T | T[];
type ViewerConfig = {
/**
* The endpoint for the viewer
*
* @default '/_tailwind'
*/
endpoint: `/${string}`;
/**
* Export the viewer during build
*
* Works in Nuxt 3; for Nuxt 2, use `npx tailwind-config-viewer export`
*
* @default false
*/
exportViewer: boolean;
};
type ExposeConfig = {
/**
* Import name for the configuration
*
* @default '#tailwind-config'
* @deprecated use `alias` in `nuxt.config` instead - https://nuxt.com/docs/api/nuxt-config#alias
*/
alias: string;
/**
* Deeper references within configuration for optimal tree-shaking.
*
* @default 2
*/
level: number;
/**
* To write the templates to file-system for usage with code that does not have access to the Virtual File System. This applies only for Nuxt 3 with Vite.
*
* @deprecated use a module if a necessary using the `app:templates` hook to write templates like so: https://github.com/nuxt/module-builder/blob/4697f18429efb83b82f3b256dd8926bb94d3df77/src/commands/prepare.ts#L37-L43
*/
write?: boolean;
};
type EditorSupportConfig = {
/**
* Enable utility to write Tailwind CSS classes inside strings.
*
* You will need to update `.vscode/settings.json` based on this value. This works only for Nuxt 3 or Nuxt 2 with Bridge.
*
* ```json
* {
* "tailwindCSS.experimental.classRegex": ["tw`(.*?)`", "tw\\('(.*?)'\\)"]
* }
* ```
*
* Read https://tailwindcss.nuxtjs.org/tailwind/editor-support#string-classes-autocomplete.
*
* @default false // if true, { as: 'tw' }
*/
autocompleteUtil: BoolObj<Pick<Import, 'as'>>;
};
type ExperimentalOptions = {
/**
* Specify individual files for Nuxt scanned directories in content configuration
* using `pages:extend` and `components:extend` hook.
*
* @default false
*/
strictScanContentPaths: boolean;
/**
* Allow usage of Tailwind CSS 4.
*
* @default false
*/
tailwindcss4: boolean;
};
interface ModuleOptions {
/**
* The path of the Tailwind configuration file. The extension can be omitted, in which case it will try to find a `.js`, `.cjs`, `.mjs`, or `.ts` file.
*
* @default []
* @deprecated provide string in `config`
*/
configPath: Arrayable<string>;
/**
* The path of the Tailwind CSS file. If the file does not exist, the module's default CSS file will be imported instead.
*
* @default '~/assets/css/tailwind.css'
*/
cssPath: string | false | [string, {
injectPosition: InjectPosition;
}];
/**
* Configuration for Tailwind CSS. Accepts (array of) string and inline configurations.
*
* for default, see https://tailwindcss.nuxtjs.org/tailwind/config
*/
config: Arrayable<InlineTWConfig | string>;
/**
* [tailwind-config-viewer](https://github.com/rogden/tailwind-config-viewer) usage *in development*
*
* @default true // { endpoint: '_tailwind' }
*/
viewer: BoolObj<ViewerConfig>;
/**
* Usage of configuration references in runtime. See https://tailwindcss.nuxtjs.org/tailwind/config#referencing-in-the-application
*
* @default false // if true, { alias: '#tailwind-config', level: 2 }
*/
exposeConfig: BoolObj<ExposeConfig>;
/**
* Suppress logging to the console when everything is ok
*
* @default nuxt.options.logLevel === 'silent'
*/
quiet: boolean;
/**
* Enable some utilities for better editor support and DX.
*
* Read https://tailwindcss.nuxtjs.org/tailwind/editor-support.
*
* @default false // if true, { autocompleteUtil: true }
*/
editorSupport: BoolObj<EditorSupportConfig>;
/**
* Enable module experimental functionalities.
*
* @default false
*/
experimental?: Partial<ExperimentalOptions>;
/**
* This option falls back to the Tailwind configuration inlined to the PostCSS
* loader, so any configuration changes while the dev server is running will
* not reflect. This is similar to the functionality prior to v6.12.0.
*
* Note: this is only provided for temporary broken builds that may require
* migration. Usage is discouraged. If any issues occur without this, please open
* an issue on https://github.com/nuxt-modules/tailwindcss/issues.
*/
disableHMR?: boolean;
}
interface ModuleHooks {
/**
* Passes any Tailwind configuration read by the module for each (extended) [layer](https://nuxt.com/docs/getting-started/layers) and [path](https://tailwindcss.nuxtjs.org/getting-started/options#configpath) before merging all of them.
*
* @param tailwindConfig
* @returns
*/
'tailwindcss:config': (tailwindConfig: Partial<TWConfig>) => void;
/**
* Passes the resolved vanilla configuration read from all layers and paths with merging using [defu](https://github.com/unjs/defu).
*
* @param tailwindConfig
* @param configPath
* @param index
* @param configPaths
* @returns
*/
'tailwindcss:loadConfig': (tailwindConfig: Partial<TWConfig> | undefined, configPath: string, index: number, configPaths: string[]) => void;
/**
* Passes the complete resolved configuration with all defaults from [the full Tailwind config](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/config.full.js) using resolveConfig.
*
* @param tailwindConfig
* @returns
*/
'tailwindcss:resolvedConfig': (tailwindConfig: ReturnType<typeof tailwindcss_resolveConfig>, oldTailwindConfig: TWConfig | undefined) => void;
}
export type { ModuleHooks as M, TWConfig as T, ModuleOptions as a };

View File

@@ -0,0 +1,181 @@
import * as tailwindcss_resolveConfig from 'tailwindcss/resolveConfig';
import * as tailwindcss from 'tailwindcss';
import * as nuxt_kit from 'nuxt/kit';
type Import = Exclude<Parameters<typeof nuxt_kit['addImports']>[0], any[]>;
type TWConfig = tailwindcss.Config;
type InjectPosition = 'first' | 'last' | number | {
after: string;
};
type _Omit<T, K extends PropertyKey> = {
[P in keyof T as Exclude<P, K>]: T[P];
};
type InlineTWConfig = _Omit<TWConfig, 'content' | 'plugins' | 'safelist'> & {
content?: (Extract<TWConfig['content'], any[]> | _Omit<Extract<TWConfig['content'], Record<string, any>>, 'extract' | 'transform'>);
safelist?: Exclude<NonNullable<TWConfig['safelist']>[number], Record<string, any>>[];
};
type BoolObj<T extends Record<string, any>> = boolean | Partial<T>;
type Arrayable<T> = T | T[];
type ViewerConfig = {
/**
* The endpoint for the viewer
*
* @default '/_tailwind'
*/
endpoint: `/${string}`;
/**
* Export the viewer during build
*
* Works in Nuxt 3; for Nuxt 2, use `npx tailwind-config-viewer export`
*
* @default false
*/
exportViewer: boolean;
};
type ExposeConfig = {
/**
* Import name for the configuration
*
* @default '#tailwind-config'
* @deprecated use `alias` in `nuxt.config` instead - https://nuxt.com/docs/api/nuxt-config#alias
*/
alias: string;
/**
* Deeper references within configuration for optimal tree-shaking.
*
* @default 2
*/
level: number;
/**
* To write the templates to file-system for usage with code that does not have access to the Virtual File System. This applies only for Nuxt 3 with Vite.
*
* @deprecated use a module if a necessary using the `app:templates` hook to write templates like so: https://github.com/nuxt/module-builder/blob/4697f18429efb83b82f3b256dd8926bb94d3df77/src/commands/prepare.ts#L37-L43
*/
write?: boolean;
};
type EditorSupportConfig = {
/**
* Enable utility to write Tailwind CSS classes inside strings.
*
* You will need to update `.vscode/settings.json` based on this value. This works only for Nuxt 3 or Nuxt 2 with Bridge.
*
* ```json
* {
* "tailwindCSS.experimental.classRegex": ["tw`(.*?)`", "tw\\('(.*?)'\\)"]
* }
* ```
*
* Read https://tailwindcss.nuxtjs.org/tailwind/editor-support#string-classes-autocomplete.
*
* @default false // if true, { as: 'tw' }
*/
autocompleteUtil: BoolObj<Pick<Import, 'as'>>;
};
type ExperimentalOptions = {
/**
* Specify individual files for Nuxt scanned directories in content configuration
* using `pages:extend` and `components:extend` hook.
*
* @default false
*/
strictScanContentPaths: boolean;
/**
* Allow usage of Tailwind CSS 4.
*
* @default false
*/
tailwindcss4: boolean;
};
interface ModuleOptions {
/**
* The path of the Tailwind configuration file. The extension can be omitted, in which case it will try to find a `.js`, `.cjs`, `.mjs`, or `.ts` file.
*
* @default []
* @deprecated provide string in `config`
*/
configPath: Arrayable<string>;
/**
* The path of the Tailwind CSS file. If the file does not exist, the module's default CSS file will be imported instead.
*
* @default '~/assets/css/tailwind.css'
*/
cssPath: string | false | [string, {
injectPosition: InjectPosition;
}];
/**
* Configuration for Tailwind CSS. Accepts (array of) string and inline configurations.
*
* for default, see https://tailwindcss.nuxtjs.org/tailwind/config
*/
config: Arrayable<InlineTWConfig | string>;
/**
* [tailwind-config-viewer](https://github.com/rogden/tailwind-config-viewer) usage *in development*
*
* @default true // { endpoint: '_tailwind' }
*/
viewer: BoolObj<ViewerConfig>;
/**
* Usage of configuration references in runtime. See https://tailwindcss.nuxtjs.org/tailwind/config#referencing-in-the-application
*
* @default false // if true, { alias: '#tailwind-config', level: 2 }
*/
exposeConfig: BoolObj<ExposeConfig>;
/**
* Suppress logging to the console when everything is ok
*
* @default nuxt.options.logLevel === 'silent'
*/
quiet: boolean;
/**
* Enable some utilities for better editor support and DX.
*
* Read https://tailwindcss.nuxtjs.org/tailwind/editor-support.
*
* @default false // if true, { autocompleteUtil: true }
*/
editorSupport: BoolObj<EditorSupportConfig>;
/**
* Enable module experimental functionalities.
*
* @default false
*/
experimental?: Partial<ExperimentalOptions>;
/**
* This option falls back to the Tailwind configuration inlined to the PostCSS
* loader, so any configuration changes while the dev server is running will
* not reflect. This is similar to the functionality prior to v6.12.0.
*
* Note: this is only provided for temporary broken builds that may require
* migration. Usage is discouraged. If any issues occur without this, please open
* an issue on https://github.com/nuxt-modules/tailwindcss/issues.
*/
disableHMR?: boolean;
}
interface ModuleHooks {
/**
* Passes any Tailwind configuration read by the module for each (extended) [layer](https://nuxt.com/docs/getting-started/layers) and [path](https://tailwindcss.nuxtjs.org/getting-started/options#configpath) before merging all of them.
*
* @param tailwindConfig
* @returns
*/
'tailwindcss:config': (tailwindConfig: Partial<TWConfig>) => void;
/**
* Passes the resolved vanilla configuration read from all layers and paths with merging using [defu](https://github.com/unjs/defu).
*
* @param tailwindConfig
* @param configPath
* @param index
* @param configPaths
* @returns
*/
'tailwindcss:loadConfig': (tailwindConfig: Partial<TWConfig> | undefined, configPath: string, index: number, configPaths: string[]) => void;
/**
* Passes the complete resolved configuration with all defaults from [the full Tailwind config](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/config.full.js) using resolveConfig.
*
* @param tailwindConfig
* @returns
*/
'tailwindcss:resolvedConfig': (tailwindConfig: ReturnType<typeof tailwindcss_resolveConfig>, oldTailwindConfig: TWConfig | undefined) => void;
}
export type { ModuleHooks as M, TWConfig as T, ModuleOptions as a };

View File

@@ -0,0 +1,181 @@
import * as tailwindcss_resolveConfig from 'tailwindcss/resolveConfig';
import * as tailwindcss from 'tailwindcss';
import * as nuxt_kit from 'nuxt/kit';
type Import = Exclude<Parameters<typeof nuxt_kit['addImports']>[0], any[]>;
type TWConfig = tailwindcss.Config;
type InjectPosition = 'first' | 'last' | number | {
after: string;
};
type _Omit<T, K extends PropertyKey> = {
[P in keyof T as Exclude<P, K>]: T[P];
};
type InlineTWConfig = _Omit<TWConfig, 'content' | 'plugins' | 'safelist'> & {
content?: (Extract<TWConfig['content'], any[]> | _Omit<Extract<TWConfig['content'], Record<string, any>>, 'extract' | 'transform'>);
safelist?: Exclude<NonNullable<TWConfig['safelist']>[number], Record<string, any>>[];
};
type BoolObj<T extends Record<string, any>> = boolean | Partial<T>;
type Arrayable<T> = T | T[];
type ViewerConfig = {
/**
* The endpoint for the viewer
*
* @default '/_tailwind'
*/
endpoint: `/${string}`;
/**
* Export the viewer during build
*
* Works in Nuxt 3; for Nuxt 2, use `npx tailwind-config-viewer export`
*
* @default false
*/
exportViewer: boolean;
};
type ExposeConfig = {
/**
* Import name for the configuration
*
* @default '#tailwind-config'
* @deprecated use `alias` in `nuxt.config` instead - https://nuxt.com/docs/api/nuxt-config#alias
*/
alias: string;
/**
* Deeper references within configuration for optimal tree-shaking.
*
* @default 2
*/
level: number;
/**
* To write the templates to file-system for usage with code that does not have access to the Virtual File System. This applies only for Nuxt 3 with Vite.
*
* @deprecated use a module if a necessary using the `app:templates` hook to write templates like so: https://github.com/nuxt/module-builder/blob/4697f18429efb83b82f3b256dd8926bb94d3df77/src/commands/prepare.ts#L37-L43
*/
write?: boolean;
};
type EditorSupportConfig = {
/**
* Enable utility to write Tailwind CSS classes inside strings.
*
* You will need to update `.vscode/settings.json` based on this value. This works only for Nuxt 3 or Nuxt 2 with Bridge.
*
* ```json
* {
* "tailwindCSS.experimental.classRegex": ["tw`(.*?)`", "tw\\('(.*?)'\\)"]
* }
* ```
*
* Read https://tailwindcss.nuxtjs.org/tailwind/editor-support#string-classes-autocomplete.
*
* @default false // if true, { as: 'tw' }
*/
autocompleteUtil: BoolObj<Pick<Import, 'as'>>;
};
type ExperimentalOptions = {
/**
* Specify individual files for Nuxt scanned directories in content configuration
* using `pages:extend` and `components:extend` hook.
*
* @default false
*/
strictScanContentPaths: boolean;
/**
* Allow usage of Tailwind CSS 4.
*
* @default false
*/
tailwindcss4: boolean;
};
interface ModuleOptions {
/**
* The path of the Tailwind configuration file. The extension can be omitted, in which case it will try to find a `.js`, `.cjs`, `.mjs`, or `.ts` file.
*
* @default []
* @deprecated provide string in `config`
*/
configPath: Arrayable<string>;
/**
* The path of the Tailwind CSS file. If the file does not exist, the module's default CSS file will be imported instead.
*
* @default '~/assets/css/tailwind.css'
*/
cssPath: string | false | [string, {
injectPosition: InjectPosition;
}];
/**
* Configuration for Tailwind CSS. Accepts (array of) string and inline configurations.
*
* for default, see https://tailwindcss.nuxtjs.org/tailwind/config
*/
config: Arrayable<InlineTWConfig | string>;
/**
* [tailwind-config-viewer](https://github.com/rogden/tailwind-config-viewer) usage *in development*
*
* @default true // { endpoint: '_tailwind' }
*/
viewer: BoolObj<ViewerConfig>;
/**
* Usage of configuration references in runtime. See https://tailwindcss.nuxtjs.org/tailwind/config#referencing-in-the-application
*
* @default false // if true, { alias: '#tailwind-config', level: 2 }
*/
exposeConfig: BoolObj<ExposeConfig>;
/**
* Suppress logging to the console when everything is ok
*
* @default nuxt.options.logLevel === 'silent'
*/
quiet: boolean;
/**
* Enable some utilities for better editor support and DX.
*
* Read https://tailwindcss.nuxtjs.org/tailwind/editor-support.
*
* @default false // if true, { autocompleteUtil: true }
*/
editorSupport: BoolObj<EditorSupportConfig>;
/**
* Enable module experimental functionalities.
*
* @default false
*/
experimental?: Partial<ExperimentalOptions>;
/**
* This option falls back to the Tailwind configuration inlined to the PostCSS
* loader, so any configuration changes while the dev server is running will
* not reflect. This is similar to the functionality prior to v6.12.0.
*
* Note: this is only provided for temporary broken builds that may require
* migration. Usage is discouraged. If any issues occur without this, please open
* an issue on https://github.com/nuxt-modules/tailwindcss/issues.
*/
disableHMR?: boolean;
}
interface ModuleHooks {
/**
* Passes any Tailwind configuration read by the module for each (extended) [layer](https://nuxt.com/docs/getting-started/layers) and [path](https://tailwindcss.nuxtjs.org/getting-started/options#configpath) before merging all of them.
*
* @param tailwindConfig
* @returns
*/
'tailwindcss:config': (tailwindConfig: Partial<TWConfig>) => void;
/**
* Passes the resolved vanilla configuration read from all layers and paths with merging using [defu](https://github.com/unjs/defu).
*
* @param tailwindConfig
* @param configPath
* @param index
* @param configPaths
* @returns
*/
'tailwindcss:loadConfig': (tailwindConfig: Partial<TWConfig> | undefined, configPath: string, index: number, configPaths: string[]) => void;
/**
* Passes the complete resolved configuration with all defaults from [the full Tailwind config](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/config.full.js) using resolveConfig.
*
* @param tailwindConfig
* @returns
*/
'tailwindcss:resolvedConfig': (tailwindConfig: ReturnType<typeof tailwindcss_resolveConfig>, oldTailwindConfig: TWConfig | undefined) => void;
}
export type { ModuleHooks as M, TWConfig as T, ModuleOptions as a };

7
node_modules/@nuxtjs/tailwindcss/dist/types.d.mts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
import type { ModuleHooks } from './module.js'
declare module '@nuxt/schema' {
interface NuxtHooks extends ModuleHooks {}
}
export { type ModuleHooks, type ModuleOptions, default } from './module.js'

7
node_modules/@nuxtjs/tailwindcss/dist/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
import type { ModuleHooks } from './module'
declare module '@nuxt/schema' {
interface NuxtHooks extends ModuleHooks {}
}
export { type ModuleHooks, type ModuleOptions, default } from './module'

View File

@@ -0,0 +1,70 @@
MIT License
Copyright (c) Pooya Parsa <pooya@pi0.io> - Daniel Roe <daniel@roe.dev>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
Copyright Joyent, Inc. and other Node contributors.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
---
Bundled zeptomatch (https://github.com/fabiospampinato/zeptomatch)
The MIT License (MIT)
Copyright (c) 2023-present Fabio Spampinato
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,73 @@
# 🛣️ pathe
> Universal filesystem path utils
[![version][npm-v-src]][npm-v-href]
[![downloads][npm-d-src]][npm-d-href]
[![size][size-src]][size-href]
## ❓ Why
For [historical reasons](https://docs.microsoft.com/en-us/archive/blogs/larryosterman/why-is-the-dos-path-character), windows followed MS-DOS and used backslash for separating paths rather than slash used for macOS, Linux, and other Posix operating systems. Nowadays, [Windows](https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN) supports both Slash and Backslash for paths. [Node.js's built-in `path` module](https://nodejs.org/api/path.html) in the default operation of the path module varies based on the operating system on which a Node.js application is running. Specifically, when running on a Windows operating system, the path module will assume that Windows-style paths are being used. **This makes inconsistent code behavior between Windows and POSIX.**
Compared to popular [upath](https://github.com/anodynos/upath), pathe provides **identical exports** of Node.js with normalization on **all operations** and is written in modern **ESM/TypeScript** and has **no dependency on Node.js**!
This package is a drop-in replacement of the Node.js's [path module](https://nodejs.org/api/path.html) module and ensures paths are normalized with slash `/` and work in environments including Node.js.
## 💿 Usage
Install using npm or yarn:
```bash
# npm
npm i pathe
# yarn
yarn add pathe
# pnpm
pnpm i pathe
```
Import:
```js
// ESM / Typescript
import { resolve, matchesGlob } from "pathe";
// CommonJS
const { resolve, matchesGlob } = require("pathe");
```
Read more about path utils from [Node.js documentation](https://nodejs.org/api/path.html) and rest assured behavior is consistently like POSIX regardless of your input paths format and running platform (the only exception is `delimiter` constant export, it will be set to `;` on windows platform).
### Extra utilities
Pathe exports some extra utilities that do not exist in standard Node.js [path module](https://nodejs.org/api/path.html).
In order to use them, you can import from `pathe/utils` subpath:
```js
import {
filename,
normalizeAliases,
resolveAlias,
reverseResolveAlias,
} from "pathe/utils";
```
## License
Made with 💛 Published under the [MIT](./LICENSE) license.
Some code was used from the Node.js project. Glob supported is powered by [zeptomatch](https://github.com/fabiospampinato/zeptomatch).
<!-- Refs -->
[npm-v-src]: https://img.shields.io/npm/v/pathe?style=flat-square
[npm-v-href]: https://npmjs.com/package/pathe
[npm-d-src]: https://img.shields.io/npm/dm/pathe?style=flat-square
[npm-d-href]: https://npmjs.com/package/pathe
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/pathe/ci/main?style=flat-square
[github-actions-href]: https://github.com/unjs/pathe/actions?query=workflow%3Aci
[size-src]: https://packagephobia.now.sh/badge?p=pathe
[size-href]: https://packagephobia.now.sh/result?p=pathe

View File

@@ -0,0 +1,39 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const _path = require('./shared/pathe.BSlhyZSM.cjs');
const delimiter = /* @__PURE__ */ (() => globalThis.process?.platform === "win32" ? ";" : ":")();
const _platforms = { posix: void 0, win32: void 0 };
const mix = (del = delimiter) => {
return new Proxy(_path._path, {
get(_, prop) {
if (prop === "delimiter") return del;
if (prop === "posix") return posix;
if (prop === "win32") return win32;
return _platforms[prop] || _path._path[prop];
}
});
};
const posix = /* @__PURE__ */ mix(":");
const win32 = /* @__PURE__ */ mix(";");
exports.basename = _path.basename;
exports.dirname = _path.dirname;
exports.extname = _path.extname;
exports.format = _path.format;
exports.isAbsolute = _path.isAbsolute;
exports.join = _path.join;
exports.matchesGlob = _path.matchesGlob;
exports.normalize = _path.normalize;
exports.normalizeString = _path.normalizeString;
exports.parse = _path.parse;
exports.relative = _path.relative;
exports.resolve = _path.resolve;
exports.sep = _path.sep;
exports.toNamespacedPath = _path.toNamespacedPath;
exports.default = posix;
exports.delimiter = delimiter;
exports.posix = posix;
exports.win32 = win32;

View File

@@ -0,0 +1,47 @@
import * as path from 'node:path';
import path__default from 'node:path';
/**
* Constant for path separator.
*
* Always equals to `"/"`.
*/
declare const sep = "/";
declare const normalize: typeof path__default.normalize;
declare const join: typeof path__default.join;
declare const resolve: typeof path__default.resolve;
/**
* Resolves a string path, resolving '.' and '.' segments and allowing paths above the root.
*
* @param path - The path to normalise.
* @param allowAboveRoot - Whether to allow the resulting path to be above the root directory.
* @returns the normalised path string.
*/
declare function normalizeString(path: string, allowAboveRoot: boolean): string;
declare const isAbsolute: typeof path__default.isAbsolute;
declare const toNamespacedPath: typeof path__default.toNamespacedPath;
declare const extname: typeof path__default.extname;
declare const relative: typeof path__default.relative;
declare const dirname: typeof path__default.dirname;
declare const format: typeof path__default.format;
declare const basename: typeof path__default.basename;
declare const parse: typeof path__default.parse;
/**
* The `path.matchesGlob()` method determines if `path` matches the `pattern`.
* @param path The path to glob-match against.
* @param pattern The glob to check the path against.
*/
declare const matchesGlob: (path: string, pattern: string | string[]) => boolean;
type NodePath = typeof path;
/**
* The platform-specific file delimiter.
*
* Equals to `";"` in windows and `":"` in all other platforms.
*/
declare const delimiter: ";" | ":";
declare const posix: NodePath["posix"];
declare const win32: NodePath["win32"];
declare const _default: NodePath;
export { basename, _default as default, delimiter, dirname, extname, format, isAbsolute, join, matchesGlob, normalize, normalizeString, parse, posix, relative, resolve, sep, toNamespacedPath, win32 };

View File

@@ -0,0 +1,47 @@
import * as path from 'node:path';
import path__default from 'node:path';
/**
* Constant for path separator.
*
* Always equals to `"/"`.
*/
declare const sep = "/";
declare const normalize: typeof path__default.normalize;
declare const join: typeof path__default.join;
declare const resolve: typeof path__default.resolve;
/**
* Resolves a string path, resolving '.' and '.' segments and allowing paths above the root.
*
* @param path - The path to normalise.
* @param allowAboveRoot - Whether to allow the resulting path to be above the root directory.
* @returns the normalised path string.
*/
declare function normalizeString(path: string, allowAboveRoot: boolean): string;
declare const isAbsolute: typeof path__default.isAbsolute;
declare const toNamespacedPath: typeof path__default.toNamespacedPath;
declare const extname: typeof path__default.extname;
declare const relative: typeof path__default.relative;
declare const dirname: typeof path__default.dirname;
declare const format: typeof path__default.format;
declare const basename: typeof path__default.basename;
declare const parse: typeof path__default.parse;
/**
* The `path.matchesGlob()` method determines if `path` matches the `pattern`.
* @param path The path to glob-match against.
* @param pattern The glob to check the path against.
*/
declare const matchesGlob: (path: string, pattern: string | string[]) => boolean;
type NodePath = typeof path;
/**
* The platform-specific file delimiter.
*
* Equals to `";"` in windows and `":"` in all other platforms.
*/
declare const delimiter: ";" | ":";
declare const posix: NodePath["posix"];
declare const win32: NodePath["win32"];
declare const _default: NodePath;
export { basename, _default as default, delimiter, dirname, extname, format, isAbsolute, join, matchesGlob, normalize, normalizeString, parse, posix, relative, resolve, sep, toNamespacedPath, win32 };

View File

@@ -0,0 +1,47 @@
import * as path from 'node:path';
import path__default from 'node:path';
/**
* Constant for path separator.
*
* Always equals to `"/"`.
*/
declare const sep = "/";
declare const normalize: typeof path__default.normalize;
declare const join: typeof path__default.join;
declare const resolve: typeof path__default.resolve;
/**
* Resolves a string path, resolving '.' and '.' segments and allowing paths above the root.
*
* @param path - The path to normalise.
* @param allowAboveRoot - Whether to allow the resulting path to be above the root directory.
* @returns the normalised path string.
*/
declare function normalizeString(path: string, allowAboveRoot: boolean): string;
declare const isAbsolute: typeof path__default.isAbsolute;
declare const toNamespacedPath: typeof path__default.toNamespacedPath;
declare const extname: typeof path__default.extname;
declare const relative: typeof path__default.relative;
declare const dirname: typeof path__default.dirname;
declare const format: typeof path__default.format;
declare const basename: typeof path__default.basename;
declare const parse: typeof path__default.parse;
/**
* The `path.matchesGlob()` method determines if `path` matches the `pattern`.
* @param path The path to glob-match against.
* @param pattern The glob to check the path against.
*/
declare const matchesGlob: (path: string, pattern: string | string[]) => boolean;
type NodePath = typeof path;
/**
* The platform-specific file delimiter.
*
* Equals to `";"` in windows and `":"` in all other platforms.
*/
declare const delimiter: ";" | ":";
declare const posix: NodePath["posix"];
declare const win32: NodePath["win32"];
declare const _default: NodePath;
export { basename, _default as default, delimiter, dirname, extname, format, isAbsolute, join, matchesGlob, normalize, normalizeString, parse, posix, relative, resolve, sep, toNamespacedPath, win32 };

View File

@@ -0,0 +1,19 @@
import { _ as _path } from './shared/pathe.M-eThtNZ.mjs';
export { c as basename, d as dirname, e as extname, f as format, i as isAbsolute, j as join, m as matchesGlob, n as normalize, a as normalizeString, p as parse, b as relative, r as resolve, s as sep, t as toNamespacedPath } from './shared/pathe.M-eThtNZ.mjs';
const delimiter = /* @__PURE__ */ (() => globalThis.process?.platform === "win32" ? ";" : ":")();
const _platforms = { posix: void 0, win32: void 0 };
const mix = (del = delimiter) => {
return new Proxy(_path, {
get(_, prop) {
if (prop === "delimiter") return del;
if (prop === "posix") return posix;
if (prop === "win32") return win32;
return _platforms[prop] || _path[prop];
}
});
};
const posix = /* @__PURE__ */ mix(":");
const win32 = /* @__PURE__ */ mix(";");
export { posix as default, delimiter, posix, win32 };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,82 @@
'use strict';
const _path = require('./shared/pathe.BSlhyZSM.cjs');
const pathSeparators = /* @__PURE__ */ new Set(["/", "\\", void 0]);
const normalizedAliasSymbol = Symbol.for("pathe:normalizedAlias");
const SLASH_RE = /[/\\]/;
function normalizeAliases(_aliases) {
if (_aliases[normalizedAliasSymbol]) {
return _aliases;
}
const aliases = Object.fromEntries(
Object.entries(_aliases).sort(([a], [b]) => _compareAliases(a, b))
);
for (const key in aliases) {
for (const alias in aliases) {
if (alias === key || key.startsWith(alias)) {
continue;
}
if (aliases[key]?.startsWith(alias) && pathSeparators.has(aliases[key][alias.length])) {
aliases[key] = aliases[alias] + aliases[key].slice(alias.length);
}
}
}
Object.defineProperty(aliases, normalizedAliasSymbol, {
value: true,
enumerable: false
});
return aliases;
}
function resolveAlias(path, aliases) {
const _path$1 = _path.normalizeWindowsPath(path);
aliases = normalizeAliases(aliases);
for (const [alias, to] of Object.entries(aliases)) {
if (!_path$1.startsWith(alias)) {
continue;
}
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
if (hasTrailingSlash(_path$1[_alias.length])) {
return _path.join(to, _path$1.slice(alias.length));
}
}
return _path$1;
}
function reverseResolveAlias(path, aliases) {
const _path$1 = _path.normalizeWindowsPath(path);
aliases = normalizeAliases(aliases);
const matches = [];
for (const [to, alias] of Object.entries(aliases)) {
if (!_path$1.startsWith(alias)) {
continue;
}
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
if (hasTrailingSlash(_path$1[_alias.length])) {
matches.push(_path.join(to, _path$1.slice(alias.length)));
}
}
return matches.sort((a, b) => b.length - a.length);
}
function filename(path) {
const base = path.split(SLASH_RE).pop();
if (!base) {
return void 0;
}
const separatorIndex = base.lastIndexOf(".");
if (separatorIndex <= 0) {
return base;
}
return base.slice(0, separatorIndex);
}
function _compareAliases(a, b) {
return b.split("/").length - a.split("/").length;
}
function hasTrailingSlash(path = "/") {
const lastChar = path[path.length - 1];
return lastChar === "/" || lastChar === "\\";
}
exports.filename = filename;
exports.normalizeAliases = normalizeAliases;
exports.resolveAlias = resolveAlias;
exports.reverseResolveAlias = reverseResolveAlias;

View File

@@ -0,0 +1,32 @@
/**
* Normalises alias mappings, ensuring that more specific aliases are resolved before less specific ones.
* This function also ensures that aliases do not resolve to themselves cyclically.
*
* @param _aliases - A set of alias mappings where each key is an alias and its value is the actual path it points to.
* @returns a set of normalised alias mappings.
*/
declare function normalizeAliases(_aliases: Record<string, string>): Record<string, string>;
/**
* Resolves a path string to its alias if applicable, otherwise returns the original path.
* This function normalises the path, resolves the alias and then joins it to the alias target if necessary.
*
* @param path - The path string to resolve.
* @param aliases - A set of alias mappings to use for resolution.
* @returns the resolved path as a string.
*/
declare function resolveAlias(path: string, aliases: Record<string, string>): string;
/**
* Resolves a path string to its possible alias.
*
* Returns an array of possible alias resolutions (could be empty), sorted by specificity (longest first).
*/
declare function reverseResolveAlias(path: string, aliases: Record<string, string>): string[];
/**
* Extracts the filename from a given path, excluding any directory paths and the file extension.
*
* @param path - The full path of the file from which to extract the filename.
* @returns the filename without the extension, or `undefined` if the filename cannot be extracted.
*/
declare function filename(path: string): string | undefined;
export { filename, normalizeAliases, resolveAlias, reverseResolveAlias };

View File

@@ -0,0 +1,32 @@
/**
* Normalises alias mappings, ensuring that more specific aliases are resolved before less specific ones.
* This function also ensures that aliases do not resolve to themselves cyclically.
*
* @param _aliases - A set of alias mappings where each key is an alias and its value is the actual path it points to.
* @returns a set of normalised alias mappings.
*/
declare function normalizeAliases(_aliases: Record<string, string>): Record<string, string>;
/**
* Resolves a path string to its alias if applicable, otherwise returns the original path.
* This function normalises the path, resolves the alias and then joins it to the alias target if necessary.
*
* @param path - The path string to resolve.
* @param aliases - A set of alias mappings to use for resolution.
* @returns the resolved path as a string.
*/
declare function resolveAlias(path: string, aliases: Record<string, string>): string;
/**
* Resolves a path string to its possible alias.
*
* Returns an array of possible alias resolutions (could be empty), sorted by specificity (longest first).
*/
declare function reverseResolveAlias(path: string, aliases: Record<string, string>): string[];
/**
* Extracts the filename from a given path, excluding any directory paths and the file extension.
*
* @param path - The full path of the file from which to extract the filename.
* @returns the filename without the extension, or `undefined` if the filename cannot be extracted.
*/
declare function filename(path: string): string | undefined;
export { filename, normalizeAliases, resolveAlias, reverseResolveAlias };

View File

@@ -0,0 +1,32 @@
/**
* Normalises alias mappings, ensuring that more specific aliases are resolved before less specific ones.
* This function also ensures that aliases do not resolve to themselves cyclically.
*
* @param _aliases - A set of alias mappings where each key is an alias and its value is the actual path it points to.
* @returns a set of normalised alias mappings.
*/
declare function normalizeAliases(_aliases: Record<string, string>): Record<string, string>;
/**
* Resolves a path string to its alias if applicable, otherwise returns the original path.
* This function normalises the path, resolves the alias and then joins it to the alias target if necessary.
*
* @param path - The path string to resolve.
* @param aliases - A set of alias mappings to use for resolution.
* @returns the resolved path as a string.
*/
declare function resolveAlias(path: string, aliases: Record<string, string>): string;
/**
* Resolves a path string to its possible alias.
*
* Returns an array of possible alias resolutions (could be empty), sorted by specificity (longest first).
*/
declare function reverseResolveAlias(path: string, aliases: Record<string, string>): string[];
/**
* Extracts the filename from a given path, excluding any directory paths and the file extension.
*
* @param path - The full path of the file from which to extract the filename.
* @returns the filename without the extension, or `undefined` if the filename cannot be extracted.
*/
declare function filename(path: string): string | undefined;
export { filename, normalizeAliases, resolveAlias, reverseResolveAlias };

View File

@@ -0,0 +1,77 @@
import { g as normalizeWindowsPath, j as join } from './shared/pathe.M-eThtNZ.mjs';
const pathSeparators = /* @__PURE__ */ new Set(["/", "\\", void 0]);
const normalizedAliasSymbol = Symbol.for("pathe:normalizedAlias");
const SLASH_RE = /[/\\]/;
function normalizeAliases(_aliases) {
if (_aliases[normalizedAliasSymbol]) {
return _aliases;
}
const aliases = Object.fromEntries(
Object.entries(_aliases).sort(([a], [b]) => _compareAliases(a, b))
);
for (const key in aliases) {
for (const alias in aliases) {
if (alias === key || key.startsWith(alias)) {
continue;
}
if (aliases[key]?.startsWith(alias) && pathSeparators.has(aliases[key][alias.length])) {
aliases[key] = aliases[alias] + aliases[key].slice(alias.length);
}
}
}
Object.defineProperty(aliases, normalizedAliasSymbol, {
value: true,
enumerable: false
});
return aliases;
}
function resolveAlias(path, aliases) {
const _path = normalizeWindowsPath(path);
aliases = normalizeAliases(aliases);
for (const [alias, to] of Object.entries(aliases)) {
if (!_path.startsWith(alias)) {
continue;
}
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
if (hasTrailingSlash(_path[_alias.length])) {
return join(to, _path.slice(alias.length));
}
}
return _path;
}
function reverseResolveAlias(path, aliases) {
const _path = normalizeWindowsPath(path);
aliases = normalizeAliases(aliases);
const matches = [];
for (const [to, alias] of Object.entries(aliases)) {
if (!_path.startsWith(alias)) {
continue;
}
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
if (hasTrailingSlash(_path[_alias.length])) {
matches.push(join(to, _path.slice(alias.length)));
}
}
return matches.sort((a, b) => b.length - a.length);
}
function filename(path) {
const base = path.split(SLASH_RE).pop();
if (!base) {
return void 0;
}
const separatorIndex = base.lastIndexOf(".");
if (separatorIndex <= 0) {
return base;
}
return base.slice(0, separatorIndex);
}
function _compareAliases(a, b) {
return b.split("/").length - a.split("/").length;
}
function hasTrailingSlash(path = "/") {
const lastChar = path[path.length - 1];
return lastChar === "/" || lastChar === "\\";
}
export { filename, normalizeAliases, resolveAlias, reverseResolveAlias };

View File

@@ -0,0 +1,61 @@
{
"name": "pathe",
"version": "2.0.3",
"description": "Universal filesystem path utils",
"repository": "unjs/pathe",
"license": "MIT",
"sideEffects": false,
"type": "module",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
},
"./utils": {
"import": {
"types": "./dist/utils.d.mts",
"default": "./dist/utils.mjs"
},
"require": {
"types": "./dist/utils.d.cts",
"default": "./dist/utils.cjs"
}
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist",
"utils.d.ts"
],
"devDependencies": {
"@types/node": "^22.13.1",
"@vitest/coverage-v8": "^3.0.5",
"changelogen": "^0.5.7",
"esbuild": "^0.25.0",
"eslint": "^9.20.1",
"eslint-config-unjs": "^0.4.2",
"jiti": "^2.4.2",
"prettier": "^3.5.0",
"typescript": "^5.7.3",
"unbuild": "^3.3.1",
"vitest": "^3.0.5",
"zeptomatch": "^2.0.0"
},
"scripts": {
"build": "unbuild",
"dev": "vitest",
"lint": "eslint . && prettier -c src test",
"lint:fix": "eslint . --fix && prettier -w src test",
"release": "pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
"test": "pnpm lint && vitest run --coverage",
"test:types": "tsc --noEmit"
}
}

View File

@@ -0,0 +1 @@
export * from "./dist/utils";

115
node_modules/@nuxtjs/tailwindcss/package.json generated vendored Normal file
View File

@@ -0,0 +1,115 @@
{
"name": "@nuxtjs/tailwindcss",
"version": "6.14.0",
"description": "Tailwind CSS module for Nuxt",
"repository": "nuxt-modules/tailwindcss",
"license": "MIT",
"type": "module",
"configKey": "tailwindcss",
"compatibility": {
"nuxt": "^2.9.0 || >=3.0.0-rc.1"
},
"exports": {
".": {
"types": "./dist/module.d.ts",
"require": "./dist/module.cjs",
"import": "./dist/module.mjs"
},
"./config": {
"types": "./dist/config.d.ts",
"require": "./dist/config.cjs",
"import": "./dist/config.mjs"
},
"./merger": {
"types": "./dist/merger.d.ts",
"require": "./dist/merger.cjs",
"import": "./dist/merger.mjs"
},
"./config-ctx": {
"types": "./dist/config-ctx.d.ts",
"require": "./dist/config-ctx.cjs",
"import": "./dist/config-ctx.mjs"
}
},
"main": "./dist/module.cjs",
"types": "./dist/types.d.ts",
"files": [
"dist"
],
"build": {
"entries": [
"./src/config",
"./src/merger",
"./src/config-ctx"
],
"externals": [
"@tailwindcss/vite"
],
"rollup": {
"emitCJS": true
}
},
"dependencies": {
"@nuxt/kit": "^3.16.0",
"autoprefixer": "^10.4.20",
"c12": "^3.0.2",
"consola": "^3.4.0",
"defu": "^6.1.4",
"h3": "^1.15.1",
"klona": "^2.0.6",
"ohash": "^2.0.11",
"pathe": "^2.0.3",
"pkg-types": "^2.1.0",
"postcss": "^8.5.3",
"postcss-nesting": "^13.0.1",
"tailwind-config-viewer": "^2.0.4",
"tailwindcss": "~3.4.17",
"ufo": "^1.5.4",
"unctx": "^2.4.1"
},
"devDependencies": {
"@fontsource/inter": "^5.2.5",
"@nuxt/content": "^2.13.4",
"@nuxt/devtools": "^2.2.1",
"@nuxt/eslint-config": "^0.7.6",
"@nuxt/module-builder": "^0.8.4",
"@nuxt/test-utils": "^3.17.1",
"@tailwindcss/typography": "^0.5.16",
"changelogen": "^0.5.7",
"destr": "^2.0.3",
"eslint": "^9.21.0",
"happy-dom": "^16.8.1",
"nuxt": "^3.16.0",
"typescript": "5.6.3",
"vitest": "^3.0.8",
"vue-tsc": "^2.2.8"
},
"resolutions": {
"@nuxtjs/tailwindcss": "link:.",
"@nuxt/ui": "npm:@nuxt/ui-edge",
"unicorn-magic": "0.2.0"
},
"stackblitz": {
"startCommand": "pnpm dev:prepare && pnpm dev"
},
"scripts": {
"play": "pnpm dev",
"dev": "nuxi dev playground",
"dev:build": "nuxi build playground",
"dev:generate": "nuxi generate playground",
"dev:preview": "nuxi preview playground",
"dev:nuxt2": "nuxi dev nuxt2-playground",
"dev:prepare": "nuxt-module-build prepare && pnpm build:stub",
"build": "nuxt-module-build build",
"build:stub": "pnpm build --stub",
"release": "pnpm lint && pnpm test && pnpm prepack && pnpm changelogen --release --push && pnpm publish",
"docs:build": "nuxi generate docs",
"docs:preview": "nuxi preview docs",
"docs:dev": "nuxi dev docs",
"lint": "eslint .",
"lint:fix": "pnpm lint --fix",
"test": "vitest run",
"test:watch": "vitest watch",
"test:types": "pnpm dev:prepare && tsc --noEmit && nuxi typecheck playground"
}
}