import { MarkdownLink, MarkdownSfcBlocks, MarkdownOptions, Markdown, MarkdownHeader } from '@vuepress/markdown';
import { PageBase, PageData, PageFrontmatter, SiteData } from '@vuepress/shared';
export { HeadAttrsConfig, HeadConfig, HeadTag, HeadTagEmpty, HeadTagNonEmpty, LocaleConfig, LocaleData, PageData, PageFrontmatter, PageHeader, SiteData, SiteLocaleConfig } from '@vuepress/shared';
import { TemplateRenderer } from '@vuepress/utils';

/**
 * Vuepress bundler
 *
 * It provides abilities to:
 * - dev: run dev server for development
 * - build: bundle assets for deployment
 */
interface Bundler {
    name: string;
    dev: (app: App) => Promise<() => Promise<void>>;
    build: (app: App) => Promise<void>;
}

/**
 * Vuepress Page
 */
type Page<ExtraPageData extends Record<any, any> = Record<never, never>, ExtraPageFrontmatter extends Record<any, any> = Record<string, unknown>, ExtraPageFields extends Record<any, any> = Record<never, never>> = PageBase<ExtraPageFrontmatter> & ExtraPageFields & {
    /**
     * Data of the page, which will be available in client code
     */
    data: PageData<ExtraPageData, ExtraPageFrontmatter>;
    /**
     * Raw Content of the page
     */
    content: string;
    /**
     * Rendered content of the page
     */
    contentRendered: string;
    /**
     * Date of the page, in 'yyyy-MM-dd' format
     *
     * @example '2020-09-09'
     */
    date: string;
    /**
     * Dependencies of the page
     */
    deps: string[];
    /**
     * Links of the page
     */
    links: MarkdownLink[];
    /**
     * Markdown env object of the page
     */
    markdownEnv: Record<string, unknown>;
    /**
     * Path of the page that inferred from file path
     *
     * If the page does not come from a file, it would be `null`
     *
     * @example '/guide/index.html'
     */
    pathInferred: string | null;
    /**
     * Locale path prefix of the page
     *
     * @example '/getting-started.html' -> '/'
     * @example '/en/getting-started.html' -> '/en/'
     * @example '/zh/getting-started.html' -> '/zh/'
     */
    pathLocale: string;
    /**
     * Permalink of the page
     *
     * If the page does not have a permalink, it would be `null`
     */
    permalink: string | null;
    /**
     * Custom data to be attached to route record
     */
    routeMeta: Record<string, unknown>;
    /**
     * Extracted sfc blocks of the page
     */
    sfcBlocks: MarkdownSfcBlocks;
    /**
     * Slug of the page
     */
    slug: string;
    /**
     * Source file path
     *
     * If the page does not come from a file, it would be `null`
     */
    filePath: string | null;
    /**
     * Source file path relative to source directory
     *
     * If the page does not come from a file, it would be `null`
     */
    filePathRelative: string | null;
    /**
     * Component file path
     */
    componentFilePath: string;
    /**
     * Component file path relative to temp directory
     */
    componentFilePathRelative: string;
    /**
     * Chunk file path
     */
    chunkFilePath: string;
    /**
     * Chunk file path relative to temp directory
     */
    chunkFilePathRelative: string;
    /**
     * Chunk name
     *
     * This will only take effect in webpack
     */
    chunkName: string;
    /**
     * Rendered html file path
     */
    htmlFilePath: string;
    /**
     * Rendered html file path relative to dest directory
     */
    htmlFilePathRelative: string;
};
/**
 * Options to create vuepress page
 */
interface PageOptions {
    /**
     * If `filePath` is not set, this option will be used as the raw
     * markdown content of the page.
     *
     * If `filePath` is set, this option will be ignored, while the
     * content of the file will be used.
     */
    content?: string;
    /**
     * Absolute file path of the markdown source file.
     */
    filePath?: string;
    /**
     * Default frontmatter of the page, which could be overridden by
     * the frontmatter of the markdown content.
     */
    frontmatter?: PageFrontmatter;
    /**
     * If this option is set, it will be used as the final route path
     * of the page, ignoring the relative path and permalink.
     */
    path?: string;
}

type PromiseOrNot<T> = Promise<T> | T;
interface Closable {
    close(): void;
}
interface Hook<Exposed, Normalized = Exposed, Result = Normalized extends (...args: any) => infer U ? U extends Promise<infer V> ? V : U : void> {
    exposed: Exposed;
    normalized: Normalized;
    result: Result;
}
type LifeCycleHook<T extends unknown[] = []> = Hook<(app: App, ...args: T) => PromiseOrNot<void>>;
type ExtendsHook<T> = Hook<(extendable: T, app: App) => PromiseOrNot<void>>;
type ClientConfigFileHook = Hook<string | ((app: App) => PromiseOrNot<string>), (app: App) => Promise<string>>;
type AliasDefineHook = Hook<Record<string, any> | ((app: App, isServer: boolean) => PromiseOrNot<Record<string, any>>), (app: App, isServer: boolean) => Promise<Record<string, any>>>;
/**
 * List of hooks
 */
interface Hooks {
    onInitialized: LifeCycleHook;
    onPrepared: LifeCycleHook;
    onWatched: LifeCycleHook<[watchers: Closable[], restart: () => Promise<void>]>;
    onGenerated: LifeCycleHook;
    extendsMarkdownOptions: ExtendsHook<MarkdownOptions>;
    extendsMarkdown: ExtendsHook<Markdown>;
    extendsPageOptions: ExtendsHook<PageOptions>;
    extendsPage: ExtendsHook<Page>;
    extendsBundlerOptions: ExtendsHook<any>;
    clientConfigFile: ClientConfigFileHook;
    alias: AliasDefineHook;
    define: AliasDefineHook;
}
/**
 * Name of hooks
 */
type HooksName = keyof Hooks;
/**
 * Exposed hooks API that can be accessed by a plugin
 */
type HooksExposed = {
    [K in HooksName]: Hooks[K]['exposed'];
};
/**
 * Normalized hooks
 */
type HooksNormalized = {
    [K in HooksName]: Hooks[K]['normalized'];
};
/**
 * Result of hooks
 */
type HooksResult = {
    [K in HooksName]: Hooks[K]['result'];
};
/**
 * Hook item
 */
interface HookItem<T extends HooksName> {
    pluginName: string;
    hook: HooksNormalized[T];
}
/**
 * Hook items queue
 */
interface HookQueue<T extends HooksName> {
    name: T;
    items: HookItem<T>[];
    add: (item: HookItem<T>) => void;
    process: (...args: Parameters<HooksNormalized[T]>) => Promise<HooksResult[T][]>;
}

/**
 * Vuepress plugin system
 */
interface PluginApi {
    /**
     * Plugins that have been used
     */
    plugins: PluginObject[];
    /**
     * All available hooks
     */
    hooks: {
        [K in HooksName]: HookQueue<K>;
    };
    /**
     * Register hooks of plugins
     *
     * Should be invoked before applying a hook
     */
    registerHooks: () => void;
}

/**
 * Vuepress plugin
 *
 * A plugin should be rather:
 * - an object (`PluginObject`)
 * - a function that returns an object (`PluginFunction`)
 *
 * A plugin package should have a `Plugin` as the default export
 */
type Plugin<T extends PluginObject = PluginObject> = T | PluginFunction<T>;
/**
 * Vuepress plugin function
 *
 * It accepts plugin options and vuepress app, returns plugin object
 */
type PluginFunction<T extends PluginObject = PluginObject> = (app: App) => T;
/**
 * Vuepress plugin object
 */
interface PluginObject extends Partial<HooksExposed> {
    name: string;
    multiple?: boolean;
}
/**
 * Config field for plugins
 */
type PluginConfig = (Plugin | Plugin[])[];

/**
 * Vuepress theme
 *
 * Theme is a special type of plugin, it should be rather:
 * - an object (`ThemeObject`)
 * - a function that returns an object (`ThemeFunction`)
 *
 * A theme package should have a `Theme` as the default export
 */
type Theme = Plugin<ThemeObject>;
/**
 * Vuepress theme function
 */
type ThemeFunction = PluginFunction<ThemeObject>;
/**
 * Vuepress theme object
 */
interface ThemeObject extends Omit<PluginObject, 'multiple'> {
    /**
     * Extended parent theme
     */
    extends?: Theme;
    /**
     * Allow using plugins in theme
     */
    plugins?: PluginConfig;
    /**
     * Allow overriding default templateBuild
     */
    templateBuild?: string;
    /**
     * Allow specifying custom template renderer
     */
    templateBuildRenderer?: TemplateRenderer;
    /**
     * Allow overriding default templateDev
     */
    templateDev?: string;
}
/**
 * Resolved theme info
 */
interface ThemeInfo {
    /**
     * Plugins, including theme itself and plugins used by theme
     */
    plugins: PluginConfig;
    /**
     * Default build template
     */
    templateBuild?: string;
    /**
     * Default build template renderer
     */
    templateBuildRenderer?: TemplateRenderer;
    /**
     * Default dev template
     */
    templateDev?: string;
}

/**
 * Vuepress app common config that shared between dev and build
 */
interface AppConfigCommon extends Partial<SiteData> {
    source: string;
    dest?: string;
    temp?: string;
    cache?: string;
    public?: string;
    debug?: boolean;
    markdown?: MarkdownOptions;
    pagePatterns?: string[];
    permalinkPattern?: string | null;
    bundler: Bundler;
    theme: Theme;
    plugins?: PluginConfig;
}
/**
 * Vuepress app config for dev
 */
interface AppConfigDev {
    /**
     * Specify the host to use for the dev server
     *
     * @default '0.0.0.0'
     */
    host?: string;
    /**
     * Specify the port to use for the dev server
     *
     * @default 8080
     */
    port?: number;
    /**
     * Whether to open the browser after dev-server had been started
     *
     * @default false
     */
    open?: boolean;
    /**
     * Specify the path of the HTML template to be used for dev
     *
     * @default '@vuepress/client/templates/dev.html'
     */
    templateDev?: string;
}
/**
 * Vuepress app config for build
 */
interface AppConfigBuild {
    /**
     * Determine what resource files should be preloaded. Use boolean value to
     * totally enable / disable.
     *
     * @default true
     */
    shouldPreload?: ((file: string, type: string) => boolean) | boolean;
    /**
     * Determine what resource files should be prefetched. Use boolean value to
     * totally enable / disable.
     *
     * @default true
     */
    shouldPrefetch?: ((file: string, type: string) => boolean) | boolean;
    /**
     * Specify the path of the HTML template to be used for build
     *
     * @default '@vuepress/client/templates/build.html'
     */
    templateBuild?: string;
    /**
     * Specify the HTML template renderer to be used for build
     *
     * @default templateRenderer from '@vuepress/utils'
     */
    templateBuildRenderer?: TemplateRenderer;
}
/**
 * Vuepress app config
 */
type AppConfig = AppConfigCommon & AppConfigDev & AppConfigBuild;
/**
 * Vuepress app options
 */
type AppOptions = Required<AppConfig>;

/**
 * Directory util function
 */
type AppDirFunction = (...args: string[]) => string;
/**
 * Directory utils
 */
interface AppDir {
    cache: AppDirFunction;
    temp: AppDirFunction;
    source: AppDirFunction;
    dest: AppDirFunction;
    public: AppDirFunction;
    client: AppDirFunction;
}
/**
 * Environment flags
 */
interface AppEnv {
    /**
     * Is running in build mode or not
     */
    isBuild: boolean;
    /**
     * Is running in dev mode or not
     */
    isDev: boolean;
    /**
     * Is debug mode enabled or not
     */
    isDebug: boolean;
}
/**
 * Write temp file util
 */
type AppWriteTemp = (file: string, content: string) => Promise<string>;

/**
 * Vuepress app
 */
interface App {
    /**
     * Directory utils
     */
    dir: AppDir;
    /**
     * Environment flags
     */
    env: AppEnv;
    /**
     * Options that filled all optional fields with a default value
     */
    options: AppOptions;
    /**
     * Plugin system
     */
    pluginApi: PluginApi;
    /**
     * Site data, which will be used in client side
     */
    siteData: SiteData;
    /**
     * Version of vuepress core
     */
    version: string;
    /**
     * Write temp file
     */
    writeTemp: AppWriteTemp;
    /**
     * Use a plugin
     */
    use: (plugin: Plugin) => this;
    /**
     * Initialize app.
     *
     * - Theme and plugin will be loaded.
     * - Layouts and pages will be resolved.
     */
    init: () => Promise<void>;
    /**
     * Prepare data for client and write temp files.
     *
     * Should be called after `app.init()`.
     */
    prepare: () => Promise<void>;
    /**
     * Markdown-it instance.
     *
     * Only available after initialization
     */
    markdown: Markdown;
    /**
     * Page objects.
     *
     * Only available after initialization
     */
    pages: Page[];
}
/**
 * Vuepress dev app
 */
interface DevApp extends App {
    /**
     * Start dev server
     *
     * Should be called after `app.prepare()`.
     */
    dev: () => ReturnType<Bundler['dev']>;
}
/**
 * Vuepress build app
 */
interface BuildApp extends App {
    /**
     * Build static files
     *
     * Should be called after `app.prepare()`.
     */
    build: () => ReturnType<Bundler['build']>;
}

/**
 * Generate client configs temp file
 */
declare const prepareClientConfigs: (app: App) => Promise<void>;

/**
 * Generate page chunk temp file of a single page
 */
declare const preparePageChunk: (app: App, page: Page) => Promise<void>;

/**
 * Generate page component temp file of a single page
 */
declare const preparePageComponent: (app: App, page: Page) => Promise<void>;

/**
 * Generate routes temp file
 */
declare const prepareRoutes: (app: App) => Promise<void>;

/**
 * Generate site data temp file
 */
declare const prepareSiteData: (app: App) => Promise<void>;

/**
 * Initialize a vuepress app
 *
 * Plugins should be used before initialization.
 */
declare const appInit: (app: App) => Promise<void>;

/**
 * Prepare files for development or build
 *
 * - page components
 * - page chunks
 * - routes
 * - site data
 * - other files that generated by plugins
 */
declare const appPrepare: (app: App) => Promise<void>;

declare const appUse: (app: App, rawPlugin: Plugin) => App;

/**
 * Create vuepress app
 */
declare const createBaseApp: (config: AppConfig, isBuild?: boolean) => App;

/**
 * Create vuepress build app
 */
declare const createBuildApp: (config: AppConfig) => BuildApp;

/**
 * Create vuepress dev app
 */
declare const createDevApp: (config: AppConfig) => DevApp;

/**
 * Create directory util function
 */
declare const createAppDirFunction: (baseDir: string) => AppDirFunction;
/**
 * Resolve directory utils for vuepress app
 */
declare const resolveAppDir: (options: AppOptions) => AppDir;

/**
 * Resolve environment flags for vuepress app
 */
declare const resolveAppEnv: (options: AppOptions, isBuild: boolean) => AppEnv;

/**
 * Create app options with default values
 */
declare const resolveAppOptions: ({ base, lang, title, description, head, locales, source, dest, temp, cache, public: publicDir, host, port, open, templateDev, shouldPreload, shouldPrefetch, templateBuild, bundler, debug, markdown, pagePatterns, permalinkPattern, plugins, theme, }: AppConfig) => AppOptions;

/**
 * Resolve pages for vuepress app
 */
declare const resolveAppPages: (app: App) => Promise<Page[]>;

/**
 * Resolve site data for vuepress app
 *
 * Site data will also be used in client
 */
declare const resolveAppSiteData: (options: AppOptions) => SiteData;

/**
 * Resolve version of vuepress app
 */
declare const resolveAppVersion: () => string;

/**
 * Resolve write temp file util for vuepress app
 */
declare const resolveAppWriteTemp: (dir: AppDir) => AppWriteTemp;

/**
 * Resolve a plugin object according to name / path / module and config
 */
declare const resolvePluginObject: <T extends PluginObject = PluginObject>(app: App, plugin: Plugin<T>) => T;

/**
 * Resolve theme info and its parent theme info
 */
declare const resolveThemeInfo: (app: App, theme: Theme) => ThemeInfo;

declare const createPage: (app: App, options: PageOptions) => Promise<Page>;

/**
 * Infer page path according to file path
 */
declare const inferPagePath: ({ app, filePathRelative, }: {
    app: App;
    filePathRelative: string | null;
}) => {
    pathInferred: string | null;
    pathLocale: string;
};

/**
 * Render page content and extract related info
 */
declare const renderPageContent: ({ app, content, filePath, filePathRelative, options, }: {
    app: App;
    content: string;
    filePath: string | null;
    filePathRelative: string | null;
    options: PageOptions;
}) => {
    contentRendered: string;
    deps: string[];
    markdownEnv: Record<string, unknown>;
    frontmatter: PageFrontmatter;
    headers: MarkdownHeader[];
    links: MarkdownLink[];
    sfcBlocks: MarkdownSfcBlocks;
    title: string;
};

/**
 * Resolve page data file path
 */
declare const resolvePageChunkInfo: ({ app, htmlFilePathRelative, }: {
    app: App;
    htmlFilePathRelative: string;
}) => {
    chunkFilePath: string;
    chunkFilePathRelative: string;
    chunkName: string;
};

/**
 * Resolve page component and related info
 */
declare const resolvePageComponentInfo: ({ app, htmlFilePathRelative, }: {
    app: App;
    htmlFilePathRelative: string;
}) => Promise<{
    componentFilePath: string;
    componentFilePathRelative: string;
}>;

/**
 * Resolve page date according to frontmatter or file path
 *
 * It will be resolved as 'yyyy-MM-dd' format
 */
declare const resolvePageDate: ({ frontmatter, filePathRelative, }: {
    frontmatter: PageFrontmatter;
    filePathRelative: string | null;
}) => string;

/**
 * Resolve page file content according to filePath or options content
 */
declare const resolvePageFileContent: ({ filePath, options, }: {
    filePath: string | null;
    options: PageOptions;
}) => Promise<string>;

/**
 * Resolve absolute and relative path of page file
 */
declare const resolvePageFilePath: ({ app, options, }: {
    app: App;
    options: PageOptions;
}) => {
    filePath: string | null;
    filePathRelative: string | null;
};

/**
 * Resolve page rendered html file path
 */
declare const resolvePageHtmlInfo: ({ app, path: pagePath, }: {
    app: App;
    path: string;
}) => {
    htmlFilePath: string;
    htmlFilePathRelative: string;
};

/**
 * Resolve language of page
 */
declare const resolvePageLang: ({ app, frontmatter, pathLocale, }: {
    app: App;
    frontmatter: PageFrontmatter;
    pathLocale: string;
}) => string;

/**
 * Resolve the final route path of a page
 */
declare const resolvePagePath: ({ permalink, pathInferred, options, }: {
    permalink: string | null;
    pathInferred: string | null;
    options: PageOptions;
}) => string;

/**
 * Resolve page permalink from frontmatter / options / pattern
 */
declare const resolvePagePermalink: ({ app, frontmatter, slug, date, pathInferred, pathLocale, }: {
    app: App;
    frontmatter: PageFrontmatter;
    slug: string;
    date: string;
    pathInferred: string | null;
    pathLocale: string;
}) => string | null;

/**
 * Resolve page route meta
 */
declare const resolvePageRouteMeta: ({ frontmatter, }: {
    frontmatter: PageFrontmatter;
}) => Record<string, unknown>;

/**
 * Resolve page slug from filename
 */
declare const resolvePageSlug: ({ filePathRelative, }: {
    filePathRelative: string | null;
}) => string;

/**
 * Create hook queue for plugin system
 */
declare const createHookQueue: <T extends keyof Hooks>(name: T) => HookQueue<T>;

declare const createPluginApi: () => PluginApi;

declare const createPluginApiHooks: () => PluginApi['hooks'];

declare const createPluginApiRegisterHooks: (plugins: PluginApi['plugins'], hooks: PluginApi['hooks']) => PluginApi['registerHooks'];

/**
 * Normalize alias and define hook
 */
declare const normalizeAliasDefineHook: (hook: AliasDefineHook['exposed']) => AliasDefineHook['normalized'];

/**
 * Normalize hook for client config file
 */
declare const normalizeClientConfigFileHook: (hook: ClientConfigFileHook['exposed']) => ClientConfigFileHook['normalized'];

export { type AliasDefineHook, type App, type AppConfig, type AppConfigBuild, type AppConfigCommon, type AppConfigDev, type AppDir, type AppDirFunction, type AppEnv, type AppOptions, type AppWriteTemp, type BuildApp, type Bundler, type ClientConfigFileHook, type DevApp, type ExtendsHook, type Hook, type HookItem, type HookQueue, type Hooks, type HooksExposed, type HooksName, type HooksNormalized, type HooksResult, type LifeCycleHook, type Page, type PageOptions, type Plugin, type PluginApi, type PluginConfig, type PluginFunction, type PluginObject, type Theme, type ThemeFunction, type ThemeInfo, type ThemeObject, appInit, appPrepare, appUse, createAppDirFunction, createBaseApp, createBuildApp, createDevApp, createHookQueue, createPage, createPluginApi, createPluginApiHooks, createPluginApiRegisterHooks, inferPagePath, normalizeAliasDefineHook, normalizeClientConfigFileHook, prepareClientConfigs, preparePageChunk, preparePageComponent, prepareRoutes, prepareSiteData, renderPageContent, resolveAppDir, resolveAppEnv, resolveAppOptions, resolveAppPages, resolveAppSiteData, resolveAppVersion, resolveAppWriteTemp, resolvePageChunkInfo, resolvePageComponentInfo, resolvePageDate, resolvePageFileContent, resolvePageFilePath, resolvePageHtmlInfo, resolvePageLang, resolvePagePath, resolvePagePermalink, resolvePageRouteMeta, resolvePageSlug, resolvePluginObject, resolveThemeInfo };
