Initial rearrangment of vuetom site source
This commit is contained in:
2
packages/vuetom/support/constant.ts
Normal file
2
packages/vuetom/support/constant.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const defaultLang = 'zh-CN'
|
||||
export const PREFERRED_LANG_KEY = 'vuetom_lang'
|
||||
23
packages/vuetom/support/lang.ts
Normal file
23
packages/vuetom/support/lang.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vitepress'
|
||||
import { defaultLang } from './constant.js'
|
||||
|
||||
export const useLang = () => {
|
||||
const route = useRoute()
|
||||
|
||||
return computed(() => {
|
||||
// the first part of the first slash
|
||||
const path = route.data?.relativePath
|
||||
let lang
|
||||
|
||||
if (path?.includes('/')) {
|
||||
lang = path.split('/').shift()
|
||||
} else {
|
||||
lang = defaultLang
|
||||
}
|
||||
|
||||
return lang
|
||||
})
|
||||
}
|
||||
|
||||
export default {}
|
||||
137
packages/vuetom/support/pages.ts
Normal file
137
packages/vuetom/support/pages.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import {
|
||||
reactive, ref, markRaw, shallowRef
|
||||
} from 'vue'
|
||||
import { inBrowser, withBase, useData } from 'vitepress'
|
||||
|
||||
// @ts-ignore
|
||||
import siteData from '@siteData'
|
||||
|
||||
export const siteDataRef = shallowRef(siteData)
|
||||
|
||||
const routes: any = ref([])
|
||||
|
||||
const NotFound = () => '404 Not Found'
|
||||
|
||||
const notFoundPageData = {
|
||||
relativePath: '',
|
||||
title: '404',
|
||||
description: 'Not Found',
|
||||
headers: [],
|
||||
frontmatter: {},
|
||||
lastUpdated: 0
|
||||
}
|
||||
|
||||
const getDefaultRoute = () => ({
|
||||
path: '/',
|
||||
component: null,
|
||||
data: notFoundPageData
|
||||
})
|
||||
|
||||
const createRouterRoutes = (
|
||||
loadPageModule: Function,
|
||||
fallbackComponent: any
|
||||
) => {
|
||||
// const router = useRouter()
|
||||
const { theme } = useData()
|
||||
const { pages } = theme.value
|
||||
let latestPendingPath = ''
|
||||
async function loadPage(
|
||||
href = '/index',
|
||||
scrollPosition = 0,
|
||||
isRetry = false
|
||||
) {
|
||||
const route = reactive(getDefaultRoute())
|
||||
const pendingPath = `/posts${href}`
|
||||
try {
|
||||
let page = loadPageModule(pendingPath)
|
||||
if ('then' in page && typeof page.then === 'function') {
|
||||
page = await page
|
||||
}
|
||||
const { default: comp, __pageData } = page
|
||||
if (!comp) {
|
||||
throw new Error(`Invalid route component: ${comp}`)
|
||||
}
|
||||
route.path = inBrowser ? pendingPath : pendingPath
|
||||
route.component = markRaw(comp)
|
||||
route.data = markRaw(__pageData)
|
||||
} catch (err) {
|
||||
// @ts-ignore
|
||||
if (!/fetch/.test(err.message) && !/^\/404(\.html|\/)?$/.test(href)) {
|
||||
console.error(err)
|
||||
}
|
||||
if (!isRetry) {
|
||||
try {
|
||||
const res = await fetch(`${siteDataRef.value.base}hashmap.json`)
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
window.__VP_HASH_MAP__ = await res.json()
|
||||
await loadPage(href, scrollPosition, true)
|
||||
return
|
||||
} catch (e) {}
|
||||
}
|
||||
if (latestPendingPath === pendingPath) {
|
||||
latestPendingPath = ''
|
||||
route.path = inBrowser ? pendingPath : withBase(pendingPath)
|
||||
route.component = fallbackComponent ? markRaw(fallbackComponent) : null
|
||||
route.data = notFoundPageData
|
||||
}
|
||||
}
|
||||
return route
|
||||
}
|
||||
pages.forEach(async (p: { link: string }) => {
|
||||
const r = await loadPage(p.link)
|
||||
routes.value.push(r)
|
||||
})
|
||||
return {
|
||||
routes: routes.value
|
||||
}
|
||||
}
|
||||
|
||||
const getRoutes = () => {
|
||||
let isInitialPageLoad = inBrowser
|
||||
let initialPath = ''
|
||||
return createRouterRoutes((path: string) => {
|
||||
let pageFilePath = pathToFile(path)
|
||||
if (isInitialPageLoad) {
|
||||
initialPath = pageFilePath
|
||||
}
|
||||
if (isInitialPageLoad || initialPath === pageFilePath) {
|
||||
pageFilePath = pageFilePath.replace(/\.js$/, '.lean.js')
|
||||
}
|
||||
if (inBrowser) {
|
||||
isInitialPageLoad = false
|
||||
}
|
||||
return import(/* @vite-ignore */ pageFilePath)
|
||||
}, NotFound)
|
||||
}
|
||||
|
||||
function pathToFile(path: string) {
|
||||
let pagePath = path.replace(/\.html$/, '')
|
||||
pagePath = decodeURIComponent(pagePath)
|
||||
if (pagePath.endsWith('/')) {
|
||||
pagePath += 'index'
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (import.meta.env.DEV) {
|
||||
pagePath += `.md?t=${Date.now()}`
|
||||
} else {
|
||||
// /foo/bar.html -> ./foo_bar.md
|
||||
if (inBrowser) {
|
||||
// @ts-ignore
|
||||
const base = import.meta.env.BASE_URL
|
||||
pagePath = `${
|
||||
pagePath.slice(base.length - 1).replace(/\//g, '_') || 'index'
|
||||
}.md`
|
||||
const pageHash = __VP_HASH_MAP__[`posts_${pagePath.toLowerCase()}`]
|
||||
pagePath = `${base}assets/posts_${pagePath}.${pageHash}.js`
|
||||
} else {
|
||||
// ssr
|
||||
pagePath = `./${pagePath.slice(1).replace(/\//g, '_')}.md.js`
|
||||
}
|
||||
}
|
||||
return pagePath
|
||||
}
|
||||
|
||||
export { getRoutes }
|
||||
|
||||
export default {}
|
||||
68
packages/vuetom/support/utils.ts
Normal file
68
packages/vuetom/support/utils.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
export const hashRE = /#.*$/
|
||||
export const extRE = /(index)?\.(md|html)$/
|
||||
export const endingSlashRE = /\/$/
|
||||
export const outboundRE = /^[a-z]+:/i
|
||||
export function isNullish(value: any) {
|
||||
return value === null || value === undefined
|
||||
}
|
||||
export function isArray(value: any) {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
export function isExternal(path: string) {
|
||||
return outboundRE.test(path)
|
||||
}
|
||||
export function isActive(route: any, path: string) {
|
||||
if (path === undefined) {
|
||||
return false
|
||||
}
|
||||
const routePath = normalize(`/${route.data.relativePath}`)
|
||||
const pagePath = normalize(path)
|
||||
|
||||
return routePath === pagePath
|
||||
}
|
||||
export function normalize(path: string) {
|
||||
return decodeURI(path).replace(hashRE, '').replace(extRE, '')
|
||||
}
|
||||
export function joinUrl(base: string, path: string) {
|
||||
const baseEndsWithSlash = base.endsWith('/')
|
||||
const pathStartsWithSlash = path.startsWith('/')
|
||||
if (baseEndsWithSlash && pathStartsWithSlash) {
|
||||
return base.slice(0, -1) + path
|
||||
}
|
||||
if (!baseEndsWithSlash && !pathStartsWithSlash) {
|
||||
return `${base}/${path}`
|
||||
}
|
||||
|
||||
return base + path
|
||||
}
|
||||
|
||||
/**
|
||||
* get the path without filename (the last segment). for example, if the given
|
||||
* path is `/guide/getting-started.html`, this method will return `/guide/`.
|
||||
* Always with a trailing slash.
|
||||
*/
|
||||
export function getPathDirName(path: string) {
|
||||
const segments = path.split('/')
|
||||
if (segments[segments.length - 1]) {
|
||||
segments.pop()
|
||||
}
|
||||
|
||||
return ensureEndingSlash(segments.join('/'))
|
||||
}
|
||||
export function ensureSlash(path: string) {
|
||||
return ensureEndingSlash(ensureStartingSlash(path))
|
||||
}
|
||||
export function ensureStartingSlash(path: string) {
|
||||
return /^\//.test(path) ? path : `/${path}`
|
||||
}
|
||||
export function ensureEndingSlash(path: string) {
|
||||
return /(\.html|\/)$/.test(path) ? path : `${path}/`
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove `.md` or `.html` extention from the given path. It also converts
|
||||
* `index` to slush.
|
||||
*/
|
||||
export function removeExtention(path: string) {
|
||||
return path.replace(/(index)?(\.(md|html))?$/, '') || '/'
|
||||
}
|
||||
Reference in New Issue
Block a user