|
1 | | -import { defineConfig } from 'vitepress' |
| 1 | +import { defineConfig, type HeadConfig } from 'vitepress' |
2 | 2 | import { version } from './_data/assets.json' |
3 | 3 |
|
| 4 | +const siteUrl = 'https://masscode.io' |
| 5 | +const siteTitle = 'massCode' |
4 | 6 | const description = 'Free, open-source developer workspace with code snippets, markdown notes, math notebook, and built-in dev tools.' |
5 | | -const ogDescription = 'Free, open-source developer workspace: code snippets, notes, math notebook, and 20+ dev tools. All data stored locally.' |
6 | | -const ogImage = 'https://masscode.io/og-image.png' |
7 | | -const ogTitle = 'massCode' |
8 | | -const ogUrl = 'https://masscode.io' |
| 7 | +const ogImage = `${siteUrl}/og-image.png` |
9 | 8 | const gsv = 'h-rU1tSutO83wOyvi4syrk_XTvgennlUPkL6fMmq5cI' |
10 | 9 |
|
| 10 | +function resolvePagePath(relativePath: string) { |
| 11 | + if (!relativePath || relativePath === 'index.md') |
| 12 | + return '/' |
| 13 | + |
| 14 | + if (relativePath.endsWith('/index.md')) |
| 15 | + return `/${relativePath.slice(0, -'index.md'.length)}` |
| 16 | + |
| 17 | + return `/${relativePath.replace(/\.md$/, '.html')}` |
| 18 | +} |
| 19 | + |
| 20 | +function resolvePageUrl(relativePath: string) { |
| 21 | + return new URL(resolvePagePath(relativePath), siteUrl).toString() |
| 22 | +} |
| 23 | + |
| 24 | +function buildSeoHead({ |
| 25 | + relativePath, |
| 26 | + pageTitle, |
| 27 | + pageDescription, |
| 28 | + isNotFound, |
| 29 | +}: { |
| 30 | + relativePath: string |
| 31 | + pageTitle: string |
| 32 | + pageDescription: string |
| 33 | + isNotFound?: boolean |
| 34 | +}): HeadConfig[] { |
| 35 | + if (isNotFound) |
| 36 | + return [['meta', { name: 'robots', content: 'noindex, nofollow' }]] |
| 37 | + |
| 38 | + const pageUrl = resolvePageUrl(relativePath) |
| 39 | + |
| 40 | + return [ |
| 41 | + ['link', { rel: 'canonical', href: pageUrl }], |
| 42 | + ['meta', { property: 'og:type', content: 'website' }], |
| 43 | + ['meta', { property: 'og:site_name', content: siteTitle }], |
| 44 | + ['meta', { property: 'og:title', content: pageTitle }], |
| 45 | + ['meta', { property: 'og:description', content: pageDescription }], |
| 46 | + ['meta', { property: 'og:url', content: pageUrl }], |
| 47 | + ['meta', { property: 'og:image', content: ogImage }], |
| 48 | + ['meta', { name: 'twitter:card', content: 'summary_large_image' }], |
| 49 | + ['meta', { name: 'twitter:title', content: pageTitle }], |
| 50 | + ['meta', { name: 'twitter:description', content: pageDescription }], |
| 51 | + ['meta', { name: 'twitter:image', content: ogImage }], |
| 52 | + ] |
| 53 | +} |
| 54 | + |
11 | 55 | export default defineConfig({ |
12 | | - title: 'massCode', |
| 56 | + title: siteTitle, |
13 | 57 | description, |
14 | 58 |
|
| 59 | + sitemap: { |
| 60 | + hostname: siteUrl, |
| 61 | + transformItems(items) { |
| 62 | + return items.filter(item => !item.url.endsWith('/404.html')) |
| 63 | + }, |
| 64 | + }, |
| 65 | + |
15 | 66 | head: [ |
16 | 67 | ['link', { rel: 'icon', type: 'image/png', href: '/logo-64w.png' }], |
17 | | - ['meta', { property: 'og:type', content: 'website' }], |
18 | | - ['meta', { property: 'og:title', content: ogTitle }], |
19 | | - ['meta', { property: 'og:image', content: ogImage }], |
20 | | - ['meta', { property: 'og:url', content: ogUrl }], |
21 | | - ['meta', { property: 'og:description', content: ogDescription }], |
22 | | - ['meta', { name: 'twitter:card', content: 'summary_large_image' }], |
23 | 68 | ['meta', { name: 'google-site-verification', content: gsv }], |
24 | 69 | ], |
25 | 70 |
|
| 71 | + transformHead({ pageData, title, description }) { |
| 72 | + return buildSeoHead({ |
| 73 | + relativePath: pageData.relativePath, |
| 74 | + pageTitle: title, |
| 75 | + pageDescription: description, |
| 76 | + isNotFound: pageData.isNotFound, |
| 77 | + }) |
| 78 | + }, |
| 79 | + |
26 | 80 | themeConfig: { |
27 | 81 | logo: '/logo-64w.png', |
28 | 82 |
|
|
0 commit comments