mirror of https://github.com/YunYouJun/valaxy
feat(devtools): can dev devtools hmr with demo
This commit is contained in:
parent
2b65948a9a
commit
a1919d1462
|
@ -2,7 +2,7 @@
|
|||
"name": "valaxy-theme-custom",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.15.0",
|
||||
"packageManager": "pnpm@9.15.1",
|
||||
"author": {
|
||||
"email": "me@yunyoujun.cn",
|
||||
"name": "YunYouJun",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
VITE_VALAXY_DEVTOOLS_DEV=true
|
|
@ -6,8 +6,6 @@ import { addonBangumi } from 'valaxy-addon-bangumi'
|
|||
import { addonComponents } from 'valaxy-addon-components'
|
||||
import { addonLightGallery } from 'valaxy-addon-lightgallery'
|
||||
import { addonTest } from 'valaxy-addon-test'
|
||||
import { addonTwikoo } from 'valaxy-addon-twikoo'
|
||||
import { addonWaline } from 'valaxy-addon-waline'
|
||||
|
||||
// import { addonMeting } from 'valaxy-addon-meting'
|
||||
|
||||
|
@ -90,14 +88,15 @@ export default defineValaxyConfig<ThemeConfig>({
|
|||
addonComponents(),
|
||||
|
||||
// comments
|
||||
addonWaline({
|
||||
serverURL: 'https://waline.yunyoujun.cn',
|
||||
pageview: true,
|
||||
comment: true,
|
||||
}),
|
||||
addonTwikoo({
|
||||
envId: 'https://twikoo.vercel.app',
|
||||
}),
|
||||
// addonWaline({
|
||||
// serverURL: 'https://waline.yunyoujun.cn',
|
||||
// pageview: true,
|
||||
// comment: true,
|
||||
// }),
|
||||
|
||||
// addonTwikoo({
|
||||
// envId: 'https://twikoo.vercel.app',
|
||||
// }),
|
||||
|
||||
addonLightGallery(),
|
||||
// addonMeting({
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"valaxy": "link:../packages/valaxy",
|
||||
"valaxy-addon-algolia": "link:../packages/valaxy-addon-algolia",
|
||||
"valaxy-addon-components": "workspace:*",
|
||||
"valaxy-addon-git-log": "^0.1.1",
|
||||
"valaxy-addon-git-log": "^0.2.0",
|
||||
"valaxy-theme-press": "link:../packages/valaxy-theme-press"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"type": "module",
|
||||
"version": "0.22.4",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.15.0",
|
||||
"packageManager": "pnpm@9.15.1",
|
||||
"description": "📄 Vite & Vue powered static blog generator.",
|
||||
"author": {
|
||||
"email": "me@yunyoujun.cn",
|
||||
|
@ -95,7 +95,6 @@
|
|||
"@types/resolve": "^1.20.6",
|
||||
"bumpp": "^9.9.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"decap-cms-app": "^3.4.0",
|
||||
"eslint": "^9.17.0",
|
||||
"https-localhost": "^4.7.1",
|
||||
"husky": "^9.1.7",
|
||||
|
|
|
@ -11,3 +11,12 @@ pnpm dev
|
|||
# in root
|
||||
pnpm devtools
|
||||
```
|
||||
|
||||
```bash
|
||||
# 启动 demo,查看 devtools(代理至开发 devtools 的端口以获取热更新)
|
||||
pnpm demo:vite
|
||||
```
|
||||
|
||||
```bash [.env]
|
||||
VITE_VALAXY_DEVTOOLS_DEV=true
|
||||
```
|
||||
|
|
|
@ -8,9 +8,12 @@ export default defineBuildConfig({
|
|||
declaration: true,
|
||||
externals: [
|
||||
// in valaxy
|
||||
'valaxy',
|
||||
'vite',
|
||||
'gray-matter',
|
||||
'fs-extra',
|
||||
'fast-glob',
|
||||
'consola',
|
||||
],
|
||||
rollup: {
|
||||
dts: {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"build": "rimraf dist && run-s build:*",
|
||||
"build:client": "vite build src/client",
|
||||
"build:node": "unbuild",
|
||||
"dev": "npm run stub && npm run dev:client",
|
||||
"dev": "npm run dev:client",
|
||||
"dev:client": "vite dev src/client --port 5001",
|
||||
"watch:client": "vite build src/client --watch",
|
||||
"stub": "unbuild --stub",
|
||||
|
@ -30,21 +30,26 @@
|
|||
"@rollup/pluginutils": "^5.1.4",
|
||||
"axios": "^1.7.9",
|
||||
"body-parser": "^2.0.2",
|
||||
"cors": "^2.8.5",
|
||||
"http-proxy-middleware": "^3.0.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"picocolors": "^1.1.1",
|
||||
"sirv": "^3.0.0"
|
||||
"sirv": "^3.0.0",
|
||||
"vite-dev-rpc": "^0.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@advjs/gui": "0.0.7-beta.1",
|
||||
"@iconify-json/ri": "catalog:",
|
||||
"@types/body-parser": "^1.19.5",
|
||||
"@types/splitpanes": "^2.2.6",
|
||||
"@types/wicg-file-system-access": "^2023.10.5",
|
||||
"gray-matter": "^4.0.3",
|
||||
"splitpanes": "^3.1.5",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"unplugin-vue-router": "^0.10.9",
|
||||
"vite": "catalog:"
|
||||
"vite": "catalog:",
|
||||
"vue-i18n": "^10.0.5",
|
||||
"zod": "^3.24.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue'
|
||||
import VDHeader from './components/VDHeader.vue'
|
||||
import { initDevtoolsClient } from './utils'
|
||||
|
||||
onMounted(() => {
|
||||
initDevtoolsClient()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="h-full" flex="~ col" text="gray-700 dark:gray-200">
|
||||
<VDHeader />
|
||||
<!-- <RouterLink to="/about">About</RouterLink> -->
|
||||
|
||||
<div style="height: calc(100% - 32px)" overflow="auto">
|
||||
<RouterView />
|
||||
</div>
|
||||
</main>
|
||||
<ValaxyDevtools />
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
tag?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="tag || 'button'"
|
||||
class="bg-white dark:bg-gray-900 inline-flex justify-center items-center size-8 hover:bg-gray-200 dark:hover:bg-gray-800"
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
|
@ -0,0 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { toggleDark } from '../composables/dark'
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MenuBarBtn :title="t('button.toggle_dark')" @click="toggleDark()">
|
||||
<div i="carbon-sun dark:carbon-moon" />
|
||||
</MenuBarBtn>
|
||||
</template>
|
|
@ -47,11 +47,13 @@ const routeMenus = [
|
|||
|
||||
<div flex="1" />
|
||||
|
||||
<a
|
||||
<SelectRootDir />
|
||||
<ToggleDark />
|
||||
<MenuBarBtn
|
||||
tag="a"
|
||||
href="https://valaxy.site" target="_blank"
|
||||
class="bg-white dark:bg-gray-900 inline-flex justify-center items-center w-8 h-8 hover:bg-gray-200"
|
||||
>
|
||||
<div i-ri-book-line />
|
||||
</a>
|
||||
</MenuBarBtn>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -16,10 +16,10 @@ function onClickPost(post: any) {
|
|||
|
||||
<template>
|
||||
<ul class="h-full" overflow="auto" pl="12" pr="4" py="4">
|
||||
<li v-for="post in postList" :key="post.path" class="list-decimal">
|
||||
<li v-for="post in postList" :key="post.path" class="list-decimal text-sm">
|
||||
<div flex>
|
||||
<span
|
||||
class="inline-flex flex-grow cursor-pointer hover:text-blue-500 text-xs"
|
||||
class="inline-flex flex-grow cursor-pointer hover:text-blue-500"
|
||||
:class="{ 'text-blue-500': activePath === post.path }"
|
||||
@click="onClickPost(post)"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { initDevtoolsClient } from '../utils'
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
|
||||
import '../styles/index.scss'
|
||||
|
||||
onMounted(() => {
|
||||
initDevtoolsClient()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="h-full" flex="~ col" text="gray-700 dark:gray-200">
|
||||
<VDHeader />
|
||||
<!-- <RouterLink to="/about">About</RouterLink> -->
|
||||
<div style="height: calc(100% - 32px)" overflow="auto">
|
||||
<PageIndex />
|
||||
</div>
|
||||
</main>>
|
||||
</template>
|
|
@ -0,0 +1,57 @@
|
|||
<script setup lang="ts">
|
||||
import { useDraggable } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
import { useAppStore } from '../stores/app'
|
||||
|
||||
const entryRef = ref()
|
||||
const { style } = useDraggable(entryRef, {
|
||||
initialValue: {
|
||||
x: 12,
|
||||
y: window.innerHeight - 60,
|
||||
},
|
||||
})
|
||||
|
||||
const app = useAppStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="entryRef" :style="style" class="fixed z-9999999999 valaxy-devtools-entry">
|
||||
<button
|
||||
class="bg-white size-10 rounded-full shadow hover:shadow-lg transition p-1 z-1 cursor-pointer"
|
||||
@click="app.isDevtoolsVisible = !app.isDevtoolsVisible"
|
||||
>
|
||||
<ValaxySvgLogo />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<template v-if="app.isDevtoolsVisible">
|
||||
<ValaxyOverlay
|
||||
class="z-9999999998! op-50"
|
||||
:show="app.isDevtoolsVisible"
|
||||
@click="app.isDevtoolsVisible = !app.isDevtoolsVisible"
|
||||
/>
|
||||
<div
|
||||
v-if="app.isDevtoolsVisible"
|
||||
class="valaxy-devtools-container fixed left-0 right-0 bottom-1 z-9999999999 shadow-xl rounded overflow-hidden m-auto"
|
||||
bg-white dark:bg-dark-800
|
||||
>
|
||||
<ValaxyDevtools />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use 'sass:map';
|
||||
@use 'valaxy-theme-yun/styles/vars.scss' as *;
|
||||
|
||||
.valaxy-devtools-entry {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.valaxy-devtools-container {
|
||||
animation-timing-function: map.get($cubic-bezier, "ease-in");
|
||||
width: min(80vw, -48px + 100vw);
|
||||
height: min(60vh, -48px + 100vh);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { useAppStore } from '../../stores/app'
|
||||
|
||||
const app = useAppStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MenuBarBtn @click="app.getDir">
|
||||
<div i-vscode-icons:default-root-folder-opened />
|
||||
</MenuBarBtn>
|
||||
</template>
|
|
@ -1,11 +1,16 @@
|
|||
<script lang="ts" setup>
|
||||
import consola from 'consola'
|
||||
import { Pane, Splitpanes } from 'splitpanes'
|
||||
import { onMounted } from 'vue'
|
||||
import { isStaticMode } from '../utils'
|
||||
import { rpc } from '../../rpc'
|
||||
import { isStaticMode } from '../../utils'
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
if (isStaticMode)
|
||||
document.title = 'Valaxy DevTools (Production)'
|
||||
|
||||
const data = await rpc.getPostList()
|
||||
consola.log('data', data)
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { useDark, usePreferredDark, useToggle } from '@vueuse/core'
|
||||
// these APIs are auto-imported from @vueuse/core
|
||||
export const isDark = useDark()
|
||||
export const toggleDark = useToggle(isDark)
|
||||
export const preferredDark = usePreferredDark()
|
|
@ -0,0 +1,7 @@
|
|||
button:
|
||||
about: About
|
||||
back: Back
|
||||
go: GO
|
||||
home: Home
|
||||
toggle_dark: Toggle dark mode
|
||||
toggle_langs: Change languages
|
|
@ -0,0 +1,7 @@
|
|||
button:
|
||||
about: 关于
|
||||
back: 返回
|
||||
go: 确定
|
||||
home: 首页
|
||||
toggle_dark: 切换深色模式
|
||||
toggle_langs: 切换语言
|
|
@ -1,14 +1,17 @@
|
|||
import { createPinia } from 'pinia'
|
||||
|
||||
// register vue composition api globally
|
||||
import { createApp, ref } from 'vue'
|
||||
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import { handleHotUpdate, routes } from 'vue-router/auto-routes'
|
||||
|
||||
import App from './App.vue'
|
||||
import { installI18n } from './modules/i18n'
|
||||
|
||||
import '@unocss/reset/tailwind.css'
|
||||
import 'uno.css'
|
||||
|
||||
import './styles/index.css'
|
||||
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
@ -33,5 +36,9 @@ if (import.meta.hot) {
|
|||
handleHotUpdate(router)
|
||||
}
|
||||
|
||||
const pinia = createPinia()
|
||||
|
||||
app.use(pinia)
|
||||
app.use(router)
|
||||
installI18n(app)
|
||||
app.mount('#app')
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import type { App } from 'vue'
|
||||
import type { Locale } from 'vue-i18n'
|
||||
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
// Import i18n resources
|
||||
// https://vitejs.dev/guide/features.html#glob-import
|
||||
//
|
||||
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: '',
|
||||
messages: {},
|
||||
})
|
||||
|
||||
const localesMap = Object.fromEntries(
|
||||
Object.entries(import.meta.glob('../locales/*.yml'))
|
||||
.map(([path, loadLocale]) => [path.match(/([\w-]*)\.yml$/)?.[1], loadLocale]),
|
||||
) as Record<Locale, () => Promise<{ default: Record<string, string> }>>
|
||||
|
||||
export const availableLocales = Object.keys(localesMap)
|
||||
|
||||
const loadedLanguages: string[] = []
|
||||
|
||||
function setI18nLanguage(lang: Locale) {
|
||||
i18n.global.locale.value = lang as any
|
||||
if (typeof document !== 'undefined')
|
||||
document.querySelector('html')?.setAttribute('lang', lang)
|
||||
return lang
|
||||
}
|
||||
|
||||
export async function loadLanguageAsync(lang: string): Promise<Locale> {
|
||||
// If the same language
|
||||
if (i18n.global.locale.value === lang)
|
||||
return setI18nLanguage(lang)
|
||||
|
||||
// If the language was already loaded
|
||||
if (loadedLanguages.includes(lang))
|
||||
return setI18nLanguage(lang)
|
||||
|
||||
// If the language hasn't been loaded yet
|
||||
const messages = await localesMap[lang]()
|
||||
i18n.global.setLocaleMessage(lang, messages.default)
|
||||
loadedLanguages.push(lang)
|
||||
return setI18nLanguage(lang)
|
||||
}
|
||||
|
||||
export function installI18n(app: App) {
|
||||
app.use(i18n)
|
||||
loadLanguageAsync('en')
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import type { ClientFunctions, ServerFunctions } from '../rpc'
|
||||
import { createRPCClient } from 'vite-dev-rpc'
|
||||
|
||||
export const rpc = createRPCClient<ServerFunctions, ClientFunctions>('demo', import.meta.hot, {
|
||||
// client functions
|
||||
})
|
|
@ -0,0 +1,29 @@
|
|||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
/**
|
||||
* Global store for users
|
||||
* @example
|
||||
* ```ts
|
||||
* import { useAppStore } from 'valaxy'
|
||||
* const appStore = useAppStore()
|
||||
* ```
|
||||
*/
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
async function getDir() {
|
||||
const dirHandle = await window.showDirectoryPicker()
|
||||
return dirHandle
|
||||
}
|
||||
|
||||
const isDevtoolsVisible = ref(false)
|
||||
|
||||
// a
|
||||
return {
|
||||
getDir,
|
||||
|
||||
isDevtoolsVisible,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(useAppStore, import.meta.hot))
|
|
@ -0,0 +1,5 @@
|
|||
.valaxy-devtools-container {
|
||||
.splitpanes__splitter {
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@ declare module 'vue-router/auto-routes' {
|
|||
* Route name map generated by unplugin-vue-router
|
||||
*/
|
||||
export interface RouteNamedMap {
|
||||
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
|
||||
'/about': RouteRecordInfo<'/about', '/about', Record<never, never>, Record<never, never>>,
|
||||
'/categories': RouteRecordInfo<'/categories', '/categories', Record<never, never>, Record<never, never>>,
|
||||
'/migration': RouteRecordInfo<'/migration', '/migration', Record<never, never>, Record<never, never>>,
|
||||
|
|
|
@ -1,87 +1,118 @@
|
|||
import { join, resolve } from 'node:path'
|
||||
import path from 'node:path'
|
||||
import { componentsDir } from '@advjs/gui/node'
|
||||
|
||||
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
|
||||
import Vue from '@vitejs/plugin-vue'
|
||||
import Unocss from 'unocss/vite'
|
||||
import VueComponents from 'unplugin-vue-components/vite'
|
||||
import VueRouter from 'unplugin-vue-router/vite'
|
||||
import { defineConfig } from 'vite'
|
||||
import { unoConfig } from '../../../../uno.config'
|
||||
import { config } from '../config'
|
||||
import { ValaxyDevtools } from '../node'
|
||||
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
export default defineConfig(() => {
|
||||
return {
|
||||
base: './',
|
||||
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
api: 'modern-compiler',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'~/': __dirname,
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
{
|
||||
name: 'local-object-transform',
|
||||
transform: {
|
||||
order: 'post',
|
||||
async handler(code) {
|
||||
return `${code}\n/* Injected with object hook! */`
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'generate-error',
|
||||
load(id) {
|
||||
if (id === '/__LOAD_ERROR')
|
||||
throw new Error('Load error')
|
||||
if (id === '/__TRANSFORM_ERROR')
|
||||
return 'transform'
|
||||
},
|
||||
transform(code, id) {
|
||||
if (id === '/__TRANSFORM_ERROR')
|
||||
throw new SyntaxError('Transform error')
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: 'no-change',
|
||||
transform: {
|
||||
order: 'post',
|
||||
async handler(code) {
|
||||
return code
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
api: 'modern-compiler',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
VueRouter({
|
||||
routesFolder: join(__dirname, 'pages'),
|
||||
dts: join(__dirname, 'typed-routes.d.ts'),
|
||||
}),
|
||||
Vue({
|
||||
include: [/\.vue$/, /\.md$/],
|
||||
}),
|
||||
VueComponents({
|
||||
dirs: ['components', componentsDir],
|
||||
dts: join(__dirname, 'components.d.ts'),
|
||||
}),
|
||||
Unocss(unoConfig),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'~/': __dirname,
|
||||
},
|
||||
},
|
||||
|
||||
optimizeDeps: {
|
||||
exclude: [
|
||||
'vite-hot-client',
|
||||
server: {
|
||||
proxy: {
|
||||
/**
|
||||
* 代理以便直接在 localhost:5001 上开发测试
|
||||
*
|
||||
* http://localhost:5001/_mockery_api_/xxx => http://localhost:5002/_mockery_api_/xxx
|
||||
*/
|
||||
'^/trpc/.*': {
|
||||
target: `http://localhost:${config.serverPort}`,
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
cors: true,
|
||||
},
|
||||
|
||||
plugins: [
|
||||
{
|
||||
name: 'local-object-transform',
|
||||
transform: {
|
||||
order: 'post',
|
||||
async handler(code) {
|
||||
return `${code}\n/* Injected with object hook! */`
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'generate-error',
|
||||
load(id) {
|
||||
if (id === '/__LOAD_ERROR')
|
||||
throw new Error('Load error')
|
||||
if (id === '/__TRANSFORM_ERROR')
|
||||
return 'transform'
|
||||
},
|
||||
transform(code, id) {
|
||||
if (id === '/__TRANSFORM_ERROR')
|
||||
throw new SyntaxError('Transform error')
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: 'no-change',
|
||||
transform: {
|
||||
order: 'post',
|
||||
async handler(code) {
|
||||
return code
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
VueRouter({
|
||||
routesFolder: path.join(__dirname, 'pages'),
|
||||
dts: path.join(__dirname, 'typed-routes.d.ts'),
|
||||
}),
|
||||
Vue({
|
||||
include: [/\.vue$/, /\.md$/],
|
||||
}),
|
||||
VueComponents({
|
||||
dirs: ['components', componentsDir],
|
||||
dts: path.join(__dirname, 'components.d.ts'),
|
||||
}),
|
||||
Unocss(unoConfig),
|
||||
|
||||
// https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n
|
||||
VueI18n({
|
||||
runtimeOnly: true,
|
||||
compositionOnly: true,
|
||||
fullInstall: true,
|
||||
include: [path.resolve(__dirname, 'locales/**')],
|
||||
}),
|
||||
|
||||
ValaxyDevtools(),
|
||||
],
|
||||
},
|
||||
|
||||
build: {
|
||||
target: 'esnext',
|
||||
outDir: resolve(__dirname, '../../dist/client'),
|
||||
minify: false, // 'esbuild',
|
||||
emptyOutDir: true,
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: [
|
||||
'vite-hot-client',
|
||||
],
|
||||
},
|
||||
|
||||
build: {
|
||||
target: 'esnext',
|
||||
outDir: path.resolve(__dirname, '../../dist/client'),
|
||||
minify: false, // 'esbuild',
|
||||
emptyOutDir: true,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
export const config = {
|
||||
clientPort: 5001,
|
||||
serverPort: 5002,
|
||||
}
|
|
@ -1,82 +1,75 @@
|
|||
import type { ResolvedConfig, ViteDevServer } from 'vite'
|
||||
/* eslint-disable unused-imports/no-unused-vars */
|
||||
import type { Connect, ResolvedConfig, ViteDevServer } from 'vite'
|
||||
import bodyParser from 'body-parser'
|
||||
|
||||
import fs from 'fs-extra'
|
||||
import matter from 'gray-matter'
|
||||
import { JSON_SCHEMA } from 'js-yaml'
|
||||
import { migration } from '../utils/migration'
|
||||
|
||||
const prefix = '/valaxy-devtools-api'
|
||||
|
||||
/**
|
||||
* migration
|
||||
* @param path
|
||||
* @param frontmatter
|
||||
*/
|
||||
export async function migration(path: string, frontmatter: { [key: string]: string }) {
|
||||
if (fs.existsSync(path)) {
|
||||
const rawMd = await fs.readFile(path, 'utf-8')
|
||||
const matterFile = matter(rawMd, { schema: JSON_SCHEMA } as any)
|
||||
let mod = false
|
||||
for (const key in frontmatter) {
|
||||
if (key in matterFile.data) {
|
||||
matterFile.data[frontmatter[key]] = matterFile.data[key]
|
||||
delete matterFile.data[key]
|
||||
mod = true
|
||||
}
|
||||
}
|
||||
if (mod) {
|
||||
const newMd = matter.stringify(matterFile.content, matterFile.data)
|
||||
await fs.writeFile(path, newMd)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// console.error(`post not exist:${path}`)
|
||||
}
|
||||
}
|
||||
const apis: {
|
||||
route: string
|
||||
fn: Connect.NextHandleFunction
|
||||
}[] = [
|
||||
{
|
||||
route: '/frontmatter',
|
||||
fn: async (req, res) => {
|
||||
// update
|
||||
if (req.method === 'POST') {
|
||||
const { pageData, frontmatter: newFm } = await (req as any).body
|
||||
// filePath
|
||||
const path = pageData.path
|
||||
if (fs.existsSync(path)) {
|
||||
const rawMd = await fs.readFile(path, 'utf-8')
|
||||
const matterFile = matter(rawMd)
|
||||
|
||||
// update frontmatter
|
||||
matterFile.data = newFm
|
||||
const newMd = matter.stringify(matterFile.content, matterFile.data)
|
||||
await fs.writeFile(path, newMd)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
route: '/migration',
|
||||
fn: async (req, res) => {
|
||||
// update
|
||||
if (req.method === 'POST') {
|
||||
const { pageData, frontmatter } = await (req as any).body
|
||||
// filePath
|
||||
const worker: Promise<void>[] = []
|
||||
|
||||
for (const item of pageData) {
|
||||
const path = item
|
||||
worker.push(migration(path, frontmatter))
|
||||
}
|
||||
// worker.push(migration(`${userRoot.root}/pages${item}.md`, frontmatter))
|
||||
// for (const item of pageData)
|
||||
// worker.push(migration(item, frontmatter))
|
||||
|
||||
Promise.all(worker).then(() => {
|
||||
res.end('ok')
|
||||
}).catch((_) => {
|
||||
res.end('migration error')
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* register api in vite.server
|
||||
* @param server
|
||||
* @param _viteConfig
|
||||
*/
|
||||
export function registerApi(server: ViteDevServer, _viteConfig: ResolvedConfig) {
|
||||
const app = server.middlewares
|
||||
|
||||
app.use(bodyParser.json())
|
||||
|
||||
app.use(`${prefix}/frontmatter`, async (req, _res) => {
|
||||
// update
|
||||
if (req.method === 'POST') {
|
||||
const { pageData, frontmatter: newFm } = await (req as any).body
|
||||
// filePath
|
||||
const path = pageData.path
|
||||
if (fs.existsSync(path)) {
|
||||
const rawMd = await fs.readFile(path, 'utf-8')
|
||||
const matterFile = matter(rawMd)
|
||||
|
||||
// update frontmatter
|
||||
matterFile.data = newFm
|
||||
const newMd = matter.stringify(matterFile.content, matterFile.data)
|
||||
await fs.writeFile(path, newMd)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.use(`${prefix}/migration`, async (req, _res) => {
|
||||
// update
|
||||
if (req.method === 'POST') {
|
||||
const { pageData, frontmatter } = await (req as any).body
|
||||
// filePath
|
||||
const worker: Promise<void>[] = []
|
||||
|
||||
for (const item of pageData) {
|
||||
const path = item
|
||||
worker.push(migration(path, frontmatter))
|
||||
}
|
||||
// worker.push(migration(`${userRoot.root}/pages${item}.md`, frontmatter))
|
||||
// for (const item of pageData)
|
||||
// worker.push(migration(item, frontmatter))
|
||||
|
||||
Promise.all(worker).then(() => {
|
||||
_res.end('ok')
|
||||
}).catch((_) => {
|
||||
_res.end('migration error')
|
||||
})
|
||||
}
|
||||
apis.forEach(({ route, fn }) => {
|
||||
app.use(prefix + route, fn)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import type { ViteDevServer } from 'vite'
|
||||
import type { ServerFunctions } from '../rpc'
|
||||
import type { ValaxyDevtoolsOptions } from './types'
|
||||
import process from 'node:process'
|
||||
import fg from 'fast-glob'
|
||||
import fs from 'fs-extra'
|
||||
import matter from 'gray-matter'
|
||||
|
||||
export function getFunctions(server: ViteDevServer, devtoolsOptions: ValaxyDevtoolsOptions): ServerFunctions {
|
||||
const userRoot = devtoolsOptions.valaxyApp?.options.userRoot || process.cwd()
|
||||
// const userRoot = GLOBAL_STATE.valaxyApp?.options.userRoot || process.cwd()
|
||||
// const userRoot = process.cwd()
|
||||
// const userRoot = server.config.root
|
||||
|
||||
return {
|
||||
async getPostList() {
|
||||
const files = await fg(`${userRoot}/pages/posts/**/*.md`)
|
||||
|
||||
const posts = []
|
||||
for await (const i of files) {
|
||||
const md = await fs.readFile(i, 'utf-8')
|
||||
const { data } = matter(md)
|
||||
posts.push(data)
|
||||
}
|
||||
|
||||
return {
|
||||
posts,
|
||||
root: userRoot,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,30 +1,29 @@
|
|||
import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'
|
||||
import type { ClientFunctions, ServerFunctions } from '../rpc'
|
||||
import type { ValaxyDevtoolsOptions } from './types'
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||
import c from 'picocolors'
|
||||
import sirv from 'sirv'
|
||||
import { createRPCServer } from 'vite-dev-rpc'
|
||||
import { DIR_CLIENT } from '../dir'
|
||||
import { registerApi } from './api'
|
||||
import { getFunctions } from './functions'
|
||||
|
||||
const NAME = 'valaxy:devtools'
|
||||
|
||||
// import.meta.env.VITE_DEV_VALAXY_DEVTOOLS = 'true'
|
||||
|
||||
export default function ValaxyDevtools(options: ValaxyDevtoolsOptions = {}): Plugin {
|
||||
export function ValaxyDevtools(options: ValaxyDevtoolsOptions = {}): Plugin {
|
||||
let config: ResolvedConfig
|
||||
|
||||
const isDevDevtools = import.meta.env?.VITE_VALAXY_DEVTOOLS_DEV === 'true'
|
||||
|
||||
function configureServer(server: ViteDevServer) {
|
||||
const _print = server.printUrls
|
||||
const base = (options.base ?? server.config.base) || '/'
|
||||
|
||||
const functions = getFunctions(server, options)
|
||||
createRPCServer<ClientFunctions, ServerFunctions>('demo', server.ws, functions)
|
||||
|
||||
const devtoolsUrl = `${base}__valaxy_devtools__/`
|
||||
if (import.meta.env?.VITE_DEV_VALAXY_DEVTOOLS === 'true') {
|
||||
server.middlewares.use(devtoolsUrl, createProxyMiddleware({
|
||||
target: 'http://localhost:5001/#/',
|
||||
changeOrigin: true,
|
||||
}) as any)
|
||||
}
|
||||
else {
|
||||
if (!isDevDevtools) {
|
||||
server.middlewares.use(devtoolsUrl, sirv(DIR_CLIENT, {
|
||||
single: true,
|
||||
dev: true,
|
||||
|
@ -53,6 +52,7 @@ export default function ValaxyDevtools(options: ValaxyDevtoolsOptions = {}): Plu
|
|||
console.log(` ${c.green('➜')} ${c.bold('Inspect')}: ${colorUrl(`${host}${base}__inspect/`)}`)
|
||||
}
|
||||
|
||||
// register api to vite.server
|
||||
registerApi(server, config)
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,8 @@ export default function ValaxyDevtools(options: ValaxyDevtoolsOptions = {}): Plu
|
|||
|
||||
enforce: 'pre',
|
||||
|
||||
// config: () => { },
|
||||
|
||||
configResolved(_config) {
|
||||
config = _config
|
||||
},
|
||||
|
@ -72,3 +74,5 @@ export default function ValaxyDevtools(options: ValaxyDevtoolsOptions = {}): Plu
|
|||
|
||||
return plugin
|
||||
}
|
||||
|
||||
export default ValaxyDevtools
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import type { ValaxyApp } from 'valaxy'
|
||||
|
||||
export interface ValaxyDevtoolsOptions {
|
||||
userRoot?: string
|
||||
base?: string
|
||||
valaxyApp?: ValaxyApp
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import fs from 'fs-extra'
|
||||
import matter from 'gray-matter'
|
||||
import { JSON_SCHEMA } from 'js-yaml'
|
||||
|
||||
/**
|
||||
* migration
|
||||
* @param path
|
||||
* @param frontmatter
|
||||
*/
|
||||
export async function migration(path: string, frontmatter: { [key: string]: string }) {
|
||||
if (fs.existsSync(path)) {
|
||||
const rawMd = await fs.readFile(path, 'utf-8')
|
||||
const matterFile = matter(rawMd, { schema: JSON_SCHEMA } as any)
|
||||
let mod = false
|
||||
for (const key in frontmatter) {
|
||||
if (key in matterFile.data) {
|
||||
matterFile.data[frontmatter[key]] = matterFile.data[key]
|
||||
delete matterFile.data[key]
|
||||
mod = true
|
||||
}
|
||||
}
|
||||
if (mod) {
|
||||
const newMd = matter.stringify(matterFile.content, matterFile.data)
|
||||
await fs.writeFile(path, newMd)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// console.error(`post not exist:${path}`)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import type { Post } from 'valaxy'
|
||||
|
||||
export interface ServerFunctions {
|
||||
// add: (a: number, b: number) => number
|
||||
/**
|
||||
* 获取文章列表
|
||||
*/
|
||||
getPostList: () => Promise<{
|
||||
posts: Post[]
|
||||
}>
|
||||
}
|
||||
|
||||
export interface ClientFunctions {
|
||||
// alert: (message: string) => void
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"types": [
|
||||
"@types/wicg-file-system-access",
|
||||
"vite/client",
|
||||
"unplugin-vue-router/client"
|
||||
],
|
||||
|
|
|
@ -36,7 +36,7 @@ const infoList = computed(() => {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="bg-black/50 fixed bottom-2 left-2 p-2 gap-1 rounded z-9999"
|
||||
class="bg-black/50 fixed bottom-20 left-2 p-2 gap-1 rounded z-9999"
|
||||
text="xs white" flex="~ col"
|
||||
>
|
||||
<div v-for="item in infoList" :key="item.label" class="gap-2 inline-flex">
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<RouterView />
|
||||
</template>
|
|
@ -1,3 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
/**
|
||||
* @see @valaxyjs/devtools
|
||||
*/
|
||||
const ValaxyDevtoolsEntry = import.meta.env
|
||||
? defineAsyncComponent(() => import('@valaxyjs/devtools/src/client/components/ValaxyDevtoolsEntry.vue'))
|
||||
: () => null
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ValaxyApp />
|
||||
<ValaxyDevtoolsEntry />
|
||||
</template>
|
||||
|
|
|
@ -1,18 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { definePerson, defineWebPage, defineWebSite, useSchemaOrg } from '@unhead/schema-org'
|
||||
import { useSeoMeta } from '@unhead/vue'
|
||||
import { useLayout, useValaxyApp } from '../composables'
|
||||
|
||||
// TODO: add docs to override ValaxyApp
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useFrontmatter, useValaxyHead } from '../composables'
|
||||
import { useTimezone } from '../composables/global'
|
||||
|
||||
// https://github.com/vueuse/head
|
||||
// you can use this to manipulate the document head in any components,
|
||||
// they will be rendered correctly in the html results with vite-ssg
|
||||
import { useSiteConfig } from '../config'
|
||||
import ValaxyAddons from './ValaxyAddons.vue'
|
||||
// @ts-expect-error virtual module
|
||||
import ValaxyThemeApp from '/@valaxyjs/ThemeAppVue'
|
||||
|
@ -22,57 +10,18 @@ import ValaxyUserApp from '/@valaxyjs/UserAppVue'
|
|||
// <link rel="apple-touch-icon" href="/pwa-192x192.png">
|
||||
// <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9">
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
// todo, allow user config
|
||||
const fm = useFrontmatter()
|
||||
const layout = useLayout()
|
||||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const title = computed(() => fm.value[`title_${locale.value}`] || fm.value.title)
|
||||
|
||||
// seo
|
||||
// todo: get first image url from markdown
|
||||
const siteUrl = computed(() => fm.value.url || siteConfig.value.url)
|
||||
const description = computed(() => fm.value.excerpt || fm.value.description || siteConfig.value.description)
|
||||
|
||||
useSeoMeta({
|
||||
description,
|
||||
ogDescription: description,
|
||||
ogLocale: computed(() => locale.value || fm.value.lang || siteConfig.value.lang || 'en'),
|
||||
ogLocaleAlternate: computed(() => siteConfig.value.languages.filter(l => l !== locale.value)),
|
||||
ogSiteName: computed(() => siteConfig.value.title),
|
||||
ogTitle: computed(() => fm.value.title || siteConfig.value.title),
|
||||
ogImage: computed(() => fm.value.ogImage || fm.value.cover || siteConfig.value.favicon),
|
||||
ogType: 'website',
|
||||
ogUrl: siteUrl,
|
||||
})
|
||||
|
||||
// for SEO
|
||||
useSchemaOrg([
|
||||
// https://unhead.unjs.io/guide/guides/identity.html
|
||||
// Personal Website or Blog
|
||||
definePerson({
|
||||
name: siteConfig.value.author.name,
|
||||
url: siteUrl.value,
|
||||
image: siteConfig.value.author.avatar,
|
||||
sameAs: siteConfig.value.social.map(s => s.link),
|
||||
}),
|
||||
defineWebSite({
|
||||
name: title.value,
|
||||
datePublished: computed(() => fm.value.date),
|
||||
dateModified: computed(() => fm.value.updated),
|
||||
}),
|
||||
defineWebPage(),
|
||||
])
|
||||
|
||||
useTimezone()
|
||||
|
||||
useValaxyHead()
|
||||
if (layout.value !== 'empty') {
|
||||
useValaxyApp()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ValaxyThemeApp />
|
||||
<ValaxyAddons />
|
||||
<ValaxyUserApp />
|
||||
<template v-if="layout !== 'empty'">
|
||||
<ValaxyThemeApp />
|
||||
<ValaxyAddons />
|
||||
<ValaxyUserApp />
|
||||
</template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_757_102259" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="97" y="222" width="830" height="647">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M729.48 756.469C729.478 756.471 729.475 756.473 729.472 756.475C729.606 756.361 729.625 756.36 729.48 756.469ZM690.046 767.723C685.618 766.845 680.868 765.982 675.803 765.143C634.63 758.32 576.843 753.701 512.383 753.12C447.923 752.538 390.063 756.114 348.774 762.193C343.694 762.941 338.929 763.717 334.486 764.515C338.914 765.394 343.664 766.256 348.729 767.095C389.902 773.918 447.689 778.537 512.149 779.119C576.609 779.7 634.469 776.124 675.758 770.045C680.838 769.298 685.603 768.521 690.046 767.723ZM295.261 752.552C295.118 752.441 295.137 752.442 295.269 752.558C295.266 752.556 295.264 752.554 295.261 752.552ZM295.052 775.769C295.054 775.768 295.057 775.766 295.06 775.764C294.926 775.877 294.907 775.878 295.052 775.769ZM729.263 779.68C729.266 779.682 729.268 779.684 729.271 779.686C729.413 779.798 729.395 779.796 729.263 779.68ZM511.932 803.118C642.542 804.296 748.572 788.686 748.756 768.252C748.941 747.819 643.21 730.299 512.6 729.121C381.99 727.942 275.96 743.552 275.776 763.986C275.591 784.42 381.322 801.939 511.932 803.118Z" fill="url(#paint0_linear_757_102259)" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M729.48 756.469C729.478 756.471 729.475 756.473 729.472 756.475C729.606 756.361 729.625 756.36 729.48 756.469ZM690.046 767.723C685.618 766.845 680.868 765.982 675.803 765.143C634.63 758.32 576.843 753.701 512.383 753.12C447.923 752.538 390.063 756.114 348.774 762.193C343.694 762.941 338.929 763.717 334.486 764.515C338.914 765.394 343.664 766.256 348.729 767.095C389.902 773.918 447.689 778.537 512.149 779.119C576.609 779.7 634.469 776.124 675.758 770.045C680.838 769.298 685.603 768.521 690.046 767.723ZM295.261 752.552C295.118 752.441 295.137 752.442 295.269 752.558C295.266 752.556 295.264 752.554 295.261 752.552ZM295.052 775.769C295.054 775.768 295.057 775.766 295.06 775.764C294.926 775.877 294.907 775.878 295.052 775.769ZM729.263 779.68C729.266 779.682 729.268 779.684 729.271 779.686C729.413 779.798 729.395 779.796 729.263 779.68ZM511.932 803.118C642.542 804.296 748.572 788.686 748.756 768.252C748.941 747.819 643.21 730.299 512.6 729.121C381.99 727.942 275.96 743.552 275.776 763.986C275.591 784.42 381.322 801.939 511.932 803.118Z" fill="url(#paint1_linear_757_102259)" />
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1>DevTools</h1>
|
||||
<p>DevTools</p>
|
||||
</div>
|
||||
</template>
|
|
@ -1 +1,2 @@
|
|||
export * from './useValaxyApp'
|
||||
export * from './useValaxyHead'
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { definePerson, defineWebPage, defineWebSite, useSchemaOrg } from '@unhead/schema-org'
|
||||
import { useSeoMeta } from '@unhead/vue'
|
||||
|
||||
// TODO: add docs to override ValaxyApp
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useFrontmatter, useValaxyHead } from '../../composables'
|
||||
import { useTimezone } from '../../composables/global'
|
||||
|
||||
// https://github.com/vueuse/head
|
||||
// you can use this to manipulate the document head in any components,
|
||||
// they will be rendered correctly in the html results with vite-ssg
|
||||
import { useSiteConfig } from '../../config'
|
||||
|
||||
export function useValaxyApp() {
|
||||
const siteConfig = useSiteConfig()
|
||||
// todo, allow user config
|
||||
const fm = useFrontmatter()
|
||||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const title = computed(() => fm.value[`title_${locale.value}`] || fm.value.title)
|
||||
|
||||
// seo
|
||||
// todo: get first image url from markdown
|
||||
const siteUrl = computed(() => fm.value.url || siteConfig.value.url)
|
||||
const description = computed(() => fm.value.excerpt || fm.value.description || siteConfig.value.description)
|
||||
|
||||
useSeoMeta({
|
||||
description,
|
||||
ogDescription: description,
|
||||
ogLocale: computed(() => locale.value || fm.value.lang || siteConfig.value.lang || 'en'),
|
||||
ogLocaleAlternate: computed(() => siteConfig.value.languages.filter(l => l !== locale.value)),
|
||||
ogSiteName: computed(() => siteConfig.value.title),
|
||||
ogTitle: computed(() => fm.value.title || siteConfig.value.title),
|
||||
ogImage: computed(() => fm.value.ogImage || fm.value.cover || siteConfig.value.favicon),
|
||||
ogType: 'website',
|
||||
ogUrl: siteUrl,
|
||||
})
|
||||
|
||||
// for SEO
|
||||
useSchemaOrg([
|
||||
// https://unhead.unjs.io/guide/guides/identity.html
|
||||
// Personal Website or Blog
|
||||
definePerson({
|
||||
name: siteConfig.value.author.name,
|
||||
url: siteUrl.value,
|
||||
image: siteConfig.value.author.avatar,
|
||||
sameAs: siteConfig.value.social.map(s => s.link),
|
||||
}),
|
||||
defineWebSite({
|
||||
name: title.value,
|
||||
datePublished: computed(() => fm.value.date),
|
||||
dateModified: computed(() => fm.value.updated),
|
||||
}),
|
||||
defineWebPage(),
|
||||
])
|
||||
|
||||
useTimezone()
|
||||
|
||||
useValaxyHead()
|
||||
}
|
|
@ -21,7 +21,7 @@ export async function addValaxyTabAndCommand() {
|
|||
// iframe view
|
||||
view: {
|
||||
type: 'iframe',
|
||||
src: '/__valaxy_devtools__/',
|
||||
src: import.meta.env.DEV ? 'http://localhost:5001/' : '/__valaxy_devtools__/',
|
||||
},
|
||||
// category: 'pinned',
|
||||
category: 'app',
|
||||
|
@ -56,5 +56,5 @@ export async function addValaxyTabAndCommand() {
|
|||
}
|
||||
|
||||
export const install: UserModule = async () => {
|
||||
await addValaxyTabAndCommand()
|
||||
// await addValaxyTabAndCommand()
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ export async function execBuild({ ssg, root, output, log }: { ssg: boolean, root
|
|||
printInfo(options)
|
||||
|
||||
const valaxyApp = createValaxyNode(options)
|
||||
// GLOBAL_STATE.valaxyApp = valaxyApp
|
||||
|
||||
// resolve options and create valaxy app
|
||||
await callHookWithLog('options:resolved', valaxyApp)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { createValaxyNode } from '../app'
|
|||
import { commonOptions } from '../cli/options'
|
||||
import { defaultViteConfig } from '../constants'
|
||||
|
||||
import { GLOBAL_STATE } from '../env'
|
||||
import { resolveOptions } from '../options'
|
||||
import { isPagesDirExist, setEnv, setTimezone } from '../utils/env'
|
||||
import { findFreePort } from '../utils/net'
|
||||
|
@ -39,6 +40,8 @@ export async function startValaxyDev({
|
|||
setTimezone(resolvedOptions.config.siteConfig.timezone)
|
||||
|
||||
const valaxyApp = createValaxyNode(resolvedOptions)
|
||||
GLOBAL_STATE.valaxyApp = valaxyApp
|
||||
|
||||
const viteConfig: InlineConfig = mergeConfig({
|
||||
// initial vite config
|
||||
...defaultViteConfig,
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import type { ViteDevServer } from 'vite'
|
||||
import type { ValaxyApp } from './types'
|
||||
|
||||
export const GLOBAL_STATE: {
|
||||
valaxyApp: ValaxyApp | undefined
|
||||
server: ViteDevServer | undefined
|
||||
} = {
|
||||
valaxyApp: undefined,
|
||||
server: undefined,
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ export * from './cli'
|
|||
export * from './common'
|
||||
export * from './config'
|
||||
export * from './constants'
|
||||
// global env
|
||||
// export * from './env'
|
||||
export * from './options'
|
||||
export * from './plugins'
|
||||
export * from './server'
|
||||
|
|
|
@ -9,6 +9,8 @@ import { createTransformIncludes } from './include'
|
|||
import { matterOptions } from './matter'
|
||||
import { transformMermaid } from './mermaid'
|
||||
|
||||
export * from './matter'
|
||||
|
||||
export async function createMarkdownPlugin(
|
||||
options: ResolvedValaxyOptions,
|
||||
): Promise<Plugin> {
|
||||
|
|
|
@ -4,6 +4,9 @@ import { EXCERPT_SEPARATOR } from '../../../constants'
|
|||
|
||||
type GrayMatterOptions = matter.GrayMatterOption<string, GrayMatterOptions>
|
||||
|
||||
/**
|
||||
* valaxy gray-matter options
|
||||
*/
|
||||
export const matterOptions: GrayMatterOptions = {
|
||||
excerpt_separator: EXCERPT_SEPARATOR,
|
||||
engines: {
|
||||
|
|
|
@ -2,17 +2,19 @@ import type { PluginOption } from 'vite'
|
|||
|
||||
import type { ValaxyServerOptions } from '../options'
|
||||
import type { ValaxyNode } from '../types'
|
||||
import path from 'node:path'
|
||||
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
|
||||
|
||||
import UnheadVite from '@unhead/addons/vite'
|
||||
|
||||
import Vue from '@vitejs/plugin-vue'
|
||||
|
||||
import consola from 'consola'
|
||||
import { resolve } from 'pathe'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import Layouts from 'vite-plugin-vue-layouts'
|
||||
|
||||
import Layouts from 'vite-plugin-vue-layouts'
|
||||
import { customElements } from '../constants'
|
||||
import { resolveImportPath } from '../utils'
|
||||
import { createConfigPlugin } from './extendConfig'
|
||||
import { createMarkdownPlugin } from './markdown'
|
||||
import { createFixPlugins } from './patchTransform'
|
||||
|
@ -31,6 +33,22 @@ export async function ViteValaxyPlugins(
|
|||
const MarkdownPlugin = await createMarkdownPlugin(options)
|
||||
const ValaxyLoader = await createValaxyLoader(options, serverOptions)
|
||||
|
||||
/**
|
||||
* for unplugin-vue-components
|
||||
*/
|
||||
const componentsDirs = roots
|
||||
.map(root => `${root}/components`)
|
||||
.concat(['src/components', 'components'])
|
||||
|
||||
if (valaxyApp.options.mode === 'dev') {
|
||||
const devtoolsDir = path.dirname(await resolveImportPath('@valaxyjs/devtools/package.json'))
|
||||
const devtoolsComponentsDir = path.resolve(devtoolsDir, 'src/client/components')
|
||||
componentsDirs.push(devtoolsComponentsDir)
|
||||
|
||||
const { componentsDir } = await import('@advjs/gui/node')
|
||||
componentsDirs.push(componentsDir)
|
||||
}
|
||||
|
||||
const plugins: (PluginOption | PluginOption[])[] = [
|
||||
MarkdownPlugin,
|
||||
createConfigPlugin(options),
|
||||
|
@ -80,11 +98,12 @@ export async function ViteValaxyPlugins(
|
|||
|
||||
// allow override
|
||||
allowOverrides: true,
|
||||
// override: user -> theme -> client
|
||||
// latter override former
|
||||
dirs: roots
|
||||
.map(root => `${root}/components`)
|
||||
.concat(['src/components', 'components']),
|
||||
/**
|
||||
* override: user -> theme -> client
|
||||
*
|
||||
* latter override former
|
||||
*/
|
||||
dirs: componentsDirs,
|
||||
dts: resolve(options.tempDir, 'components.d.ts'),
|
||||
|
||||
...valaxyConfig.components,
|
||||
|
|
|
@ -38,7 +38,9 @@ export async function createServer(
|
|||
// only enable when dev
|
||||
vitePlugins.push(
|
||||
(await import('vite-plugin-vue-devtools')).default(),
|
||||
(await import('@valaxyjs/devtools')).default(),
|
||||
(await import('@valaxyjs/devtools')).default({
|
||||
valaxyApp,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import type Router from 'unplugin-vue-router/vite'
|
|||
import type { DefaultTheme, PartialDeep, ValaxyAddon, ValaxyConfig } from 'valaxy/types'
|
||||
import type { UserConfig as ViteUserConfig } from 'vite'
|
||||
import type Layouts from 'vite-plugin-vue-layouts'
|
||||
import type { createValaxyNode } from './app'
|
||||
import type { ResolvedValaxyOptions } from './options'
|
||||
import type { MarkdownOptions } from './plugins/markdown/types'
|
||||
|
||||
|
@ -245,3 +246,5 @@ export interface ValaxyAddonResolver {
|
|||
|
||||
setup?: (node: ValaxyNode) => void
|
||||
}
|
||||
|
||||
export type ValaxyApp = ReturnType<typeof createValaxyNode>
|
||||
|
|
|
@ -61,9 +61,9 @@
|
|||
"dependencies": {
|
||||
"@antfu/install-pkg": "^0.5.0",
|
||||
"@antfu/utils": "^0.7.10",
|
||||
"@clack/prompts": "^0.8.2",
|
||||
"@clack/prompts": "^0.9.0",
|
||||
"@iconify-json/ri": "catalog:",
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.1",
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.2",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@unhead/addons": "^1.11.14",
|
||||
"@unhead/schema-org": "^1.11.14",
|
||||
|
@ -75,7 +75,7 @@
|
|||
"@vueuse/core": "12.0.0-beta.1",
|
||||
"@vueuse/integrations": "12.0.0-beta.1",
|
||||
"beasties": "^0.2.0",
|
||||
"consola": "^3.2.3",
|
||||
"consola": "^3.3.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"css-i18n": "^0.0.5",
|
||||
"dayjs": "^1.11.13",
|
||||
|
|
4216
pnpm-lock.yaml
4216
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -15,4 +15,4 @@ catalog:
|
|||
'@iconify-json/vscode-icons': ^1.2.6
|
||||
typescript: '5.6'
|
||||
unbuild: ^3.0.1
|
||||
vite: ^6.0.4
|
||||
vite: ^6.0.5
|
||||
|
|
Loading…
Reference in New Issue