jccp_a/vuepress/node_modules/@vuepress/cli/dist/index.js
hellcat ac91e1fbe4 1
2025-11-12 17:57:30 +08:00

674 lines
21 KiB
JavaScript

// src/commands/build.ts
import process6 from "process";
import { createBuildApp } from "@vuepress/core";
import { debug as debug2, formatMs, fs as fs5, logger as logger3, withSpinner } from "@vuepress/utils";
// src/config/loadUserConfig.ts
import process from "process";
import { pathToFileURL } from "url";
import { fs, hash, importFileDefault, path } from "@vuepress/utils";
import { build } from "esbuild";
var loadUserConfig = async (userConfigPath) => {
if (!userConfigPath) {
return {
userConfig: {},
userConfigDependencies: []
};
}
const dirnameVarName = "__vite_injected_original_dirname";
const filenameVarName = "__vite_injected_original_filename";
const importMetaUrlVarName = "__vite_injected_original_import_meta_url";
const result = await build({
absWorkingDir: process.cwd(),
entryPoints: [userConfigPath],
write: false,
target: [`node${process.versions.node}`],
platform: "node",
bundle: true,
format: "esm",
mainFields: ["main"],
sourcemap: "inline",
metafile: true,
define: {
"__dirname": dirnameVarName,
"__filename": filenameVarName,
"import.meta.url": importMetaUrlVarName,
"import.meta.dirname": dirnameVarName,
"import.meta.filename": filenameVarName
},
plugins: [
{
name: "externalize-deps",
setup(pluginBuild) {
pluginBuild.onResolve({ filter: /.*/ }, ({ path: id }) => {
if (!id.startsWith(".") && !path.isAbsolute(id)) {
return {
external: true
};
}
return null;
});
}
},
{
name: "inject-file-scope-variables",
setup(pluginBuild) {
pluginBuild.onLoad({ filter: /\.[cm]?[jt]s$/ }, async (args) => {
const contents = await fs.readFile(args.path, "utf-8");
const injectValues = `const ${dirnameVarName} = ${JSON.stringify(
path.dirname(args.path)
)};const ${filenameVarName} = ${JSON.stringify(args.path)};const ${importMetaUrlVarName} = ${JSON.stringify(
pathToFileURL(args.path).href
)};`;
return {
loader: args.path.endsWith("ts") ? "ts" : "js",
contents: injectValues + contents
};
});
}
}
]
});
const { text } = result.outputFiles[0];
const tempFilePath = `${userConfigPath}.${hash(text)}.mjs`;
let userConfig;
try {
await fs.writeFile(tempFilePath, text);
userConfig = await importFileDefault(tempFilePath);
} finally {
await fs.rm(tempFilePath);
}
return {
userConfig,
userConfigDependencies: Object.keys(result.metafile.inputs)
};
};
// src/config/resolveAppConfig.ts
import { ensureEndingSlash, ensureLeadingSlash } from "@vuepress/shared";
import { colors, isChildPath, logger } from "@vuepress/utils";
var resolveAppConfig = ({
defaultAppConfig,
cliAppConfig,
userConfig
}) => {
const appConfig = {
// allow setting default app config via `cli()`
...defaultAppConfig,
// user config from config file
...userConfig,
// allow cli options to override config file
...cliAppConfig
};
if (appConfig.source === void 0) {
logger.error(`The ${colors.magenta("source")} option is missing.`);
return null;
}
if (appConfig.bundler === void 0 || appConfig.theme === void 0) {
logger.error(
`The ${colors.magenta("bundler")} or ${colors.magenta("theme")} option is missing. For more details: ${colors.green("https://vuepress.vuejs.org/guide/troubleshooting.html#the-bundler-theme-option-is-missing")}`
);
return null;
}
if (appConfig.base && !(appConfig.base.startsWith("/") && appConfig.base.endsWith("/"))) {
const rawBase = appConfig.base;
appConfig.base = ensureLeadingSlash(ensureEndingSlash(rawBase));
logger.warn(
`${colors.magenta("base")} should start and end with a slash (/), so it has been normalized from ${colors.magenta(rawBase)} to ${colors.magenta(appConfig.base)}`
);
}
if (appConfig.dest && isChildPath(appConfig.source, appConfig.dest)) {
logger.warn(
`${colors.magenta("dest")} directory would be emptied during build, so we fallback it to the default directory for the safety of your source files`
);
delete appConfig.dest;
}
return appConfig;
};
// src/config/resolveCliAppConfig.ts
import process2 from "process";
import { path as path2 } from "@vuepress/utils";
var OPTIONS_COMMON = ["debug", "open", "port", "host"];
var OPTIONS_DIRECTORY = ["cache", "dest", "temp"];
var resolveCliAppConfig = (sourceDir, cliOptions, cwd = process2.cwd()) => {
const source = path2.resolve(cwd, sourceDir);
const appConfig = {
source
};
OPTIONS_COMMON.forEach((name) => {
if (cliOptions[name] !== void 0) {
appConfig[name] = cliOptions[name];
}
});
OPTIONS_DIRECTORY.forEach((name) => {
if (cliOptions[name] !== void 0) {
appConfig[name] = path2.resolve(cwd, cliOptions[name]);
}
});
return appConfig;
};
// src/config/resolveUserConfig.ts
import { debug } from "@vuepress/utils";
// src/config/resolveUserConfigConventionalPath.ts
import process3 from "process";
import { fs as fs2, path as path3 } from "@vuepress/utils";
var resolveUserConfigConventionalPath = (source, cwd = process3.cwd()) => [
path3.resolve(cwd, "vuepress.config.ts"),
path3.resolve(cwd, "vuepress.config.js"),
path3.resolve(cwd, "vuepress.config.mjs"),
path3.resolve(source, ".vuepress/config.ts"),
path3.resolve(source, ".vuepress/config.js"),
path3.resolve(source, ".vuepress/config.mjs")
].find((item) => fs2.pathExistsSync(item));
// src/config/resolveUserConfigPath.ts
import process4 from "process";
import { colors as colors2, fs as fs3, logger as logger2, path as path4 } from "@vuepress/utils";
var resolveUserConfigPath = (config, cwd = process4.cwd()) => {
const configPath = path4.resolve(cwd, config);
if (!fs3.pathExistsSync(configPath)) {
throw logger2.createError(
`config file does not exist: ${colors2.magenta(config)}`
);
}
return configPath;
};
// src/config/resolveUserConfig.ts
var log = debug("vuepress:cli/resolveUserConfig");
var resolveUserConfig = async ({
cliOptionsConfig,
cliAppConfigSource
}) => {
const userConfigPath = cliOptionsConfig ? resolveUserConfigPath(cliOptionsConfig) : resolveUserConfigConventionalPath(cliAppConfigSource);
log(`userConfigPath:`, userConfigPath);
const { userConfig, userConfigDependencies } = await loadUserConfig(userConfigPath);
return {
userConfig,
userConfigDependencies,
userConfigPath
};
};
// src/config/transformUserConfigToPlugin.ts
import process5 from "process";
import { fs as fs4, path as path5 } from "@vuepress/utils";
var transformUserConfigToPlugin = (userConfig, source, cwd = process5.cwd()) => {
const userConfigPlugin = {
name: "user-config",
...userConfig
};
userConfigPlugin.clientConfigFile ??= [
path5.resolve(cwd, "vuepress.client.ts"),
path5.resolve(cwd, "vuepress.client.js"),
path5.resolve(cwd, "vuepress.client.mjs"),
path5.resolve(source, ".vuepress/client.ts"),
path5.resolve(source, ".vuepress/client.js"),
path5.resolve(source, ".vuepress/client.mjs")
].find((item) => fs4.pathExistsSync(item));
return userConfigPlugin;
};
// src/config/resolveConfig.ts
var resolveConfig = async ({
sourceDir,
cliOptions,
defaultAppConfig
}) => {
const cliAppConfig = resolveCliAppConfig(sourceDir, cliOptions);
const { userConfig, userConfigDependencies, userConfigPath } = await resolveUserConfig({
cliOptionsConfig: cliOptions.config,
cliAppConfigSource: cliAppConfig.source
});
const userConfigPlugin = transformUserConfigToPlugin(
userConfig,
cliAppConfig.source
);
const appConfig = resolveAppConfig({
defaultAppConfig,
cliAppConfig,
userConfig
});
return {
appConfig,
userConfigDependencies,
userConfigPath,
userConfigPlugin
};
};
// src/commands/build.ts
var log2 = debug2("vuepress:cli/build");
var build2 = async ({
defaultAppConfig,
sourceDir = ".",
cliOptions = {}
}) => {
const start = Date.now();
log2(`cliOptions:`, cliOptions);
process6.env.NODE_ENV ??= "production";
const { appConfig, userConfigPlugin } = await resolveConfig({
defaultAppConfig,
sourceDir,
cliOptions
});
if (appConfig === null) {
throw logger3.createError("Failed to resolve config");
}
const app = createBuildApp(appConfig);
app.use(userConfigPlugin);
if (cliOptions.cleanTemp === true) {
await withSpinner("Cleaning temp")(async () => {
await fs5.remove(app.dir.temp());
});
}
if (cliOptions.cleanCache === true) {
await withSpinner("Cleaning cache")(async () => {
await fs5.remove(app.dir.cache());
});
}
await fs5.emptyDir(app.dir.dest());
await withSpinner("Initializing and preparing data")(async () => {
await app.init();
await app.prepare();
});
await app.build();
await app.pluginApi.hooks.onGenerated.process(app);
logger3.success(`VuePress build completed in ${formatMs(Date.now() - start)}!`);
};
// src/commands/dev/dev.ts
import process8 from "process";
import { createDevApp } from "@vuepress/core";
import { debug as debug3, fs as fs6, logger as logger6, withSpinner as withSpinner2 } from "@vuepress/utils";
// src/commands/dev/watchPageFiles.ts
import { colors as colors3, logger as logger4, path as path6, picomatch } from "@vuepress/utils";
import chokidar from "chokidar";
// src/commands/dev/handlePageAdd.ts
import {
createPage,
preparePageChunk,
preparePageComponent,
prepareRoutes
} from "@vuepress/core";
var handlePageAdd = async (app, filePath) => {
const pageIndex = app.pages.findIndex((page2) => page2.filePath === filePath);
if (pageIndex !== -1) {
return null;
}
const page = await createPage(app, {
filePath
});
app.pages.push(page);
await preparePageComponent(app, page);
await preparePageChunk(app, page);
await prepareRoutes(app);
return page;
};
// src/commands/dev/handlePageChange.ts
import {
createPage as createPage2,
preparePageChunk as preparePageChunk2,
preparePageComponent as preparePageComponent2,
prepareRoutes as prepareRoutes2
} from "@vuepress/core";
var handlePageChange = async (app, filePath) => {
const pageIndex = app.pages.findIndex((page) => page.filePath === filePath);
if (pageIndex === -1) {
return null;
}
const pageOld = app.pages[pageIndex];
const pageNew = await createPage2(app, {
filePath
});
app.pages.splice(pageIndex, 1, pageNew);
await preparePageComponent2(app, pageNew);
await preparePageChunk2(app, pageNew);
const isPathChanged = pageOld.path !== pageNew.path;
const isRouteMetaChanged = JSON.stringify(pageOld.routeMeta) !== JSON.stringify(pageNew.routeMeta);
if (isPathChanged || isRouteMetaChanged) {
await prepareRoutes2(app);
}
return [pageOld, pageNew];
};
// src/commands/dev/handlePageUnlink.ts
import { prepareRoutes as prepareRoutes3 } from "@vuepress/core";
var handlePageUnlink = async (app, filePath) => {
const pageIndex = app.pages.findIndex((page2) => page2.filePath === filePath);
if (pageIndex === -1) {
return null;
}
const page = app.pages[pageIndex];
app.pages.splice(pageIndex, 1);
await prepareRoutes3(app);
return page;
};
// src/commands/dev/pageDepsHelper.ts
var createPageDepsHelper = () => {
const store = /* @__PURE__ */ new Map();
return {
add: ({ deps, filePathRelative }) => {
const depsAdded = [];
if (filePathRelative) {
deps.forEach((item) => {
if (!store.has(item)) {
store.set(item, /* @__PURE__ */ new Set());
depsAdded.push(item);
}
store.get(item)?.add(filePathRelative);
});
}
return depsAdded;
},
remove: ({ deps, filePathRelative }) => {
const depsRemoved = [];
if (filePathRelative) {
deps.forEach((item) => {
const pagePathsSet = store.get(item);
pagePathsSet?.delete(filePathRelative);
if (pagePathsSet?.size === 0) {
store.delete(item);
depsRemoved.push(item);
}
});
}
return depsRemoved;
},
get: (dep) => {
const pagePathsSet = store.get(dep);
return pagePathsSet ? [...pagePathsSet] : [];
}
};
};
// src/commands/dev/watchPageFiles.ts
var watchPageFiles = (app) => {
const depsWatcher = chokidar.watch([], {
ignoreInitial: true
});
const depsHelper = createPageDepsHelper();
const addDeps = (page) => {
const depsToAdd = depsHelper.add(page);
depsWatcher.add(depsToAdd);
};
const removeDeps = (page) => {
const depsToRemove = depsHelper.remove(page);
depsWatcher.unwatch(depsToRemove);
};
const depsListener = async (dep) => {
const pagePaths = depsHelper.get(dep);
for (const filePathRelative of pagePaths) {
logger4.info(
`dependency of page ${colors3.magenta(filePathRelative)} is modified`
);
await handlePageChange(app, app.dir.source(filePathRelative));
}
};
depsWatcher.on("add", depsListener);
depsWatcher.on("change", depsListener);
depsWatcher.on("unlink", depsListener);
app.pages.forEach((page) => {
addDeps(page);
});
const pagePatterns = [];
const ignorePatterns = [];
for (const pattern of app.options.pagePatterns) {
if (pattern.startsWith("!")) {
ignorePatterns.push(pattern.slice(1));
} else {
pagePatterns.push(pattern);
}
}
const sourceDir = app.dir.source();
const tempDir = app.dir.temp();
const cacheDir = app.dir.cache();
const isPageMatch = picomatch(pagePatterns, {
ignore: ignorePatterns,
cwd: sourceDir
});
const pagesWatcher = chokidar.watch(".", {
cwd: sourceDir,
ignored: (filepath, stats) => {
if (filepath.includes("node_modules")) {
return true;
}
if (filepath.startsWith(tempDir) || filepath.startsWith(cacheDir)) {
return true;
}
return !!stats?.isFile() && !isPageMatch(path6.relative(sourceDir, filepath));
},
ignoreInitial: true
});
pagesWatcher.on("add", async (filePathRelative) => {
logger4.info(`page ${colors3.magenta(filePathRelative)} is created`);
const page = await handlePageAdd(app, app.dir.source(filePathRelative));
if (page === null) return;
addDeps(page);
});
pagesWatcher.on("change", async (filePathRelative) => {
logger4.info(`page ${colors3.magenta(filePathRelative)} is modified`);
const result = await handlePageChange(app, app.dir.source(filePathRelative));
if (result === null) return;
const [pageOld, pageNew] = result;
removeDeps(pageOld);
addDeps(pageNew);
});
pagesWatcher.on("unlink", async (filePathRelative) => {
logger4.info(`page ${colors3.magenta(filePathRelative)} is removed`);
const page = await handlePageUnlink(app, app.dir.source(filePathRelative));
if (page === null) return;
removeDeps(page);
});
return [pagesWatcher, depsWatcher];
};
// src/commands/dev/watchUserConfigFile.ts
import process7 from "process";
import { colors as colors4, logger as logger5 } from "@vuepress/utils";
import chokidar2 from "chokidar";
var watchUserConfigFile = ({
userConfigPath,
userConfigDependencies,
restart
}) => {
const cwd = process7.cwd();
const configWatcher = chokidar2.watch(userConfigPath, {
cwd,
ignoreInitial: true
});
configWatcher.on("change", (configFile) => {
logger5.info(`config ${colors4.magenta(configFile)} is modified`);
void restart();
});
const depsWatcher = chokidar2.watch(userConfigDependencies, {
cwd,
ignoreInitial: true
});
depsWatcher.on("change", (depFile) => {
logger5.info(`config dependency ${colors4.magenta(depFile)} is modified`);
void restart();
});
return [configWatcher, depsWatcher];
};
// src/commands/dev/dev.ts
var log3 = debug3("vuepress:cli/dev");
var dev = async ({
defaultAppConfig,
sourceDir = ".",
cliOptions = {}
}) => {
log3(`cliOptions:`, cliOptions);
process8.env.NODE_ENV ??= "development";
const {
appConfig,
userConfigDependencies,
userConfigPath,
userConfigPlugin
} = await resolveConfig({
defaultAppConfig,
sourceDir,
cliOptions
});
if (appConfig === null) {
throw logger6.createError("Failed to resolve config");
}
const app = createDevApp(appConfig);
app.use(userConfigPlugin);
if (cliOptions.cleanTemp === true) {
await withSpinner2("Cleaning temp")(async () => fs6.remove(app.dir.temp()));
}
if (cliOptions.cleanCache === true) {
await withSpinner2("Cleaning cache")(async () => fs6.remove(app.dir.cache()));
}
await withSpinner2("Initializing and preparing data")(async () => {
await app.init();
await app.prepare();
});
const close = await app.dev();
if (cliOptions.watch === false) {
return;
}
const watchers = [];
const restart = async () => {
await Promise.all([
// close all watchers
...watchers.map(async (item) => item.close()),
// close current dev server
close()
]);
await dev({
defaultAppConfig,
sourceDir,
cliOptions: {
...cliOptions,
// do not clean cache and temp on restart
cleanCache: false,
cleanTemp: false
}
});
logger6.tip(`dev server has restarted, please refresh your browser`);
};
watchers.push(...watchPageFiles(app));
if (userConfigPath) {
watchers.push(
...watchUserConfigFile({
userConfigPath,
userConfigDependencies,
restart
})
);
}
await app.pluginApi.hooks.onWatched.process(app, watchers, restart);
};
// src/commands/info.ts
import { logger as logger7, ora } from "@vuepress/utils";
import envinfo from "envinfo";
var info = async () => {
const spinner = ora();
spinner.start("Collecting Environment Info");
const result = await envinfo.run(
{
System: ["OS", "CPU", "Memory", "Shell"],
Binaries: ["bun", "Node", "npm", "pnpm", "Yarn"],
Utilities: ["Git"],
Browsers: ["Chrome", "Edge", "Firefox", "Safari"],
npmPackages: [
"@vuepress/bundler-vite",
"@vuepress/bundler-webpack",
"@vuepress/cli",
"@vuepress/client",
"@vuepress/core",
"@vuepress/markdown",
"@vuepress/shared",
"@vuepress/utils",
"vuepress",
"vue",
"vue-router"
]
},
{
showNotFound: true,
duplicates: true,
fullTree: true
}
);
spinner.stop();
logger7.info(result);
};
// src/cli.ts
import { createRequire } from "module";
import process9 from "process";
import { colors as colors5, logger as logger8 } from "@vuepress/utils";
import { cac } from "cac";
var require2 = createRequire(import.meta.url);
var cli = (defaultAppConfig = {}) => {
const program = cac("vuepress");
const versionCli = require2("../package.json").version;
const versionCore = require2("@vuepress/core/package.json").version;
program.version(`core@${versionCore} vuepress/cli@${versionCli}`);
program.help();
program.command("dev [sourceDir]", "Start development server").option("-c, --config <config>", "Set path to config file").option("-p, --port <port>", "Use specified port (default: 8080)").option("-t, --temp <temp>", "Set the directory of the temporary files").option("--host <host>", "Use specified host (default: 0.0.0.0)").option("--cache <cache>", "Set the directory of the cache files").option("--clean-temp", "Clean the temporary files before dev").option("--clean-cache", "Clean the cache files before dev").option("--open", "Open browser when ready").option("--debug", "Enable debug mode").option("--no-watch", "Disable watching page and config files").action(
async (sourceDir, cliOptions) => dev({
defaultAppConfig,
sourceDir,
cliOptions
})
);
program.command("build [sourceDir]", "Build to static site").option("-c, --config <config>", "Set path to config file").option(
"-d, --dest <dest>",
"Set the directory build output (default: .vuepress/dist)"
).option("-t, --temp <temp>", "Set the directory of the temporary files").option("--cache <cache>", "Set the directory of the cache files").option("--clean-temp", "Clean the temporary files before build").option("--clean-cache", "Clean the cache files before build").option("--debug", "Enable debug mode").action(
async (sourceDir, cliOptions) => build2({
defaultAppConfig,
sourceDir,
cliOptions
})
);
program.command("info", "Display environment information").action(info);
program.parse(process9.argv, { run: false });
if (program.matchedCommand) {
;
program.runMatchedCommand().catch((err) => {
logger8.error(err instanceof Error ? colors5.red(err.stack) : err);
process9.exit(1);
});
} else {
program.outputHelp();
}
};
// src/defineUserConfig.ts
var defineUserConfig = (config) => config;
export {
build2 as build,
cli,
createPageDepsHelper,
defineUserConfig,
dev,
handlePageAdd,
handlePageChange,
handlePageUnlink,
info,
loadUserConfig,
resolveAppConfig,
resolveCliAppConfig,
resolveConfig,
resolveUserConfig,
resolveUserConfigConventionalPath,
resolveUserConfigPath,
transformUserConfigToPlugin,
watchPageFiles,
watchUserConfigFile
};