adjust implementation

pull/4660/head
Divyansh Singh 5 months ago
parent d5b15634e7
commit 87048f5e3f

@ -120,7 +120,7 @@ export default defineConfig({
firebase: 'logos:firebase' firebase: 'logos:firebase'
} }
}), }),
process.env.NODE_ENV === 'production' && !!process.env.NETLIFY &&
llmstxt({ llmstxt({
workDir: 'en', workDir: 'en',
ignoreFiles: ['index.md'] ignoreFiles: ['index.md']

@ -33,7 +33,7 @@ export async function renderPage(
usedIcons: Set<string> usedIcons: Set<string>
) { ) {
const routePath = `/${page.replace(/\.md$/, '')}` const routePath = `/${page.replace(/\.md$/, '')}`
const siteData = resolveSiteDataByRoute(config.site, routePath) const siteData = resolveSiteDataByRoute(config.site, page)
// render page // render page
const context = await render(routePath) const context = await render(routePath)

@ -1,4 +1,9 @@
import type { HeadConfig, PageData, SiteData } from '../../types/shared' import type {
AdditionalConfig,
HeadConfig,
PageData,
SiteData
} from '../../types/shared'
export type { export type {
Awaitable, Awaitable,
@ -13,12 +18,16 @@ export type {
SiteData, SiteData,
SSGContext, SSGContext,
AdditionalConfig, AdditionalConfig,
AdditionalConfigDict AdditionalConfigDict,
AdditionalConfigLoader
} from '../../types/shared' } from '../../types/shared'
export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i
export const APPEARANCE_KEY = 'vitepress-theme-appearance' export const APPEARANCE_KEY = 'vitepress-theme-appearance'
export const VP_SOURCE_KEY = '[VP_SOURCE]'
const UnpackStackView = Symbol('stack-view:unpack')
const HASH_RE = /#.*$/ const HASH_RE = /#.*$/
const HASH_OR_QUERY_RE = /[?#].*$/ const HASH_OR_QUERY_RE = /[?#].*$/
const INDEX_OR_EXT_RE = /(?:(^|\/)index)?\.(?:md|html)$/ const INDEX_OR_EXT_RE = /(?:(^|\/)index)?\.(?:md|html)$/
@ -98,15 +107,18 @@ export function resolveSiteDataByRoute(
const localeIndex = getLocaleForPath(siteData, relativePath) const localeIndex = getLocaleForPath(siteData, relativePath)
const { label, link, ...localeConfig } = siteData.locales[localeIndex] ?? {} const { label, link, ...localeConfig } = siteData.locales[localeIndex] ?? {}
Object.assign(localeConfig, { localeIndex }) Object.assign(localeConfig, { localeIndex })
const additionalConfigs = resolveAdditionalConfig(siteData, relativePath) const additionalConfigs = resolveAdditionalConfig(siteData, relativePath)
if (inBrowser && (import.meta as any).env?.DEV) { if (inBrowser && (import.meta as any).env?.DEV) {
;(localeConfig as any)[VP_SOURCE_KEY] = `locale config (${localeIndex})` ;(localeConfig as any)[VP_SOURCE_KEY] = `locale config (${localeIndex})`
reportConfigLayers(relativePath, [ reportConfigLayers(relativePath, [
...additionalConfigs, ...additionalConfigs,
localeConfig as SiteData, localeConfig,
siteData siteData
]) ])
} }
const topLayer = { const topLayer = {
head: mergeHead( head: mergeHead(
siteData.head ?? [], siteData.head ?? [],
@ -114,6 +126,7 @@ export function resolveSiteDataByRoute(
...additionalConfigs.map((data) => data?.head ?? []).reverse() ...additionalConfigs.map((data) => data?.head ?? []).reverse()
) )
} as SiteData } as SiteData
return stackView<SiteData>( return stackView<SiteData>(
topLayer, topLayer,
...additionalConfigs, ...additionalConfigs,
@ -256,33 +269,36 @@ export function escapeHtml(str: string): string {
.replace(/&(?![\w#]+;)/g, '&amp;') .replace(/&(?![\w#]+;)/g, '&amp;')
} }
export function resolveAdditionalConfig(site: SiteData, path: string) { function resolveAdditionalConfig(
if (!path.startsWith('/')) path = `/${path}` { additionalConfig }: SiteData,
const additionalConfig = site.additionalConfig path: string
): AdditionalConfig[] {
if (additionalConfig === undefined) return [] if (additionalConfig === undefined) return []
else if (typeof additionalConfig === 'function') if (typeof additionalConfig === 'function') return additionalConfig(path)
return additionalConfig(path) as SiteData[]
const configs: SiteData[] = [] const configs: AdditionalConfig[] = []
const segments = path.split('/').slice(1, -1) const segments = path.split('/').slice(0, -1) // remove file name
while (segments.length) { while (segments.length) {
const key = `/${segments.join('/')}/` const key = `/${segments.join('/')}/`
if (key in additionalConfig) configs.push(additionalConfig[key] as SiteData) configs.push(additionalConfig[key])
segments.pop() segments.pop()
} }
if ('/' in additionalConfig) configs.push(additionalConfig['/'] as SiteData)
return configs
}
export const VP_SOURCE_KEY = '[VP_SOURCE]' configs.push(additionalConfig['/'])
return configs.filter((config) => config !== undefined)
}
function reportConfigLayers(path: string, layers: SiteData[]) { // This helps users to understand which configuration files are active
// This helps users to understand which configuration files are active function reportConfigLayers(path: string, layers: Partial<SiteData>[]) {
const summaryTitle = `Config Layers for ${path}:` const summaryTitle = `Config Layers for ${path}:`
const summary = layers.map((c, i, arr) => { const summary = layers.map((c, i, arr) => {
const n = i + 1 const n = i + 1
if (n === arr.length) return `${n}. .vitepress/config (root)` if (n === arr.length) return `${n}. .vitepress/config (root)`
return `${n}. ${(c as any)?.[VP_SOURCE_KEY] ?? '(Unknown Source)'}` return `${n}. ${(c as any)?.[VP_SOURCE_KEY] ?? '(Unknown Source)'}`
}) })
console.debug( console.debug(
[summaryTitle, ''.padEnd(summaryTitle.length, '='), ...summary].join('\n') [summaryTitle, ''.padEnd(summaryTitle.length, '='), ...summary].join('\n')
) )
@ -293,53 +309,45 @@ function reportConfigLayers(path: string, layers: SiteData[]) {
* Returns a readonly proxy behaving like a merged object of the input objects. * Returns a readonly proxy behaving like a merged object of the input objects.
* Layers are merged in descending precedence, i.e. earlier layer is on top. * Layers are merged in descending precedence, i.e. earlier layer is on top.
*/ */
export function stackView<T extends object>(...layers: Partial<T>[]): T { export function stackView<T extends ObjectType>(..._layers: Partial<T>[]): T {
layers = layers.filter((layer) => layer !== undefined) const layers = _layers.filter((layer) => isObject(layer))
if (!isObject(layers[0])) return layers[0] as T if (layers.length <= 1) return _layers[0] as T
layers = layers.filter(isObject)
if (layers.length <= 1) return layers[0] as T const allKeys = new Set(layers.flatMap((layer) => Reflect.ownKeys(layer)))
return new Proxy( const allKeysArray = [...allKeys]
{},
{ return new Proxy({} as T, {
get(_, key) { get(_, prop) {
return key === UnpackStackView if (prop === UnpackStackView) return layers
? layers return stackView(
: stackView(...layers.map((layer) => (layer as any)?.[key])) ...layers
}, .map((layer) => layer[prop])
set(_, key, value) { .filter((v): v is NonNullable<T[string | symbol]> => v !== undefined)
throw new Error('StackView is read-only and cannot be mutated.') )
}, },
has(_, key) { set() {
for (const layer of layers) { throw new Error('StackView is read-only and cannot be mutated.')
if (key in layer) return true },
} has(_, prop) {
return false return allKeys.has(prop)
}, },
ownKeys(_) { ownKeys() {
const keys = new Set<string>() return allKeysArray
for (const layer of layers) { },
for (const key of Object.keys(layer)) { getOwnPropertyDescriptor(_, prop) {
keys.add(key) for (const layer of layers) {
} const descriptor = Object.getOwnPropertyDescriptor(layer, prop)
} if (descriptor) return descriptor
return Array.from(keys)
},
getOwnPropertyDescriptor(_, key) {
for (const layer of layers) {
if (key in layer) {
return Object.getOwnPropertyDescriptor(layer, key)
}
}
} }
} }
) as T })
} }
const UnpackStackView = Symbol('stack-view:unpack')
stackView.unpack = function <T>(obj: T): T[] | undefined { stackView.unpack = function <T>(obj: T): T[] | undefined {
return (obj as any)?.[UnpackStackView] return (obj as any)?.[UnpackStackView]
} }
export function isObject(value: unknown): value is Record<string, any> { type ObjectType = Record<PropertyKey, any>
export function isObject(value: unknown): value is ObjectType {
return Object.prototype.toString.call(value) === '[object Object]' return Object.prototype.toString.call(value) === '[object Object]'
} }

2
types/shared.d.ts vendored

@ -191,7 +191,7 @@ export type AdditionalConfigDict<ThemeConfig = any> = Record<
> >
export type AdditionalConfigLoader<ThemeConfig = any> = ( export type AdditionalConfigLoader<ThemeConfig = any> = (
path: string relativePath: string
) => AdditionalConfig<ThemeConfig>[] ) => AdditionalConfig<ThemeConfig>[]
// Manually declaring all properties as rollup-plugin-dts // Manually declaring all properties as rollup-plugin-dts

Loading…
Cancel
Save