// src/commands/build/createBuild.ts import process6 from "process"; import { createBuildApp } from "@vuepress/core"; import { debug, formatMs, fs as fs5, logger as logger3, withSpinner } from "@vuepress/utils"; // src/config/defineUserConfig.ts var defineUserConfig = (config) => config; // src/config/loadUserConfig.ts 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], outfile: "out.js", write: false, target: ["node18"], platform: "node", bundle: true, format: "esm", sourcemap: "inline", metafile: true, define: { "__dirname": dirnameVarName, "__filename": filenameVarName, "import.meta.url": importMetaUrlVarName }, plugins: [ { name: "externalize-deps", setup(build2) { build2.onResolve({ filter: /.*/ }, ({ path: id }) => { if (id[0] !== "." && !path.isAbsolute(id)) { return { external: true }; } return null; }); } }, { name: "inject-file-scope-variables", setup(build2) { build2.onLoad({ filter: /\.[cm]?[jt]s$/ }, async (args) => { const contents = await fs.readFile(args.path, "utf8"); 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.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://v2.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, commandOptions, cwd = process2.cwd()) => { const source = path2.resolve(cwd, sourceDir); const appConfig = { source }; OPTIONS_COMMON.forEach((name) => { if (commandOptions[name] !== void 0) { appConfig[name] = commandOptions[name]; } }); OPTIONS_DIRECTORY.forEach((name) => { if (commandOptions[name] !== void 0) { appConfig[name] = path2.resolve(cwd, commandOptions[name]); } }); return appConfig; }; // 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/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 }; if (userConfigPlugin.clientConfigFile === void 0) { 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/commands/build/createBuild.ts var log = debug("vuepress:cli/build"); var createBuild = (defaultAppConfig) => async (sourceDir = ".", commandOptions = {}) => { const start = Date.now(); log(`commandOptions:`, commandOptions); if (process6.env.NODE_ENV === void 0) { process6.env.NODE_ENV = "production"; } const cliAppConfig = resolveCliAppConfig(sourceDir, commandOptions); const userConfigPath = commandOptions.config ? resolveUserConfigPath(commandOptions.config) : resolveUserConfigConventionalPath(cliAppConfig.source); log(`userConfigPath:`, userConfigPath); const { userConfig } = await loadUserConfig(userConfigPath); const appConfig = resolveAppConfig({ defaultAppConfig, cliAppConfig, userConfig }); if (appConfig === null) { return; } const app = createBuildApp(appConfig); app.use(transformUserConfigToPlugin(userConfig, cliAppConfig.source)); if (commandOptions.cleanTemp === true) { await withSpinner("Cleaning temp")(() => { return fs5.remove(app.dir.temp()); }); } if (commandOptions.cleanCache === true) { await withSpinner("Cleaning cache")(() => { return 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/createDev.ts import process8 from "process"; import { createDevApp } from "@vuepress/core"; import { debug as debug2, fs as fs6, logger as logger6, withSpinner as withSpinner2 } from "@vuepress/utils"; // src/commands/dev/watchPageFiles.ts import { colors as colors3, logger as logger4 } 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([], { disableGlobbing: true, 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); if (!pagePaths) return; 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 pagesWatcher = chokidar.watch(app.options.pagePatterns, { cwd: app.dir.source(), 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`); restart(); }); const depsWatcher = chokidar2.watch(userConfigDependencies, { cwd, ignoreInitial: true }); depsWatcher.on("change", (depFile) => { logger5.info(`config dependency ${colors4.magenta(depFile)} is modified`); restart(); }); return [configWatcher, depsWatcher]; }; // src/commands/dev/createDev.ts var log2 = debug2("vuepress:cli/dev"); var createDev = (defaultAppConfig) => { const dev = async (sourceDir = ".", commandOptions = {}) => { log2(`commandOptions:`, commandOptions); if (process8.env.NODE_ENV === void 0) { process8.env.NODE_ENV = "development"; } const cliAppConfig = resolveCliAppConfig(sourceDir, commandOptions); const userConfigPath = commandOptions.config ? resolveUserConfigPath(commandOptions.config) : resolveUserConfigConventionalPath(cliAppConfig.source); log2(`userConfigPath:`, userConfigPath); const { userConfig, userConfigDependencies } = await loadUserConfig(userConfigPath); const appConfig = resolveAppConfig({ defaultAppConfig, cliAppConfig, userConfig }); if (appConfig === null) { return; } const app = createDevApp(appConfig); app.use(transformUserConfigToPlugin(userConfig, cliAppConfig.source)); if (commandOptions.cleanTemp === true) { await withSpinner2("Cleaning temp")(() => { return fs6.remove(app.dir.temp()); }); } if (commandOptions.cleanCache === true) { await withSpinner2("Cleaning cache")(() => { return fs6.remove(app.dir.cache()); }); } await withSpinner2("Initializing and preparing data")(async () => { await app.init(); await app.prepare(); }); const close = await app.dev(); if (commandOptions.watch === false) { return; } const watchers = []; const restart = async () => { await Promise.all([ // close all watchers ...watchers.map((item) => item.close()), // close current dev server close() ]); await dev(sourceDir, { ...commandOptions, // 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); }; return dev; }; // src/commands/info.ts import { 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(); console.info(result); }; // src/cli.ts import { createRequire } from "module"; import process9 from "process"; import { colors as colors5 } 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 ", "Set path to config file").option("-p, --port ", "Use specified port (default: 8080)").option("-t, --temp ", "Set the directory of the temporary files").option("--host ", "Use specified host (default: 0.0.0.0)").option("--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(createDev(defaultAppConfig)); program.command("build [sourceDir]", "Build to static site").option("-c, --config ", "Set path to config file").option( "-d, --dest ", "Set the directory build output (default: .vuepress/dist)" ).option("-t, --temp ", "Set the directory of the temporary files").option("--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(createBuild(defaultAppConfig)); program.command("info", "Display environment information").action(info); program.parse(process9.argv, { run: false }); if (program.matchedCommand) { program.runMatchedCommand().catch((err) => { console.error(colors5.red(err.stack)); process9.exit(1); }); } else { program.outputHelp(); } }; export { cli, createBuild, createDev, defineUserConfig, handlePageAdd, handlePageChange, handlePageUnlink, info, loadUserConfig, resolveAppConfig, resolveCliAppConfig, resolveUserConfigConventionalPath, resolveUserConfigPath, transformUserConfigToPlugin, watchPageFiles, watchUserConfigFile };