| import type { ExtendedRequest, ResolvedArticle } from '@/types' |
| import type { Response, NextFunction } from 'express' |
| import findPage from '@/frame/lib/find-page' |
| import { renderContent } from '@/content-render/index' |
| import Permalink from '@/frame/lib/permalink' |
|
|
| import { createLogger } from '@/observability/logger/index' |
|
|
| const logger = createLogger('middleware:resolve-recommended') |
|
|
| |
| |
| |
| function buildArticlePath(currentLanguage: string, articlePath: string, basePath?: string): string { |
| const pathPrefix = basePath ? `/${currentLanguage}/${basePath}` : `/${currentLanguage}` |
| const separator = articlePath.startsWith('/') ? '' : '/' |
| return `${pathPrefix}${separator}${articlePath}` |
| } |
|
|
| |
| |
| |
| function tryResolveArticlePath( |
| rawPath: string, |
| pageRelativePath: string | undefined, |
| req: ExtendedRequest, |
| ): any { |
| const { pages, redirects } = req.context! |
| const currentLanguage = req.context!.currentLanguage || 'en' |
|
|
| |
| if (!pages || !redirects) { |
| return undefined |
| } |
|
|
| |
| const contentRelativePath = buildArticlePath(currentLanguage, rawPath) |
| let foundPage = findPage(contentRelativePath, pages, redirects) |
|
|
| if (foundPage) { |
| return foundPage |
| } |
|
|
| |
| if (pageRelativePath) { |
| const pageDirPath = pageRelativePath.split('/').slice(0, -1).join('/') |
| const pageRelativeFullPath = buildArticlePath(currentLanguage, rawPath, pageDirPath) |
| foundPage = findPage(pageRelativeFullPath, pages, redirects) |
|
|
| if (foundPage) { |
| return foundPage |
| } |
| } |
|
|
| |
| if (!rawPath.endsWith('.md')) { |
| const pathWithExtension = `${rawPath}.md` |
|
|
| |
| const contentRelativePathWithExt = buildArticlePath(currentLanguage, pathWithExtension) |
| foundPage = findPage(contentRelativePathWithExt, pages, redirects) |
|
|
| if (foundPage) { |
| return foundPage |
| } |
|
|
| |
| if (pageRelativePath) { |
| const pageDirPath = pageRelativePath.split('/').slice(0, -1).join('/') |
| const pageRelativeFullPathWithExt = buildArticlePath( |
| currentLanguage, |
| pathWithExtension, |
| pageDirPath, |
| ) |
| foundPage = findPage(pageRelativeFullPathWithExt, pages, redirects) |
|
|
| if (foundPage) { |
| return foundPage |
| } |
| } |
| } |
|
|
| return foundPage |
| } |
|
|
| |
| |
| |
| function getPageHref(page: any): string { |
| if (page.relativePath) { |
| return Permalink.relativePathToSuffix(page.relativePath) |
| } |
| return '' |
| } |
|
|
| |
| |
| |
| async function resolveRecommended( |
| req: ExtendedRequest, |
| res: Response, |
| next: NextFunction, |
| ): Promise<void> { |
| try { |
| const page = req.context?.page |
| const rawRecommended = (page as any)?.rawRecommended |
| const spotlight = (page as any)?.spotlight |
| |
| |
| let articlePaths: string[] = [] |
|
|
| |
| if (rawRecommended && Array.isArray(rawRecommended)) { |
| articlePaths.push(...rawRecommended) |
| } |
|
|
| |
| if (articlePaths.length === 0 && spotlight && Array.isArray(spotlight)) { |
| const spotlightPaths = spotlight |
| .filter((item: any) => item && typeof item.article === 'string') |
| .map((item: any) => item.article) |
| articlePaths.push(...spotlightPaths) |
| } |
|
|
| if (articlePaths.length === 0) { |
| return next() |
| } |
|
|
| |
| articlePaths = [...new Set(articlePaths)] |
| const resolved: ResolvedArticle[] = [] |
|
|
| for (const rawPath of articlePaths) { |
| try { |
| const foundPage = tryResolveArticlePath(rawPath, page?.relativePath, req) |
|
|
| if ( |
| foundPage && |
| (!req.context?.currentVersion || |
| foundPage.applicableVersions.includes(req.context.currentVersion)) |
| ) { |
| const href = getPageHref(foundPage) |
| const category = foundPage.relativePath |
| ? foundPage.relativePath.split('/').slice(0, -1).filter(Boolean) |
| : [] |
|
|
| resolved.push({ |
| title: foundPage.title, |
| intro: await renderContent(foundPage.intro, req.context), |
| href, |
| category, |
| }) |
| } |
| } catch (error) { |
| logger.warn(`Failed to resolve recommended article: ${rawPath}`, { error }) |
| } |
| } |
|
|
| |
| if (page) { |
| ;(page as any).recommended = resolved |
| } |
| } catch (error) { |
| logger.error('Error in resolveRecommended middleware:', { error }) |
| } |
|
|
| next() |
| } |
|
|
| export default resolveRecommended |
|
|