import MarkdownIt, { Options } from 'markdown-it';
import MarkdownItToken from 'markdown-it/lib/token.mjs';
import MarkdownItState from 'markdown-it/lib/rules_core/state_core.mjs';
import { Options as Options$1 } from 'markdown-it-emoji';
import { NavbarOptions, SidebarOptions, PluginsOptions, ThemeOptions } from 'vuepress-theme-hope';

/**
 * Options of @mdit-vue/plugin-sfc
 */
interface SfcPluginOptions {
    /**
     * Custom blocks to be extracted
     *
     * @default []
     */
    customBlocks?: string[];
}
/**
 * SFC block that extracted from markdown
 */
interface SfcBlock {
    /**
     * The type of the block
     */
    type: string;
    /**
     * The content, including open-tag and close-tag
     */
    content: string;
    /**
     * The content that stripped open-tag and close-tag off
     */
    contentStripped: string;
    /**
     * The open-tag
     */
    tagOpen: string;
    /**
     * The close-tag
     */
    tagClose: string;
}
interface MarkdownSfcBlocks {
    /**
     * The `<template>` block
     */
    template: SfcBlock | null;
    /**
     * The common `<script>` block
     */
    script: SfcBlock | null;
    /**
     * The `<script setup>` block
     */
    scriptSetup: SfcBlock | null;
    /**
     * All `<script>` blocks.
     *
     * By default, SFC only allows one `<script>` block and one `<script setup>` block.
     * However, some tools may support different types of `<script>`s, so we keep all of them here.
     */
    scripts: SfcBlock[];
    /**
     * All `<style>` blocks.
     */
    styles: SfcBlock[];
    /**
     * All custom blocks.
     */
    customBlocks: SfcBlock[];
}
declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * SFC blocks that extracted by `@mdit-vue/plugin-sfc`
         */
        sfcBlocks?: MarkdownSfcBlocks;
    }
}

interface MarkdownItEnv {
}
interface MarkdownItHeader {
    /**
     * The level of the header
     *
     * `1` to `6` for `<h1>` to `<h6>`
     */
    level: number;
    /**
     * The title of the header
     */
    title: string;
    /**
     * The slug of the header
     *
     * Typically the `id` attr of the header anchor
     */
    slug: string;
    /**
     * Link of the header
     *
     * Typically using `#${slug}` as the anchor hash
     */
    link: string;
    /**
     * The children of the header
     */
    children: MarkdownItHeader[];
}

/**
 * Config for `<head>` tags
 */
type HeadConfig = [HeadTagEmpty, HeadAttrsConfig] | [HeadTagNonEmpty, HeadAttrsConfig, string];
/**
 * Non-empty tags in `<head>`
 */
type HeadTagNonEmpty = 'noscript' | 'script' | 'style' | 'template' | 'title';
/**
 * Empty tags in `<head>`
 */
type HeadTagEmpty = 'base' | 'link' | 'meta' | 'script';
/**
 * Attributes to be set for tags in `<head>`
 */
type HeadAttrsConfig = Record<string, boolean | string>;

/**
 * Locales config, a key-value object
 *
 * - Key is the locale path (prefix)
 * - Value is the locales data
 *
 * @remark suffix `Config` means this is for user config
 */
type LocaleConfig<T extends LocaleData = LocaleData> = Record<string, Partial<T>>;
/**
 * Locales data
 */
type LocaleData = Record<never, never>;

/**
 * Base type of vuepress page
 */
interface PageBase<ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>> {
    /**
     * Route path of the page
     *
     * Firstly inferred from the file path
     *
     * Might be overridden by permalink
     *
     * @example '/guide/index.html'
     * @example '/2020/02/02/hello-world.html'
     */
    path: string;
    /**
     * Title of the page
     */
    title: string;
    /**
     * Language of the page
     */
    lang: string;
    /**
     * Front matter of the page
     */
    frontmatter: PageFrontmatter<ExtraPageFrontmatter>;
}
/**
 * Vuepress page data
 */
type PageData<ExtraPageData extends Record<string, unknown> = Record<string, unknown>, ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>> = ExtraPageData & PageBase<ExtraPageFrontmatter>;
/**
 * Vuepress page frontmatter
 *
 * Notice that frontmatter is parsed from yaml or other languages,
 * so we cannot guarantee the type safety
 */
type PageFrontmatter<T extends Record<string, unknown> = Record<string, unknown>> = Partial<T> & {
    date?: Date | string;
    description?: string;
    head?: HeadConfig[];
    lang?: string;
    layout?: string;
    permalink?: string | null;
    permalinkPattern?: string | null;
    routeMeta?: Record<string, unknown>;
    title?: string;
};
/**
 * Vuepress page header
 */
type PageHeader = MarkdownItHeader;

/**
 * Vuepress site data
 */
interface SiteData extends SiteLocaleData {
    /**
     * The base URL the site will be deployed at
     *
     * It should always start and end with a slash
     *
     * @default '/'
     */
    base: '/' | `/${string}/`;
    /**
     * Specify locales for i18n support
     *
     * It will override the root-level site data in different subpath
     *
     * @example
     * {
     *   '/en/': {
     *     lang: 'en-US',
     *     title: 'Hello',
     *     description: 'This will take effect under /en/ subpath',
     *   },
     *   '/zh/': {
     *     lang: 'zh-CN',
     *     title: '你好',
     *     description: '它将会在 /zh/ 子路径下生效',
     *   }
     * }
     */
    locales: SiteLocaleConfig;
}
/**
 * Locales data of vuepress site
 *
 * If they are set in the root of site data, they will be used
 * as the default value
 *
 * If they are set in the `locales` of site data, they will be
 * used for specific locale
 */
interface SiteLocaleData {
    /**
     * Language for the site
     *
     * @default 'en-US'
     */
    lang: string;
    /**
     * Title for the site
     *
     * @default ''
     */
    title: string;
    /**
     * Description for the site
     *
     * @default ''
     */
    description: string;
    /**
     * Head config
     *
     * Describe the tags to be appended into the `<head>` tag
     *
     * @default []
     *
     * @example ['link', { rel: 'icon', href: '/logo.png' }]
     * @example ['style', { type: 'text/css' }, 'p { color: red; }']
     */
    head: HeadConfig[];
}
/**
 * Site locale config
 */
type SiteLocaleConfig = LocaleConfig<SiteLocaleData>;

/**
 * Takes a string or object with `content` property, extracts
 * and parses front-matter from the string, then returns an object
 * with `data`, `content` and other [useful properties](#returned-object).
 *
 * ```js
 * var matter = require('gray-matter');
 * console.log(matter('---\ntitle: Home\n---\nOther stuff'));
 * //=> { data: { title: 'Home'}, content: 'Other stuff' }
 * ```
 * @param {Object|String} `input` String, or object with `content` string
 * @param {Object} `options`
 * @return {Object}
 * @api public
 */
declare function matter<
  I extends matter.Input,
  O extends matter.GrayMatterOption<I, O>
>(input: I | { content: I }, options?: O): matter.GrayMatterFile<I>

declare namespace matter {
  type Input = string | Buffer
  interface GrayMatterOption<
    I extends Input,
    O extends GrayMatterOption<I, O>
  > {
    parser?: () => void
    eval?: boolean
    excerpt?: boolean | ((input: I, options: O) => string)
    excerpt_separator?: string
    engines?: {
      [index: string]:
        | ((input: string) => object)
        | { parse: (input: string) => object; stringify?: (data: object) => string }
    }
    language?: string
    delimiters?: string | [string, string]
  }
  interface GrayMatterFile<I extends Input> {
    data: { [key: string]: any }
    content: string
    excerpt?: string
    orig: Buffer | I
    language: string
    matter: string
    stringify(lang: string): string
  }
  
  /**
   * Stringify an object to YAML or the specified language, and
   * append it to the given string. By default, only YAML and JSON
   * can be stringified. See the [engines](#engines) section to learn
   * how to stringify other languages.
   *
   * ```js
   * console.log(matter.stringify('foo bar baz', {title: 'Home'}));
   * // results in:
   * // ---
   * // title: Home
   * // ---
   * // foo bar baz
   * ```
   * @param {String|Object} `file` The content string to append to stringified front-matter, or a file object with `file.content` string.
   * @param {Object} `data` Front matter to stringify.
   * @param {Object} `options` [Options](#options) to pass to gray-matter and [js-yaml].
   * @return {String} Returns a string created by wrapping stringified yaml with delimiters, and appending that to the given string.
   */
  export function stringify<O extends GrayMatterOption<string, O>>(
    file: string | { content: string },
    data: object,
    options?: GrayMatterOption<string, O>
  ): string

  /**
   * Synchronously read a file from the file system and parse
   * front matter. Returns the same object as the [main function](#matter).
   *
   * ```js
   * var file = matter.read('./content/blog-post.md');
   * ```
   * @param {String} `filepath` file path of the file to read.
   * @param {Object} `options` [Options](#options) to pass to gray-matter.
   * @return {Object} Returns [an object](#returned-object) with `data` and `content`
   */
  export function read<O extends GrayMatterOption<string, O>>(
    fp: string,
    options?: GrayMatterOption<string, O>
  ): matter.GrayMatterFile<string>

  /**
   * Returns true if the given `string` has front matter.
   * @param  {String} `string`
   * @param  {Object} `options`
   * @return {Boolean} True if front matter exists.
   */
  export function test<O extends matter.GrayMatterOption<string, O>>(
    str: string,
    options?: GrayMatterOption<string, O>
  ): boolean

  /**
   * Detect the language to use, if one is defined after the
   * first front-matter delimiter.
   * @param  {String} `string`
   * @param  {Object} `options`
   * @return {Object} Object with `raw` (actual language string), and `name`, the language with whitespace trimmed
   */
  export function language<O extends matter.GrayMatterOption<string, O>>(
    str: string,
    options?: GrayMatterOption<string, O>
  ): { name: string; raw: string }
}

type GrayMatterOptions = matter.GrayMatterOption<string, GrayMatterOptions>;
/**
 * Options of @mdit-vue/plugin-frontmatter
 */
interface FrontmatterPluginOptions {
    /**
     * Options of gray-matter
     *
     * @see https://github.com/jonschlinkert/gray-matter#options
     */
    grayMatterOptions?: GrayMatterOptions;
    /**
     * Render the excerpt or not
     *
     * @default true
     */
    renderExcerpt?: boolean;
}
declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * The raw Markdown content without frontmatter
         */
        content?: string;
        /**
         * The excerpt that extracted by `@mdit-vue/plugin-frontmatter`
         *
         * - Would be the rendered HTML when `renderExcerpt` is enabled
         * - Would be the raw Markdown when `renderExcerpt` is disabled
         */
        excerpt?: string;
        /**
         * The frontmatter that extracted by `@mdit-vue/plugin-frontmatter`
         */
        frontmatter?: Record<string, unknown>;
    }
}

/**
 * Options of @mdit-vue/plugin-headers
 */
interface HeadersPluginOptions {
    /**
     * A custom slugification function
     *
     * Should use the same slugify function with markdown-it-anchor
     * to ensure the link is matched
     */
    slugify?: (str: string) => string;
    /**
     * A function for formatting header title
     */
    format?: (str: string) => string;
    /**
     * Heading level that going to be extracted
     *
     * Should be a subset of markdown-it-anchor's `level` option
     * to ensure the slug is existed
     *
     * @default [2,3]
     */
    level?: number[];
    /**
     * Should allow headers inside nested blocks or not
     *
     * If set to `true`, headers inside blockquote, list, etc. would also be extracted.
     *
     * @default false
     */
    shouldAllowNested?: boolean;
}
declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * The headers that extracted by `@mdit-vue/plugin-headers`
         */
        headers?: MarkdownItHeader[];
    }
}

/**
 * Options of @mdit-vue/plugin-toc
 */
interface TocPluginOptions {
    /**
     * The pattern serving as the TOC placeholder in your markdown
     *
     * @default /^\[\[toc\]\]$/i
     */
    pattern?: RegExp;
    /**
     * A custom slugification function
     *
     * Should use the same slugify function with markdown-it-anchor
     * to ensure the link is matched
     */
    slugify?: (str: string) => string;
    /**
     * A function for formatting headings
     */
    format?: (str: string) => string;
    /**
     * Heading level that going to be included in the TOC
     *
     * Should be a subset of markdown-it-anchor's `level` option
     * to ensure the link is existed
     *
     * @default [2,3]
     */
    level?: number[];
    /**
     * Should allow headers inside nested blocks or not
     *
     * If set to `true`, headers inside blockquote, list, etc. would also be included.
     *
     * @default false
     */
    shouldAllowNested?: boolean;
    /**
     * HTML tag of the TOC container
     *
     * @default 'nav'
     */
    containerTag?: string;
    /**
     * The class for the TOC container
     *
     * @default 'table-of-contents'
     */
    containerClass?: string;
    /**
     * HTML tag of the TOC list
     *
     * @default 'ul'
     */
    listTag?: 'ol' | 'ul';
    /**
     * The class for the TOC list
     *
     * @default ''
     */
    listClass?: string;
    /**
     * The class for the `<li>` tag
     *
     * @default ''
     */
    itemClass?: string;
    /**
     * The tag of the link inside `<li>` tag
     *
     * @default 'a'
     */
    linkTag?: 'a' | 'router-link';
    /**
     * The class for the link inside the `<li>` tag
     *
     * @default ''
     */
    linkClass?: string;
}

declare namespace anchor {
  export type Token = MarkdownItToken
  export type State = MarkdownItState
  export type RenderHref = (slug: string, state: State) => string;
  export type RenderAttrs = (slug: string, state: State) => Record<string, string | number>;

  export interface PermalinkOptions {
    class?: string,
    symbol?: string,
    renderHref?: RenderHref,
    renderAttrs?: RenderAttrs
  }

  export interface HeaderLinkPermalinkOptions extends PermalinkOptions {
    safariReaderFix?: boolean;
  }

  export interface LinkAfterHeaderPermalinkOptions extends PermalinkOptions {
    style?: 'visually-hidden' | 'aria-label' | 'aria-describedby' | 'aria-labelledby',
    assistiveText?: (title: string) => string,
    visuallyHiddenClass?: string,
    space?: boolean | string,
    placement?: 'before' | 'after'
    wrapper?: [string, string] | null
  }

  export interface LinkInsideHeaderPermalinkOptions extends PermalinkOptions {
    space?: boolean | string,
    placement?: 'before' | 'after',
    ariaHidden?: boolean
  }

  export interface AriaHiddenPermalinkOptions extends PermalinkOptions {
    space?: boolean | string,
    placement?: 'before' | 'after'
  }

  export type PermalinkGenerator = (slug: string, opts: PermalinkOptions, state: State, index: number) => void;

  export interface AnchorInfo {
    slug: string;
    title: string;
  }

  export interface AnchorOptions {
    level?: number | number[];

    slugify?(str: string): string;
    slugifyWithState?(str: string, state: State): string;
    getTokensText?(tokens: Token[]): string;

    uniqueSlugStartIndex?: number;
    permalink?: PermalinkGenerator;

    callback?(token: Token, anchor_info: AnchorInfo): void;

    tabIndex?: number | false;
  }

  export const permalink: {
    headerLink: (opts?: HeaderLinkPermalinkOptions) => PermalinkGenerator
    linkAfterHeader: (opts?: LinkAfterHeaderPermalinkOptions) => PermalinkGenerator
    linkInsideHeader: (opts?: LinkInsideHeaderPermalinkOptions) => PermalinkGenerator
    ariaHidden: (opts?: AriaHiddenPermalinkOptions) => PermalinkGenerator
  };
}

declare function anchor(md: MarkdownIt, opts?: anchor.AnchorOptions): void;

declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * The title that extracted by `@mdit-vue/plugin-title`
         */
        title?: string;
    }
}

type AnchorPluginOptions = anchor.AnchorOptions;

interface AssetsPluginOptions {
    /**
     * Whether to prepend base to absolute path
     */
    absolutePathPrependBase?: boolean;
    /**
     * Prefix to add to relative assets links
     */
    relativePathPrefix?: string;
}

type EmojiPluginOptions = Options$1;

interface ImportCodePluginOptions {
    /**
     * A function to handle the import path
     */
    handleImportPath?: (str: string) => string;
}

interface LinksPluginOptions {
    /**
     * Additional attributes for external links
     *
     * @default
     * ```js
     * ({
     *   target: '_blank',
     *   rel: 'noopener noreferrer',
     * })
     * ```
     */
    externalAttrs?: Record<string, string>;
    /**
     * Tag for internal links
     *
     * @default 'RouteLink'
     */
    internalTag?: 'a' | 'RouteLink' | 'RouterLink';
    /**
     * Method to check if a link is external
     *
     * @default import { isLinkExternal } from '@vuepress/shared'
     */
    isExternal?: (href: string, env: MarkdownEnv) => boolean;
}

interface VPrePluginOptions {
    /**
     * Add `v-pre` directive to `<pre>` tag of code block or not
     */
    block?: boolean;
    /**
     * Add `v-pre` directive to `<code>` tag of inline code or not
     */
    inline?: boolean;
}

type Markdown = MarkdownIt;

interface MarkdownOptions extends Options {
    anchor?: AnchorPluginOptions | false;
    assets?: AssetsPluginOptions | false;
    component?: false;
    emoji?: EmojiPluginOptions | false;
    frontmatter?: FrontmatterPluginOptions | false;
    headers?: HeadersPluginOptions | false;
    title?: false;
    importCode?: ImportCodePluginOptions | false;
    links?: LinksPluginOptions | false;
    sfc?: SfcPluginOptions | false;
    slugify?: MarkdownSlugifyFunction;
    toc?: TocPluginOptions | false;
    vPre?: VPrePluginOptions | false;
    /**
     * @deprecated This feature has been removed. Please use `@vuepress/plugin-prismjs` or `@vuepress/plugin-shiki` instead.
     */
    code?: never;
}
/**
 * Internal links in markdown file
 *
 * Used for file existence check
 */
interface MarkdownLink {
    raw: string;
    relative: string;
    absolute: string | null;
}
/**
 * The `env` object to be passed to markdown-it render function
 *
 * Input some meta data for markdown file parsing and rendering
 *
 * Output some resources from the markdown file
 */
interface MarkdownEnv extends MarkdownItEnv {
    /**
     * Base / publicPath of current site
     */
    base?: string;
    /**
     * Absolute file path of the markdown file
     */
    filePath?: string | null;
    /**
     * Relative file path of the markdown file
     */
    filePathRelative?: string | null;
    /**
     * Frontmatter of the markdown file
     */
    frontmatter?: PageFrontmatter;
    /**
     * Imported file that extracted by importCodePlugin
     */
    importedFiles?: string[];
    /**
     * Links that extracted by linksPlugin
     */
    links?: MarkdownLink[];
}
/**
 * Type of `slugify` function
 */
type MarkdownSlugifyFunction = (str: string) => string;

declare module "upath" {

  /**
   * A parsed path object generated by path.parse() or consumed by path.format().
   */
  export interface ParsedPath {
    /**
     * The root of the path such as '/' or 'c:\'
     */
    root: string;
    /**
     * The full directory path such as '/home/user/dir' or 'c:\path\dir'
     */
    dir: string;
    /**
     * The file name including extension (if any) such as 'index.html'
     */
    base: string;
    /**
     * The file extension (if any) such as '.html'
     */
    ext: string;
    /**
     * The file name without extension (if any) such as 'index'
     */
    name: string;
  }

  /**
   * Version of the library
   */
  export var VERSION: string;

  /**
   * Just converts all `to/` and consolidates duplicates, without performing any normalization.
   *
   * @param p string path to convert to unix.
   */
  export function toUnix(p: string): string;

  /**
   * Exactly like path.normalize(path), but it keeps the first meaningful ./.
   *
   * Note that the unix / is returned everywhere, so windows \ is always converted to unix /.
   *
   * @param p string path to normalize.
   */
  export function normalizeSafe(p: string): string;

  /**
   * Exactly like path.normalizeSafe(path), but it trims any useless ending /.
   *
   * @param p string path to normalize
   */
  export function normalizeTrim(p: string): string;

  /**
   * Exactly like path.join(), but it keeps the first meaningful ./.
   *
   * Note that the unix / is returned everywhere, so windows \ is always converted to unix /.
   *
   * @param paths string paths to join
   */
  export function joinSafe(...p: any[]): string;

  /**
   * Adds .ext to filename, but only if it doesn't already have the exact extension.
   *
   * @param file string filename to add extension to
   * @param ext string extension to add
   */
  export function addExt(file: string, ext: string): string;

  /**
   * Trims a filename's extension.
   *
   * Extensions are considered to be up to maxSize chars long, counting the dot (defaults to 7).
   *
   * An Array of ignoreExts (eg ['.min']) prevents these from being considered as extension, thus are not trimmed.
   *
   * @param filename string filename to trim it's extension
   * @param ignoreExts array extensions to ignore
   * @param maxSize number max length of the extension
   */
  export function trimExt(filename: string, ignoreExts?: string[], maxSize?: number): string;

  /**
   * Removes the specific ext extension from filename, if it has it. Otherwise it leaves it as is. As in all upath functions, it be .ext or ext.
   *
   * @param file string filename to remove extension to
   * @param ext string extension to remove
   */
  export function removeExt(filename: string, ext: string): string;

  /**
   * Changes a filename's extension to ext. If it has no (valid) extension, it adds it.
   *
   * Valid extensions are considered to be up to maxSize chars long, counting the dot (defaults to 7).
   *
   * An Array of ignoreExts (eg ['.min']) prevents these from being considered as extension, thus are not changed - the new extension is added instead.
   *
   * @param filename string filename to change it's extension
   * @param ext string extension to change to
   * @param ignoreExts array extensions to ignore
   * @param maxSize number max length of the extension
   */
  export function changeExt(filename: string, ext: string, ignoreExts?: string[], maxSize?: number): string;

  /**
   * Adds .ext to filename, only if it doesn't already have any old extension.
   *
   * (Old) extensions are considered to be up to maxSize chars long, counting the dot (defaults to 7).
   *
   * An Array of ignoreExts (eg ['.min']) will force adding default .ext even if one of these is present.
   *
   * @param filename string filename to default to it's extension
   * @param ext string extension to default to
   * @param ignoreExts array extensions to ignore
   * @param maxSize number max length of the extension
   */
  export function defaultExt(filename: string, ext: string, ignoreExts?: string[], maxSize?: number): string;

  /**
   * Normalize a string path, reducing '..' and '.' parts.
   * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
   *
   * @param p string path to normalize.
   */
  export function normalize(p: string): string;
  /**
   * Join all arguments together and normalize the resulting path.
   * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
   *
   * @param paths string paths to join.
   */
  export function join(...paths: any[]): string;
  /**
   * Join all arguments together and normalize the resulting path.
   * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
   *
   * @param paths string paths to join.
   */
  export function join(...paths: string[]): string;
  /**
   * The right-most parameter is considered {to}.  Other parameters are considered an array of {from}.
   *
   * Starting from leftmost {from} parameter, resolves {to} to an absolute path.
   *
   * If {to} isn't already absolute, {from} arguments are prepended in right to left order, until an absolute path is found. If after using all {from} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory.
   *
   * @param pathSegments string paths to join.  Non-string arguments are ignored.
   */
  export function resolve(...pathSegments: any[]): string;
  /**
   * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory.
   *
   * @param path path to test.
   */
  export function isAbsolute(path: string): boolean;
  /**
   * Solve the relative path from {from} to {to}.
   * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve.
   *
   * @param from
   * @param to
   */
  export function relative(from: string, to: string): string;
  /**
   * Return the directory name of a path. Similar to the Unix dirname command.
   *
   * @param p the path to evaluate.
   */
  export function dirname(p: string): string;
  /**
   * Return the last portion of a path. Similar to the Unix basename command.
   * Often used to extract the file name from a fully qualified path.
   *
   * @param p the path to evaluate.
   * @param ext optionally, an extension to remove from the result.
   */
  export function basename(p: string, ext?: string): string;
  /**
   * Return the extension of the path, from the last '.' to end of string in the last portion of the path.
   * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string
   *
   * @param p the path to evaluate.
   */
  export function extname(p: string): string;
  /**
   * The platform-specific file separator. '\\' or '/'.
   */
  export var sep: string;
  /**
   * The platform-specific file delimiter. ';' or ':'.
   */
  export var delimiter: string;
  /**
   * Returns an object from a path string - the opposite of format().
   *
   * @param pathString path to evaluate.
   */
  export function parse(pathString: string): ParsedPath;
  /**
   * Returns a path string from an object - the opposite of parse().
   *
   * @param pathString path to evaluate.
   */
  export function format(pathObject: ParsedPath): string;

  export module posix {
    export function normalize(p: string): string;
    export function join(...paths: any[]): string;
    export function resolve(...pathSegments: any[]): string;
    export function isAbsolute(p: string): boolean;
    export function relative(from: string, to: string): string;
    export function dirname(p: string): string;
    export function basename(p: string, ext?: string): string;
    export function extname(p: string): string;
    export var sep: string;
    export var delimiter: string;
    export function parse(p: string): ParsedPath;
    export function format(pP: ParsedPath): string;
  }

  export module win32 {
    export function normalize(p: string): string;
    export function join(...paths: any[]): string;
    export function resolve(...pathSegments: any[]): string;
    export function isAbsolute(p: string): boolean;
    export function relative(from: string, to: string): string;
    export function dirname(p: string): string;
    export function basename(p: string, ext?: string): string;
    export function extname(p: string): string;
    export var sep: string;
    export var delimiter: string;
    export function parse(p: string): ParsedPath;
    export function format(pP: ParsedPath): string;
  }
}

/**
 * Context type of the template renderer
 */
interface TemplateRendererContext {
    /**
     * The rendered page content. Typically to be put inside `<div id="app"></div>`
     */
    content: string;
    /**
     * The rendered page head. Typically to be put inside `<head></head>`
     */
    head: string;
    /**
     * The language of the page. Typically to be put inside `<html lang="{{ lang }}">`
     */
    lang: string;
    /**
     * The rendered prefetch links. Typically to be put inside `<head></head>`
     */
    prefetch: string;
    /**
     * The rendered preload links. Typically to be put inside `<head></head>`
     */
    preload: string;
    /**
     * The rendered scripts. Typically to be put before `</body>`
     */
    scripts: string;
    /**
     * The rendered styles. Typically to be put inside `<head></head>`
     */
    styles: string;
    /**
     * The version of VuePress
     */
    version: string;
}
/**
 * Type of the template renderer function
 */
type TemplateRenderer = (template: string, context: TemplateRendererContext) => Promise<string> | string;

/**
 * Vuepress bundler
 *
 * It provides abilities to:
 * - dev: run dev server for development
 * - build: bundle assets for deployment
 */
interface Bundler {
    /**
     * Name of the bundler
     */
    name: string;
    /**
     * Method to run vuepress app in dev mode, starting dev server
     */
    dev: (app: App) => Promise<() => Promise<void>>;
    /**
     * Method to run vuepress app in build mode, generating static pages and assets
     */
    build: (app: App) => Promise<void>;
}
type BundlerOptions = Record<string, unknown>;

/**
 * Vuepress Page
 */
type Page<ExtraPageData extends Record<string, unknown> = Record<string, unknown>, ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>, ExtraPageFields extends Record<string, unknown> = Record<string, unknown>> = ExtraPageFields & PageBase<ExtraPageFrontmatter> & {
    /**
     * 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[];
    /**
     * Headers of the page
     */
    headers: PageHeader[];
    /**
     * 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 {
    /**
     * The raw markdown content of the page.
     *
     * If `content` is not provided, the file content of the `filePath`
     * 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 : never> {
    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, unknown> | ((app: App, isServer: boolean) => PromiseOrNot<Record<string, unknown>>), (app: App, isServer: boolean) => Promise<Record<string, unknown>>>;
/**
 * 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<BundlerOptions>;
    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> = PluginFunction<T> | 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 of the plugin
     */
    name: string;
    /**
     * Allow the plugin to be used multiple times or not
     */
    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 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;
}

/**
 * Vuepress app common config that shared between dev and build
 */
interface AppConfigCommon extends Partial<SiteData> {
    /**
     * Source directory of the markdown files.
     *
     * Vuepress will load markdown files from this directory.
     *
     * @required
     */
    source: string;
    /**
     * Destination directory of the output files.
     *
     * Vuepress will output the static site files to this directory.
     *
     * @default `${source}/.vuepress/dist`
     */
    dest?: string;
    /**
     * Temp files directory.
     *
     * Vuepress will write temp files to this directory.
     *
     * @default `${source}/.vuepress/.temp`
     */
    temp?: string;
    /**
     * Cache files directory.
     *
     * Vuepress will write cache files to this directory.
     *
     * @default `${source}/.vuepress/.cache`
     */
    cache?: string;
    /**
     * Public files directory.
     *
     * Vuepress will copy the files from public directory to the output directory.
     *
     * @default `${source}/.vuepress/public`
     */
    public?: string;
    /**
     * Whether to enable debug mode
     *
     * @default false
     */
    debug?: boolean;
    /**
     * Markdown options
     *
     * @default {}
     */
    markdown?: MarkdownOptions;
    /**
     * Patterns to match the markdown files as pages
     *
     * @default ['**\/*.md', '!.vuepress', '!node_modules']
     */
    pagePatterns?: string[];
    /**
     * Pattern to generate permalink for pages
     *
     * @default null
     */
    permalinkPattern?: string | null;
    /**
     * Vuepress bundler
     *
     * @required
     */
    bundler: Bundler;
    /**
     * Vuepress theme
     *
     * @required
     */
    theme: Theme;
    /**
     * Vuepress plugins
     *
     * @default []
     */
    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?: boolean | ((file: string, type: string) => boolean);
    /**
     * Determine what resource files should be prefetched. Use boolean value to
     * totally enable / disable.
     *
     * @default true
     */
    shouldPrefetch?: boolean | ((file: string, type: string) => 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 `import { templateRenderer } from '@vuepress/utils'`
     */
    templateBuildRenderer?: TemplateRenderer;
}
/**
 * Vuepress app user config.
 *
 * It would be provided by user, typically via a config file.
 */
type AppConfig = AppConfigBuild & AppConfigCommon & AppConfigDev;
/**
 * Vuepress app options that resolved from user config.
 *
 * It fills all optional fields with a default value.
 */
type AppOptions = Required<AppConfig>;

/**
 * Directory util function
 */
type AppDirFunction = (...args: string[]) => string;
/**
 * Directory utils
 */
interface AppDir {
    /**
     * Resolve file path in cache directory
     */
    cache: AppDirFunction;
    /**
     * Resolve file path in temp directory
     */
    temp: AppDirFunction;
    /**
     * Resolve file path in source directory
     */
    source: AppDirFunction;
    /**
     * Resolve file path in dest directory
     */
    dest: AppDirFunction;
    /**
     * Resolve file path in public directory
     */
    public: AppDirFunction;
    /**
     * Resolve file path in client directory
     */
    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>;

/**
 * App base properties, will be available after creation, even before initialization
 */
interface AppPropertiesBase {
    /**
     * 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;
    /**
     * 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>;
    /**
     * Use a plugin.
     *
     * Should be called before `app.init()`.
     */
    use: (plugin: Plugin) => this;
    /**
     * Util to write temp file
     */
    writeTemp: AppWriteTemp;
}
/**
 * App initialized properties, will only be available after initialization
 */
interface AppPropertiesInitialized {
    /**
     * Markdown-it instance.
     *
     * Only available after initialization
     */
    markdown: Markdown;
    /**
     * Page objects.
     *
     * Only available after initialization
     */
    pages: Page[];
}
/**
 * Vuepress app instance
 */
type App = AppPropertiesBase & AppPropertiesInitialized;

/**
 * User config type of vuepress
 *
 * It will be transformed to `AppConfig` by cli
 */
type UserConfig = Omit<PluginObject, 'multiple' | 'name'> & Partial<AppConfig>;

/**
 * 用户配置
 */
type VipVuepressUserConfig = UserConfig;
/**
 * 定义 vuepress 配置
 * @param config 配置
 */
declare function defineVipVuepressConfig(config: VipVuepressUserConfig): VipVuepressUserConfig;
/**
 * 导航栏
 * @param options 配置
 */
declare function defineVipNavbarConfig(options: NavbarOptions): NavbarOptions;
/**
 * 侧边栏
 * @param options 配置
 */
declare function defineVipSidebarConfig(options: SidebarOptions): SidebarOptions;
/**
 * 默认的文档目录
 * - docs
 */
declare const VUEPRESS_DEFAULT_DOCS_DIR: string;

/**
 * 主题中插件的一些配置
 */
declare const baseThemePluginOptions: PluginsOptions;
/**
 * 主题相关配置
 * 参考：https://theme-hope.vuejs.press/zh/config/intro.html
 */
declare function getVipHopeTheme(userConfig: ThemeOptions): ThemeFunction;
/**
 * 引入代码文件时的路径替换
 * https://vuejs.press/zh/guide/markdown.html#%E5%AF%BC%E5%85%A5%E4%BB%A3%E7%A0%81%E5%9D%97
 * - 例如：引入的路径中包含@code，会替换为当前目录下的code目录
 * @param pathArray 路径规则，旧路径，新路径
 * @param cwd 文件目录，默认当前目录
 * @returns 新路径
 */
declare function handleImportCodePath(pathArray: Array<[oldPath: string, newPath: string]>, cwd?: string): (str: string) => string;

export { VUEPRESS_DEFAULT_DOCS_DIR, type VipVuepressUserConfig, baseThemePluginOptions, defineVipNavbarConfig, defineVipSidebarConfig, defineVipVuepressConfig, getVipHopeTheme, handleImportCodePath };
