'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;
|