'use strict'; const fs = require('fs'); const path = require('upath'); const chokidar = require('chokidar'); const consola = require('consola'); const chalk = require('chalk'); const semver = require('semver'); const globby = require('globby'); const scule = require('scule'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); const path__default = /*#__PURE__*/_interopDefaultLegacy(path); const chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar); const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola); const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk); const semver__default = /*#__PURE__*/_interopDefaultLegacy(semver); const globby__default = /*#__PURE__*/_interopDefaultLegacy(globby); function requireNuxtVersion(currentVersion, requiredVersion) { const pkgName = require("../package.json").name; if (!currentVersion || !requireNuxtVersion) { return; } const _currentVersion = semver__default['default'].coerce(currentVersion); const _requiredVersion = semver__default['default'].coerce(requiredVersion); if (semver__default['default'].lt(_currentVersion, _requiredVersion)) { throw new Error(` ${chalk__default['default'].cyan(pkgName)} is not compatible with your current Nuxt version : ${chalk__default['default'].yellow("v" + currentVersion)} Required: ${chalk__default['default'].green("v" + requiredVersion)} or ${chalk__default['default'].cyan("higher")} `); } } function sortDirsByPathLength({ path: pathA }, { path: pathB }) { return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length; } function hyphenate(str) { return str.replace(/\B([A-Z])/g, "-$1").toLowerCase(); } async function scanComponents(dirs, srcDir) { const components = []; const filePaths = new Set(); const scannedPaths = []; for (const { path: path$1, pattern, ignore = [], prefix, extendComponent, pathPrefix, level, prefetch = false, preload = false, isAsync: dirIsAsync } of dirs.sort(sortDirsByPathLength)) { const resolvedNames = new Map(); for (const _file of await globby__default['default'](pattern, { cwd: path$1, ignore })) { const filePath = path.join(path$1, _file); if (scannedPaths.find((d) => filePath.startsWith(d))) { continue; } if (filePaths.has(filePath)) { continue; } filePaths.add(filePath); const prefixParts = [].concat(prefix ? scule.splitByCase(prefix) : [], pathPrefix !== false ? scule.splitByCase(path.relative(path$1, path.dirname(filePath))) : []); let fileName = path.basename(filePath, path.extname(filePath)); if (fileName.toLowerCase() === "index") { fileName = pathPrefix === false ? path.basename(path.dirname(filePath)) : ""; } const isAsync = (fileName.endsWith(".async") ? true : dirIsAsync) || null; fileName = fileName.replace(/\.async$/, ""); const fileNameParts = scule.splitByCase(fileName); const componentNameParts = []; while (prefixParts.length && (prefixParts[0] || "").toLowerCase() !== (fileNameParts[0] || "").toLowerCase()) { componentNameParts.push(prefixParts.shift()); } const componentName = scule.pascalCase(componentNameParts).replace(/^\d+/, "") + scule.pascalCase(fileNameParts).replace(/^\d+/, ""); if (resolvedNames.has(componentName)) { console.warn(`Two component files resolving to the same name \`${componentName}\`: - ${filePath} - ${resolvedNames.get(componentName)}`); continue; } resolvedNames.set(componentName, filePath); const pascalName = scule.pascalCase(componentName); const kebabName = hyphenate(componentName); const shortPath = path.relative(srcDir, filePath); const chunkName = "components/" + kebabName; let component = { filePath, pascalName, kebabName, chunkName, shortPath, isAsync, import: "", asyncImport: "", export: "default", global: Boolean(global), level: Number(level), prefetch: Boolean(prefetch), preload: Boolean(preload) }; if (typeof extendComponent === "function") { component = await extendComponent(component) || component; } component.import = component.import || `require('${component.filePath}').${component.export}`; component.asyncImport = component.asyncImport || `function () { return import('${component.filePath}' /* webpackChunkName: "${component.chunkName}" */).then(function(m) { return m['${component.export}'] || m }) }`; const definedComponent = components.find((c) => c.pascalName === component.pascalName); if (definedComponent && component.level < definedComponent.level) { Object.assign(definedComponent, component); } else if (!definedComponent) { components.push(component); } } scannedPaths.push(path$1); } return components; } const isPureObjectOrString = (val) => !Array.isArray(val) && typeof val === "object" || typeof val === "string"; const getDir = (p) => fs__default['default'].statSync(p).isDirectory() ? p : path__default['default'].dirname(p); const componentsModule = function() { var _a; const { nuxt } = this; const { components } = nuxt.options; if (!components) { return; } requireNuxtVersion((_a = nuxt == null ? void 0 : nuxt.constructor) == null ? void 0 : _a.version, "2.10"); const options = { dirs: ["~/components"], loader: !nuxt.options.dev, ...Array.isArray(components) ? { dirs: components } : components }; nuxt.hook("build:before", async (builder) => { const nuxtIgnorePatterns = builder.ignore.ignore ? builder.ignore.ignore._rules.map((rule) => rule.pattern) : []; await nuxt.callHook("components:dirs", options.dirs); const resolvePath = (dir) => nuxt.resolver.resolvePath(dir); try { const globalDir = getDir(resolvePath("~/components/global")); if (!options.dirs.find((dir) => resolvePath(dir) === globalDir)) { options.dirs.push({ path: globalDir }); } } catch (err) { nuxt.options.watch.push(path__default['default'].resolve(nuxt.options.srcDir, "components", "global")); } const componentDirs = options.dirs.filter(isPureObjectOrString).map((dir) => { const dirOptions = typeof dir === "object" ? dir : { path: dir }; let dirPath = dirOptions.path; try { dirPath = getDir(nuxt.resolver.resolvePath(dirOptions.path)); } catch (err) { } const transpile = typeof dirOptions.transpile === "boolean" ? dirOptions.transpile : "auto"; dirOptions.level = Number(dirOptions.level || 0); const enabled = fs__default['default'].existsSync(dirPath); if (!enabled && dirOptions.path !== "~/components") { console.warn("Components directory not found: `" + dirPath + "`"); } const extensions = dirOptions.extensions || builder.supportedExtensions; return { ...dirOptions, enabled, path: dirPath, extensions, pattern: dirOptions.pattern || `**/*.{${extensions.join(",")},}`, isAsync: dirOptions.isAsync, ignore: [ "**/*.stories.{js,ts,jsx,tsx}", "**/*{M,.m,-m}ixin.{js,ts,jsx,tsx}", "**/*.d.ts", ...nuxtIgnorePatterns, ...dirOptions.ignore || [] ], transpile: transpile === "auto" ? dirPath.includes("node_modules") : transpile }; }).filter((d) => d.enabled); nuxt.options.build.transpile.push(...componentDirs.filter((dir) => dir.transpile).map((dir) => dir.path)); let components2 = await scanComponents(componentDirs, nuxt.options.srcDir); await nuxt.callHook("components:extend", components2); if (options.loader) { consola__default['default'].info("Using components loader to optimize imports"); this.extendBuild((config) => { var _a2; const vueRule = (_a2 = config.module) == null ? void 0 : _a2.rules.find((rule) => { var _a3; return (_a3 = rule.test) == null ? void 0 : _a3.toString().includes(".vue"); }); if (!vueRule) { throw new Error("Cannot find vue loader"); } if (!vueRule.use) { vueRule.use = [{ loader: vueRule.loader.toString(), options: vueRule.options }]; delete vueRule.loader; delete vueRule.options; } if (!Array.isArray(vueRule.use)) { vueRule.use = [vueRule.use]; } vueRule.use.unshift({ loader: require.resolve("./loader"), options: { getComponents: () => components2 } }); }); nuxt.hook("webpack:config", (configs) => { for (const config of configs.filter((c) => ["client", "modern", "server"].includes(c.name))) { config.entry.app.unshift(path__default['default'].resolve(__dirname, "../lib/installComponents.js")); } }); } if (nuxt.options.dev && componentDirs.some((dir) => dir.watch !== false)) { const watcher = chokidar__default['default'].watch(componentDirs.filter((dir) => dir.watch !== false).map((dir) => dir.path), nuxt.options.watchers.chokidar); watcher.on("all", async (eventName) => { if (!["add", "unlink"].includes(eventName)) { return; } components2 = await scanComponents(componentDirs, nuxt.options.srcDir); await nuxt.callHook("components:extend", components2); await builder.generateRoutesAndFiles(); }); nuxt.hook("close", () => { watcher.close(); }); } const getComponents = () => components2; const templates = [ "components/index.js", "components/plugin.js", "components/readme_md", "vetur/tags.json" ]; for (const t of templates) { this[t.includes("plugin") ? "addPlugin" : "addTemplate"]({ src: path__default['default'].resolve(__dirname, "../templates", t), fileName: t.replace("_", "."), options: { getComponents } }); } const componentsListFile = path__default['default'].resolve(nuxt.options.buildDir, "components/readme.md"); consola__default['default'].info("Discovered Components:", path__default['default'].relative(process.cwd(), componentsListFile)); }); }; componentsModule.meta = { name: "@nuxt/components" }; module.exports = componentsModule;