207 lines
7.3 KiB
TypeScript
207 lines
7.3 KiB
TypeScript
import { defineConfig } from 'vitepress'
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import type { HeadConfig, SiteConfig, TransformContext } from 'vitepress'
|
|
|
|
const siteUrl = process.env.SITE_URL || 'http://localhost:5173'
|
|
const siteName = '恭学教育集团'
|
|
const defaultOgImage = 'https://fenxiang-1304851894.cos.ap-nanjing.myqcloud.com/%E5%B0%81%E9%9D%A2.png'
|
|
const defaultKeywords = '天津专升本,专升本培训,恭学教育,天津专升本刷题,专升本网校,天津专升本教材,专升本辅导,天津专升本报名,专升本真题,天津专升本课程'
|
|
|
|
/**
|
|
* 将 Markdown 相对路径转换为站点 URL 路径
|
|
* - index.md -> /
|
|
* - books.md -> /books
|
|
* - knowledge/index.md -> /knowledge/
|
|
* - knowledge/sample-article.md -> /knowledge/sample-article
|
|
*/
|
|
function relativePathToUrl(relativePath: string): string {
|
|
let route = relativePath.replace(/\.md$/, '')
|
|
route = route.replace(/(^|\/)index$/, '')
|
|
if (!route.startsWith('/')) {
|
|
route = `/${route}`
|
|
}
|
|
return route || '/'
|
|
}
|
|
|
|
function formatDate(date: Date): string {
|
|
return date.toISOString().split('T')[0]
|
|
}
|
|
|
|
function getPageLastmod(relativePath: string): string | undefined {
|
|
const filePath = path.resolve('./docs', relativePath)
|
|
try {
|
|
const content = fs.readFileSync(filePath, 'utf-8')
|
|
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/)
|
|
if (fmMatch) {
|
|
const dateMatch = fmMatch[1].match(/^publishedAt:\s*(.+)$/m) || fmMatch[1].match(/^date:\s*(.+)$/m)
|
|
if (dateMatch) {
|
|
const d = new Date(dateMatch[1].trim())
|
|
if (!isNaN(d.getTime())) {
|
|
return formatDate(d)
|
|
}
|
|
}
|
|
}
|
|
const stat = fs.statSync(filePath)
|
|
return formatDate(stat.mtime)
|
|
} catch {
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
export default defineConfig({
|
|
cleanUrls: 'with-subfolders',
|
|
title: '恭学教育集团',
|
|
titleTemplate: false,
|
|
description: '恭学教育集团是天津专升本培训领军品牌,专注天津专升本7年,已服务21万+学员。提供专业刷题系统、在线网校、权威教材和一对一升学规划,真题覆盖率100%,助你轻松升本成功!',
|
|
lang: 'zh-CN',
|
|
head: [
|
|
['link', { rel: 'icon', href: '/logo.png' }],
|
|
['link', { rel: 'apple-touch-icon', href: '/logo.png' }],
|
|
['meta', { name: 'author', content: '恭学教育集团' }],
|
|
['meta', { property: 'og:site_name', content: siteName }],
|
|
['meta', { property: 'og:locale', content: 'zh_CN' }],
|
|
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
|
|
],
|
|
themeConfig: {
|
|
logo: '/logo.png',
|
|
nav: [],
|
|
outline: false,
|
|
socialLinks: [],
|
|
},
|
|
vite: {
|
|
resolve: {
|
|
alias: {
|
|
'@': '/docs/.vitepress',
|
|
},
|
|
},
|
|
plugins: [
|
|
{
|
|
name: 'knowledge-index-redirect',
|
|
configureServer(server) {
|
|
server.middlewares.use((req, res, next) => {
|
|
if (req.url === '/knowledge') {
|
|
res.statusCode = 302
|
|
res.setHeader('Location', '/knowledge/')
|
|
res.end()
|
|
return
|
|
}
|
|
next()
|
|
})
|
|
},
|
|
},
|
|
],
|
|
},
|
|
transformHead({ pageData, siteData }: TransformContext) {
|
|
const isNotFound = pageData.relativePath === '404.md'
|
|
const isArticle =
|
|
pageData.relativePath.startsWith('knowledge/') &&
|
|
pageData.relativePath !== 'knowledge/index.md' &&
|
|
pageData.frontmatter.publishedAt
|
|
|
|
const url = `${siteUrl}${relativePathToUrl(pageData.relativePath)}`
|
|
const title = pageData.title || siteName
|
|
const description = pageData.description || siteData.description || ''
|
|
const keywords = Array.isArray(pageData.frontmatter.keywords)
|
|
? pageData.frontmatter.keywords.join(',')
|
|
: defaultKeywords
|
|
const ogImage = pageData.frontmatter.coverImage || defaultOgImage
|
|
|
|
const tags: HeadConfig[] = [
|
|
['link', { rel: 'canonical', href: url }],
|
|
['meta', { name: 'robots', content: isNotFound ? 'noindex, nofollow' : 'index, follow' }],
|
|
['meta', { name: 'keywords', content: keywords }],
|
|
['meta', { property: 'og:title', content: title }],
|
|
['meta', { property: 'og:description', content: description }],
|
|
['meta', { property: 'og:url', content: url }],
|
|
['meta', { property: 'og:image', content: ogImage }],
|
|
['meta', { property: 'og:type', content: isArticle ? 'article' : 'website' }],
|
|
['meta', { name: 'twitter:title', content: title }],
|
|
['meta', { name: 'twitter:description', content: description }],
|
|
['meta', { name: 'twitter:image', content: ogImage }],
|
|
]
|
|
|
|
const organizationLd = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Organization',
|
|
'@id': `${siteUrl}/#organization`,
|
|
name: siteName,
|
|
url: siteUrl,
|
|
logo: `${siteUrl}/logo.png`,
|
|
image: defaultOgImage,
|
|
description:
|
|
'恭学教育集团是天津专升本培训领军品牌,专注天津专升本培训、刷题系统、在线网校、权威教材和升学规划服务。',
|
|
sameAs: [],
|
|
}
|
|
|
|
const ldScripts: HeadConfig[] = [
|
|
['script', { type: 'application/ld+json' }, JSON.stringify(organizationLd)],
|
|
]
|
|
|
|
if (isArticle) {
|
|
const fm = pageData.frontmatter
|
|
const articleLd = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Article',
|
|
headline: title,
|
|
description,
|
|
url,
|
|
image: ogImage,
|
|
author: {
|
|
'@type': fm.author ? 'Person' : 'Organization',
|
|
name: fm.author || siteName,
|
|
},
|
|
publisher: {
|
|
'@id': `${siteUrl}/#organization`,
|
|
},
|
|
datePublished: fm.publishedAt,
|
|
dateModified: fm.publishedAt,
|
|
keywords: Array.isArray(fm.tags) ? fm.tags.join(',') : keywords,
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': url,
|
|
},
|
|
}
|
|
ldScripts.push(['script', { type: 'application/ld+json' }, JSON.stringify(articleLd)])
|
|
} else {
|
|
const webPageLd = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebPage',
|
|
name: title,
|
|
description,
|
|
url,
|
|
isPartOf: {
|
|
'@id': `${siteUrl}/#organization`,
|
|
},
|
|
}
|
|
ldScripts.push(['script', { type: 'application/ld+json' }, JSON.stringify(webPageLd)])
|
|
}
|
|
|
|
return [...tags, ...ldScripts]
|
|
},
|
|
buildEnd(siteConfig: SiteConfig) {
|
|
const pages = siteConfig.pages.filter((p) => p !== '404.md')
|
|
const urls = pages
|
|
.map((p) => ({
|
|
loc: `${siteUrl}${relativePathToUrl(p)}`,
|
|
lastmod: getPageLastmod(p),
|
|
changefreq: p === 'index.md' ? 'daily' : 'weekly',
|
|
priority: p === 'index.md' ? '1.0' : '0.8',
|
|
}))
|
|
.sort((a, b) => a.loc.localeCompare(b.loc))
|
|
|
|
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${urls
|
|
.map(
|
|
(u) =>
|
|
` <url>\n <loc>${u.loc}</loc>\n${u.lastmod ? ` <lastmod>${u.lastmod}</lastmod>\n` : ''} <changefreq>${u.changefreq}</changefreq>\n <priority>${u.priority}</priority>\n </url>`,
|
|
)
|
|
.join('\n')}\n</urlset>\n`
|
|
|
|
fs.mkdirSync(siteConfig.outDir, { recursive: true })
|
|
fs.writeFileSync(path.join(siteConfig.outDir, 'sitemap.xml'), sitemap)
|
|
|
|
const robots = `User-agent: *\nAllow: /\nDisallow: /404\n\nSitemap: ${siteUrl}/sitemap.xml\n`
|
|
fs.writeFileSync(path.join(siteConfig.outDir, 'robots.txt'), robots)
|
|
},
|
|
})
|