feat: tntegrated @nolebase/vitepress-plugin-meta for SEO and meta elements (#374)
部署文档 / build (push) Has been cancelled
Details
部署文档 / build (push) Has been cancelled
Details
Signed-off-by: Neko Ayaka <neko@ayaka.moe>pull/375/head
parent
63ee8492eb
commit
dadd466a6b
|
@ -1,20 +1,9 @@
|
||||||
{
|
{
|
||||||
"cSpell.words": [
|
|
||||||
"antfu",
|
|
||||||
"astro",
|
|
||||||
"Attributify",
|
|
||||||
"iconify",
|
|
||||||
"katex",
|
|
||||||
"pangu",
|
|
||||||
"pjts"
|
|
||||||
],
|
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit",
|
"source.fixAll.eslint": "explicit",
|
||||||
"source.organizeImports": "never"
|
"source.organizeImports": "never"
|
||||||
},
|
},
|
||||||
// Enable the ESlint flat config support
|
|
||||||
"eslint.experimental.useFlatConfig": true,
|
|
||||||
// The following is optional.
|
// The following is optional.
|
||||||
// It's better to put under project setting `.vscode/settings.json`
|
// It's better to put under project setting `.vscode/settings.json`
|
||||||
// to avoid conflicts with working with different eslint configs
|
// to avoid conflicts with working with different eslint configs
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
version: "0.2"
|
||||||
|
ignorePaths: []
|
||||||
|
dictionaryDefinitions: []
|
||||||
|
dictionaries: []
|
||||||
|
words:
|
||||||
|
- antfu
|
||||||
|
- astro
|
||||||
|
- Attributify
|
||||||
|
- iconify
|
||||||
|
- katex
|
||||||
|
- nolebase
|
||||||
|
- octicon
|
||||||
|
- pangu
|
||||||
|
- pjts
|
||||||
|
- unocss
|
||||||
|
- unplugin
|
||||||
|
- vitepress
|
||||||
|
ignoreWords: []
|
||||||
|
import: []
|
|
@ -16,6 +16,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^2.21.1",
|
"@antfu/eslint-config": "^2.21.1",
|
||||||
"@cloudflare/workers-types": "^4.20240620.0",
|
"@cloudflare/workers-types": "^4.20240620.0",
|
||||||
|
"@iconify-json/carbon": "^1.1.36",
|
||||||
|
"@iconify-json/icon-park-outline": "^1.1.15",
|
||||||
"@iconify-json/octicon": "^1.1.55",
|
"@iconify-json/octicon": "^1.1.55",
|
||||||
"@project-trans/suggestion-box": "^0.0.9",
|
"@project-trans/suggestion-box": "^0.0.9",
|
||||||
"@project-trans/vitepress-theme-project-trans": "workspace:*",
|
"@project-trans/vitepress-theme-project-trans": "workspace:*",
|
||||||
|
|
|
@ -41,9 +41,10 @@
|
||||||
"@antfu/eslint-config": "^2.21.1",
|
"@antfu/eslint-config": "^2.21.1",
|
||||||
"@cloudflare/workers-types": "^4.20240620.0",
|
"@cloudflare/workers-types": "^4.20240620.0",
|
||||||
"@iconify-json/octicon": "^1.1.55",
|
"@iconify-json/octicon": "^1.1.55",
|
||||||
"@nolebase/vitepress-plugin-enhanced-readabilities": "2.1.2",
|
"@nolebase/vitepress-plugin-enhanced-readabilities": "^2.1.2",
|
||||||
"@nolebase/vitepress-plugin-git-changelog": "2.1.2",
|
"@nolebase/vitepress-plugin-git-changelog": "^2.1.2",
|
||||||
"@nolebase/vitepress-plugin-highlight-targeted-heading": "2.1.2",
|
"@nolebase/vitepress-plugin-highlight-targeted-heading": "^2.1.2",
|
||||||
|
"@nolebase/vitepress-plugin-meta": "^2.2.1",
|
||||||
"@project-trans/suggestion-box": "^0.0.9",
|
"@project-trans/suggestion-box": "^0.0.9",
|
||||||
"@types/markdown-it": "^14.1.1",
|
"@types/markdown-it": "^14.1.1",
|
||||||
"@types/markdown-it-footnote": "^3.0.4",
|
"@types/markdown-it-footnote": "^3.0.4",
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { readFileSync, statSync } from 'node:fs'
|
||||||
import { dirname, join, resolve } from 'node:path'
|
import { dirname, join, resolve } from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import { GitChangelog } from '@nolebase/vitepress-plugin-git-changelog/vite'
|
import { GitChangelog } from '@nolebase/vitepress-plugin-git-changelog/vite'
|
||||||
|
import { transformHeadMeta } from '@nolebase/vitepress-plugin-meta'
|
||||||
import {
|
import {
|
||||||
MarkdownSectionWrapper,
|
MarkdownSectionWrapper,
|
||||||
PageHeaderTemplate,
|
PageHeaderTemplate,
|
||||||
|
@ -19,7 +20,7 @@ import { useThemeContext } from './utils/themeContext'
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
function genConfig() {
|
function genConfig() {
|
||||||
const themeConfig = useThemeContext()
|
const themeConfig = useThemeContext()
|
||||||
const { siteTitle, siteDescription, githubRepoLink, rootDir, nav }
|
const { siteTitle, githubRepoLink, nav }
|
||||||
= themeConfig
|
= themeConfig
|
||||||
return defineConfig({
|
return defineConfig({
|
||||||
lang: 'zh-CN',
|
lang: 'zh-CN',
|
||||||
|
@ -122,143 +123,12 @@ function genConfig() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
transformHead: (context) => {
|
transformHead: async (context) => {
|
||||||
const head = [...context.head] || []
|
let head = [...context.head]
|
||||||
|
|
||||||
const pageSourceFilePath = join(rootDir, context.pageData.filePath)
|
const returnedHead = await transformHeadMeta()(head, context)
|
||||||
const pageSourceFileStat = statSync(
|
if (typeof returnedHead !== 'undefined')
|
||||||
join(rootDir, context.pageData.filePath),
|
head = returnedHead
|
||||||
)
|
|
||||||
|
|
||||||
if (pageSourceFileStat.isDirectory()) {
|
|
||||||
head.push([
|
|
||||||
'meta',
|
|
||||||
{
|
|
||||||
property: 'og:title',
|
|
||||||
content: siteTitle,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
head.push([
|
|
||||||
'meta',
|
|
||||||
{
|
|
||||||
name: 'description',
|
|
||||||
content: siteDescription,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
return head
|
|
||||||
}
|
|
||||||
|
|
||||||
let pageSourceFileContent = readFileSync(pageSourceFilePath, {
|
|
||||||
encoding: 'utf-8',
|
|
||||||
})
|
|
||||||
|
|
||||||
// remove all frontmatter
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/---[\s\S]*?---/,
|
|
||||||
'',
|
|
||||||
)
|
|
||||||
|
|
||||||
// remove markdown heading markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/^(#+)\s+(.*)/gm,
|
|
||||||
' $2 ',
|
|
||||||
)
|
|
||||||
// remove markdown link markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/\[([^\]]+)\]\([^)]+\)/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
// remove markdown image markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/\!\[([^\]]+)\]\([^)]+\)/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
// remove markdown reference link markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(/\[.*]/gm, '')
|
|
||||||
// remove markdown bold markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/\*\*([^*]+)\*\*/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/__([^*]+)__/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
// remove markdown italic markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/\*([^*]+)\*/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/_([^*]+)_/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
// remove markdown code markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/`([^`]+)`/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
// remove markdown code block markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/```([^`]+)```/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
// remove markdown table header markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(/\|:?-+:?\|/gm, '')
|
|
||||||
// remove markdown table cell markup but keep the text content
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
/\|([^|]+)\|/gm,
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
|
|
||||||
// remove specific html tags completely
|
|
||||||
const tags = ['']
|
|
||||||
tags.forEach((tag) => {
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
new RegExp(`<${tag}[^>]*>[\\s\\S]*?<\\/${tag}>`, 'g'),
|
|
||||||
'',
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// remove specific html tags but keep the text content
|
|
||||||
const tagsToKeepContent = ['u', 'Containers', 'img', 'a']
|
|
||||||
tagsToKeepContent.forEach((tag) => {
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(
|
|
||||||
new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\\/${tag}>`, 'g'),
|
|
||||||
' $1 ',
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// remove all new lines (either \r, \n)
|
|
||||||
pageSourceFileContent = pageSourceFileContent.replace(/[\r|\n]/gm, '')
|
|
||||||
|
|
||||||
// calculate the first 200 characters of the page content
|
|
||||||
let pageContent = pageSourceFileContent.slice(0, 200)
|
|
||||||
// trim space
|
|
||||||
pageContent = pageContent.trim()
|
|
||||||
// if pageSourceFileContent is longer than 200 characters, add ellipsis
|
|
||||||
if (pageSourceFileContent.length > 100)
|
|
||||||
pageContent += '...'
|
|
||||||
|
|
||||||
if (context.pageData.frontmatter?.layout === 'home') {
|
|
||||||
pageContent
|
|
||||||
= context.pageData.frontmatter?.hero?.tagline ?? siteDescription
|
|
||||||
}
|
|
||||||
|
|
||||||
head.push(['meta', { name: 'description', content: pageContent }])
|
|
||||||
|
|
||||||
head.push(['meta', { property: 'og:title', content: context.title }])
|
|
||||||
|
|
||||||
head.push(['meta', { property: 'og:description', content: pageContent }])
|
|
||||||
|
|
||||||
head.push(['meta', { property: 'og:title', content: context.title }])
|
|
||||||
|
|
||||||
head.push([
|
|
||||||
'meta',
|
|
||||||
{ property: 'twitter:description', content: pageContent },
|
|
||||||
])
|
|
||||||
|
|
||||||
return head
|
return head
|
||||||
},
|
},
|
||||||
|
|
731
pnpm-lock.yaml
731
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue