refactor: declare module-level state at the top of files

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pull/5342/head
Divyansh Singh 5 days ago
parent 72f5b6d0de
commit 4e28826745

@ -35,6 +35,9 @@ const excludedModules = [
clientDir
]
const cache = new Map<string, boolean>()
const cacheTheme = new Map<string, boolean>()
// bundles the VitePress app for both client AND server.
export async function bundle(
config: SiteConfig,
@ -187,9 +190,6 @@ export async function bundle(
return { clientResult, serverResult, pageToHashMap: sortedPageToHashMap }
}
const cache = new Map<string, boolean>()
const cacheTheme = new Map<string, boolean>()
function chunkName(
themeEntryRE: RegExp,
id: string,

@ -33,6 +33,10 @@ export * from './siteConfig'
const debug = createDebug('vitepress:config')
const supportedConfigExtensions = ['js', 'ts', 'mjs', 'mts']
const additionalConfigRE = /(?:^|\/|\\)config\.m?[jt]s$/
const additionalConfigGlob = `**/config.{js,mjs,ts,mts}`
const resolve = (root: string, file: string) =>
normalizePath(path.resolve(root, `.vitepress`, file))
@ -181,10 +185,6 @@ export async function resolveConfig(
return config as SiteConfig
}
const supportedConfigExtensions = ['js', 'ts', 'mjs', 'mts']
const additionalConfigRE = /(?:^|\/|\\)config\.m?[jt]s$/
const additionalConfigGlob = `**/config.{js,mjs,ts,mts}`
export function isAdditionalConfigFile(path: string) {
return additionalConfigRE.test(path)
}

@ -61,14 +61,6 @@ export type { Header } from '../shared'
// not exported from @mdit/plugin-emoji, so derive it from the plugin signature
type EmojiPluginOptions = NonNullable<Parameters<typeof emojiPlugin>[1]>
// `true` and `undefined` enable a plugin with its default options - only an
// object carries user-provided plugin options
function normalizePluginOptions<T>(
value: T | boolean | undefined
): T | undefined {
return typeof value === 'boolean' ? undefined : value
}
export type ThemeOptions =
| ThemeRegistrationAny
| BuiltinTheme
@ -545,3 +537,11 @@ export async function createMarkdownRenderer(
return md
}
// `true` and `undefined` enable a plugin with its default options - only an
// object carries user-provided plugin options
function normalizePluginOptions<T>(
value: T | boolean | undefined
): T | undefined {
return typeof value === 'boolean' ? undefined : value
}

@ -18,6 +18,19 @@ export interface ContainerPluginOptions {
locales?: Record<string, MarkdownLocaleOptions | undefined>
}
const containerLabels = [
['tip', 'tipLabel', 'TIP'],
['info', 'infoLabel', 'INFO'],
['warning', 'warningLabel', 'WARNING'],
['danger', 'dangerLabel', 'DANGER'],
['details', 'detailsLabel', 'Details'],
['note', 'noteLabel', 'NOTE'],
['important', 'importantLabel', 'IMPORTANT'],
['caution', 'cautionLabel', 'CAUTION']
] as const
const alertMarkerRE = /^\[!([\w-]+)\]([^\n\r]*)/
export const containerPlugin = (
md: MarkdownItAsync,
options?: ContainerOptions,
@ -64,17 +77,6 @@ function titlesFor(
return (localeIndex && titles.byLocale[localeIndex]) || titles.base
}
const containerLabels = [
['tip', 'tipLabel', 'TIP'],
['info', 'infoLabel', 'INFO'],
['warning', 'warningLabel', 'WARNING'],
['danger', 'dangerLabel', 'DANGER'],
['details', 'detailsLabel', 'Details'],
['note', 'noteLabel', 'NOTE'],
['important', 'importantLabel', 'IMPORTANT'],
['caution', 'cautionLabel', 'CAUTION']
] as const
function resolveTitlesByLocale(
options?: ContainerOptions,
locales?: Record<string, MarkdownLocaleOptions | undefined>
@ -185,8 +187,6 @@ function createCodeGroupOpenRender(md: MarkdownItAsync): RenderRule {
}
}
const alertMarkerRE = /^\[!([\w-]+)\]([^\n\r]*)/
export const gitHubAlertsPlugin = (
md: MarkdownItAsync,
options?: ContainerOptions,

@ -26,6 +26,18 @@ import { processIncludes } from './utils/processIncludes'
const debug = createDebug('vitepress:md')
const cache = new LRUCache<string, MarkdownCompileResult>({ max: 1024 })
const scriptRE = /<\/script>/
const scriptLangTsRE = /<\s*script[^>]*\blang=['"]ts['"][^>]*/
const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
let __pages: string[] = []
let __dynamicRoutes = new Map<string, [string, string]>()
let __rewrites = new Map<string, string>()
let __ts: number
export interface MarkdownCompileResult {
vueSrc: string
pageData: PageData
@ -43,11 +55,6 @@ export function clearCache(relativePath?: string) {
cache.find((_, key) => key.endsWith(relativePath!) && cache.delete(key))
}
let __pages: string[] = []
let __dynamicRoutes = new Map<string, [string, string]>()
let __rewrites = new Map<string, string>()
let __ts: number
function normalizeDriveLetter(file: string) {
return file.replace(/^[a-z]:/i, (drive) => drive.toLowerCase())
}
@ -280,13 +287,6 @@ export async function createMarkdownToVueRenderFn(
}
}
const scriptRE = /<\/script>/
const scriptLangTsRE = /<\s*script[^>]*\blang=['"]ts['"][^>]*/
const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
function injectPageDataCode(tags: string[], data: PageData) {
const code = `\nexport const __pageData = JSON.parse(${JSON.stringify(
JSON.stringify(data)

@ -15,6 +15,9 @@ const debug = createDebug('vitepress:local-search')
const LOCAL_SEARCH_INDEX_ID = '@localSearchIndex'
const LOCAL_SEARCH_INDEX_REQUEST_PATH = '/' + LOCAL_SEARCH_INDEX_ID
const headingRegex = /<h(\d*).*?>(.*?<a.*? href="#.*?".*?>.*?<\/a>)<\/h\1>/gi
const headingContentRegex = /(.*)<a.*? href="#(.*?)".*?>.*?<\/a>/i
interface IndexObject {
id: string
text: string
@ -248,9 +251,6 @@ export async function localSearchPlugin(
}
}
const headingRegex = /<h(\d*).*?>(.*?<a.*? href="#.*?".*?>.*?<\/a>)<\/h\1>/gi
const headingContentRegex = /(.*)<a.*? href="#(.*?)".*?>.*?<\/a>/i
/**
* Splits HTML into sections based on headings
*/

@ -14,19 +14,6 @@ const loaderMatch = /\.data\.m?(j|t)s($|\?)/
let server: ViteDevServer
export interface LoaderModule<T = any> {
watch?: string[] | string
load: (watchedFiles: string[]) => Awaitable<T>
options?: { globOptions?: GlobOptions }
}
/**
* Helper for defining loaders with type inference
*/
export function defineLoader<T>(loader: LoaderModule<T>): LoaderModule<T> {
return loader
}
// Map from loader module id to its module info
const idToLoaderModulesMap: Record<
string,
@ -45,6 +32,19 @@ let idToPendingPromiseMap: Record<string, Promise<string> | undefined> =
Object.create(null)
let isBuild = false
export interface LoaderModule<T = any> {
watch?: string[] | string
load: (watchedFiles: string[]) => Awaitable<T>
options?: { globOptions?: GlobOptions }
}
/**
* Helper for defining loaders with type inference
*/
export function defineLoader<T>(loader: LoaderModule<T>): LoaderModule<T> {
return loader
}
export const staticDataPlugin: Plugin = {
name: 'vitepress:data',

@ -11,6 +11,49 @@ export type CLIShortcut = {
): Awaitable<void>
}
const SHORTCUTS: CLIShortcut[] = [
{
key: 'r',
description: 'restart the server',
async action(server, restartServer) {
server.config.logger.info(c.green(`restarting server...\n`), {
clear: true,
timestamp: true
})
await restartServer()
}
},
{
key: 'u',
description: 'show server url',
action(server) {
server.config.logger.info('')
server.printUrls()
}
},
{
key: 'o',
description: 'open in browser',
action(server) {
server.openBrowser()
}
},
{
key: 'c',
description: 'clear console',
action(server) {
server.config.logger.clearScreen('error')
}
},
{
key: 'q',
description: 'quit',
async action(server) {
await server.close().finally(() => process.exit())
}
}
]
export function bindShortcuts(
server: ViteDevServer,
restartServer: () => Promise<void>
@ -69,46 +112,3 @@ export function bindShortcuts(
process.stdin.setRawMode(false)
})
}
const SHORTCUTS: CLIShortcut[] = [
{
key: 'r',
description: 'restart the server',
async action(server, restartServer) {
server.config.logger.info(c.green(`restarting server...\n`), {
clear: true,
timestamp: true
})
await restartServer()
}
},
{
key: 'u',
description: 'show server url',
action(server) {
server.config.logger.info('')
server.printUrls()
}
},
{
key: 'o',
description: 'open in browser',
action(server) {
server.openBrowser()
}
},
{
key: 'c',
description: 'clear console',
action(server) {
server.config.logger.clearScreen('error')
}
},
{
key: 'q',
description: 'quit',
async action(server) {
await server.close().finally(() => process.exit())
}
}
]

@ -1,3 +1,23 @@
/*
export function deserializeFunctions(value: any): any {
if (Array.isArray(value)) {
return value.map(deserializeFunctions)
} else if (typeof value === 'object' && value !== null) {
return Object.keys(value).reduce((acc, key) => {
acc[key] = deserializeFunctions(value[key])
return acc
}, {} as any)
} else if (typeof value === 'string' && value.startsWith('_vp-fn_')) {
return new Function(`return ${value.slice(7)}`)()
} else {
return value
}
}
*/
export const deserializeFunctions =
'function deserializeFunctions(r){return Array.isArray(r)?r.map(deserializeFunctions):typeof r=="object"&&r!==null?Object.keys(r).reduce((t,n)=>(t[n]=deserializeFunctions(r[n]),t),{}):typeof r=="string"&&r.startsWith("_vp-fn_")?new Function(`return ${r.slice(7)}`)():r}'
export function serializeFunctions(value: any, key?: string): any {
if (Array.isArray(value)) {
return value.map((v) => serializeFunctions(v))
@ -20,23 +40,3 @@ export function serializeFunctions(value: any, key?: string): any {
return value
}
}
/*
export function deserializeFunctions(value: any): any {
if (Array.isArray(value)) {
return value.map(deserializeFunctions)
} else if (typeof value === 'object' && value !== null) {
return Object.keys(value).reduce((acc, key) => {
acc[key] = deserializeFunctions(value[key])
return acc
}, {} as any)
} else if (typeof value === 'string' && value.startsWith('_vp-fn_')) {
return new Function(`return ${value.slice(7)}`)()
} else {
return value
}
}
*/
export const deserializeFunctions =
'function deserializeFunctions(r){return Array.isArray(r)?r.map(deserializeFunctions):typeof r=="object"&&r!==null?Object.keys(r).reduce((t,n)=>(t[n]=deserializeFunctions(r[n]),t),{}):typeof r=="string"&&r.startsWith("_vp-fn_")?new Function(`return ${r.slice(7)}`)():r}'

@ -37,6 +37,14 @@ const HASH_WITHOUT_FRAGMENT_RE = /#.*?(?=:~:|$)/
const HASH_OR_QUERY_RE = /[?#].*$/
const INDEX_OR_EXT_RE = /(?:(^|\/)index)?(?:\.(?:md|html))?$/
// https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g
const DRIVE_LETTER_REGEX = /^[a-z]:/i
const KNOWN_EXTENSIONS = new Set()
const shellLangs = ['shellscript', 'shell', 'bash', 'sh', 'zsh']
export const inBrowser = typeof document !== 'undefined'
export const notFoundPageData: PageData = {
@ -217,11 +225,6 @@ export function mergeHead(...headArrays: HeadConfig[][]): HeadConfig[] {
return merged
}
// https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g
const DRIVE_LETTER_REGEX = /^[a-z]:/i
export function sanitizeFileName(name: string): string {
const match = DRIVE_LETTER_REGEX.exec(name)
const driveLetter = match ? match[0] : ''
@ -239,8 +242,6 @@ export function slash(p: string): string {
return p.replace(/\\/g, '/')
}
const KNOWN_EXTENSIONS = new Set()
export function treatAsHtml(filename: string): boolean {
if (KNOWN_EXTENSIONS.size === 0) {
const extraExts =
@ -368,7 +369,6 @@ export function isObject(value: unknown): value is ObjectType {
return Object.prototype.toString.call(value) === '[object Object]'
}
const shellLangs = ['shellscript', 'shell', 'bash', 'sh', 'zsh']
export function isShell(lang: string): boolean {
return shellLangs.includes(lang)
}

Loading…
Cancel
Save