Skip to content

Commit

Permalink
feat(devtools): add update frontmatter api
Browse files Browse the repository at this point in the history
  • Loading branch information
YunYouJun committed Feb 14, 2024
1 parent 13fa219 commit f375568
Show file tree
Hide file tree
Showing 21 changed files with 458 additions and 91 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
},

"cSpell.words": [
"AGUI",
"algoliasearch",
"beian",
"codepen",
Expand Down
8 changes: 7 additions & 1 deletion demo/yun/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@
"build": "npm run fuse && npm run build:ssg",
"build:spa": "valaxy build",
"build:ssg": "valaxy build --ssg --log=info",
"dev": "nodemon -w \"../../packages/valaxy/dist/*.mjs\" --exec \"valaxy . --port 4860\"",
"dev": "nodemon --exec \"valaxy . --port 4860\"",
"fuse": "valaxy fuse",
"new": "valaxy new",
"rss": "valaxy rss",
"serve": "vite preview"
},
"nodemonConfig": {
"watch": [
"../../packages/valaxy/dist/*.mjs",
"../../packages/devtools/dist/*"
]
},
"dependencies": {
"valaxy": "workspace:*",
"valaxy-addon-algolia": "workspace:*",
Expand Down
6 changes: 5 additions & 1 deletion packages/devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"build:node": "unbuild",
"dev": "npm run stub && npm run dev:client",
"dev:client": "vite build src/client --watch",
"dev:src": "vite dev src/client",
"dev:src": "vite dev src/client --port 5001",
"stub": "unbuild --stub",
"prepublishOnly": "npm run build",
"release": "bumpp && npm publish"
Expand All @@ -33,8 +33,12 @@
"sirv": "^2.0.4"
},
"devDependencies": {
"@advjs/gui": "0.0.5-beta.0",
"@iconify-json/ri": "^1.1.19",
"@types/body-parser": "^1.19.5",
"@types/splitpanes": "^2.2.6",
"axios": "^1.6.7",
"http-proxy-middleware": "^2.0.6",
"splitpanes": "^3.1.5",
"typescript": "^5.3.3",
"unbuild": "^2.0.0",
Expand Down
9 changes: 9 additions & 0 deletions packages/devtools/src/client/App.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
<script lang="ts" setup>
import { onMounted } from 'vue'
import { initDevtoolsClient } from './utils'
onMounted(() => {
initDevtoolsClient()
})
</script>

<template>
<RouterView />
</template>
57 changes: 54 additions & 3 deletions packages/devtools/src/client/components/PageFrontmatter.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
<script lang="ts" setup>
defineProps<{
frontmatter?: object
import { ref, toRaw } from 'vue'
import type { PostFrontMatter } from 'valaxy'
import axios from 'axios'
import consola from 'consola'
import { pageData } from '../composables/app'
const props = defineProps<{
frontmatter: PostFrontMatter
}>()
const newFm = ref<PostFrontMatter>(props.frontmatter)
async function saveNewFm() {
// const data = await fetch('/valaxy-devtools-api/frontmatter', {
// method: 'POST',
// // body: JSON.stringify(toRaw(newFm.value)),
// })
const res = await axios.post('/valaxy-devtools-api/frontmatter', {
pageData: pageData.value,
frontmatter: toRaw(newFm.value),
})
if (res)
consola.success('Frontmatter saved')
// console.log(res)
}
</script>

<template>
<div>
<ul v-if="frontmatter">
<li v-for="(value, key) in frontmatter" :key="key">
<strong>{{ key }}</strong>: {{ value }}
<strong>{{ key }}</strong>
<span mr-1>:</span>

<template v-if="key === 'tags'">
<VDTag v-for="tag in value" :key="tag">
{{ tag }}
</VDTag>
</template>
<template v-else-if="key === 'categories'">
<VDPostCategories :categories="value" />
</template>
<template v-else-if="key === 'encryptedContent'">
[Encrypted]
</template>
<template v-else-if="key === 'partiallyEncryptedContents'">
[Partially Encrypted]
</template>
<template v-else-if="key === 'title'">
<!-- eslint-disable-next-line vue/no-mutating-props -->
<AGUIInput v-model="newFm.title" />
</template>
<template v-else>
{{ value }}
</template>
</li>
</ul>

<AGUIButton @click="saveNewFm">
Save Frontmatter
</AGUIButton>
</div>
</template>
22 changes: 22 additions & 0 deletions packages/devtools/src/client/components/PostPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts" setup>
import { getWindowProperty, openInEditor } from '../utils'
import { frontmatter } from '../composables/app'
function launchEditor() {
openInEditor({
file: getWindowProperty('$pageData').path,
})
}
</script>

<template>
<div p="2">
<div class="flex" gap="2" py-2>
<button class="text-xs shadow transition hover:shadow-lg p-2" @click="launchEditor()">
<div i-vscode-icons:file-type-vscode />
</button>
</div>

<PageFrontmatter v-if="frontmatter" :frontmatter="frontmatter" />
</div>
</template>
26 changes: 26 additions & 0 deletions packages/devtools/src/client/components/VDPostCategories.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts" setup>
import type { Post } from 'valaxy'
defineProps<{
categories: Post['categories']
}>()
</script>

<template>
<RouterLink
:to="{
path: '/categories',
query: { category: Array.isArray(categories) ? categories.join('/') : categories },
}"
class="post-category transition text-xs hover:(text-blue-500 border-blue-500)"
px-2 py-1
border rounded-full
inline-flex justify-center items-center
bg="hover:(blue-500 opacity-10)"
>
<div m="x-1" inline-flex i-ri-folder-2-line />
<span>
{{ Array.isArray(categories) ? categories.join(' > ') : categories }}
</span>
</RouterLink>
</template>
30 changes: 5 additions & 25 deletions packages/devtools/src/client/components/VDPostList.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import type { Router } from 'vue-router/auto'
import { getGlobalValaxyProperty, getWindowProperty, openInEditor } from '../utils'
import { frontmatter } from '../composables/app'
const activePath = ref('')
const __VUE_DEVTOOLS_ROUTER__ = getWindowProperty('__VUE_DEVTOOLS_ROUTER__') as Router
__VUE_DEVTOOLS_ROUTER__.beforeEach((to, _from, next) => {
activePath.value = to.path
frontmatter.value = getWindowProperty('$frontmatter')
next()
})
import { getGlobalValaxyProperty } from '../utils'
import { activePath, devtoolsRouter } from '../composables/app'
const postList = ref()
Expand All @@ -20,31 +10,21 @@ onMounted(() => {
})
function onClickPost(post: any) {
__VUE_DEVTOOLS_ROUTER__.push(post.path)
}
function launchEditor() {
openInEditor({
file: getWindowProperty('$pageData').path,
})
devtoolsRouter.value?.push(post.path)
}
</script>

<template>
<ul class="h-full" overflow="auto" pl="12" pr="4" py="4">
{{ activePath }}
<li v-for="post in postList" :key="post.path" class="list-decimal">
<div flex>
<span
class="inline-flex flex-grow cursor-pointer underline hover:text-blue-500"
:class="{ 'text-blue-500': activePath === post.path }"
class="inline-flex flex-grow cursor-pointer hover:text-blue-500"
:class="{ 'text-blue-500 font-bold': activePath === post.path }"
@click="onClickPost(post)"
>
{{ post.title }}
</span>
<button class="ml-2 text-xs" @click="launchEditor()">
<div i-vscode-icons:file-type-vscode />
</button>
</div>
</li>
</ul>
Expand Down
9 changes: 9 additions & 0 deletions packages/devtools/src/client/components/VDTag.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts" setup>
</script>

<template>
<div class="vd-tag inline-flex shadow border rounded text-xs" p="x-2 y-1">
<slot />
</div>
</template>
9 changes: 8 additions & 1 deletion packages/devtools/src/client/composables/app.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import type { PageData, PostFrontMatter } from 'valaxy'
import { ref } from 'vue'

export const frontmatter = ref<object>({})
import type { Router } from 'vue-router'

export const devtoolsRouter = ref<Router>()
export const activePath = ref('')

export const frontmatter = ref<PostFrontMatter>()
export const pageData = ref<PageData>()
15 changes: 4 additions & 11 deletions packages/devtools/src/client/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
<script lang="ts" setup>
import { Pane, Splitpanes } from 'splitpanes'
import { onMounted } from 'vue'
import { getWindowProperty, isStaticMode } from '../utils'
import type { BlogWindow } from '../types'
import { frontmatter } from '../composables/app'
import { isStaticMode } from '../utils'
onMounted(() => {
if (isStaticMode)
document.title = 'Valaxy DevTools (Production)'
const $frontmatter = getWindowProperty('$frontmatter') as BlogWindow['$frontmatter']
if ($frontmatter)
frontmatter.value = $frontmatter
})
</script>

<template>
<main class="h-full" flex="~ col" text="gray-700 dark:gray-200">
<div class="w-full border-b shadow flex justify-end">
<a href="https://valaxy.site" target="_blank" class="bg-gray-100 inline-flex justify-center items-center w-8 h-8">
<div class="w-full border-b shadow flex justify-end" dark="border-b-black">
<a href="https://valaxy.site" target="_blank" class="bg-gray-100 dark:bg-gray-900 inline-flex justify-center items-center w-8 h-8">
<div i-ri-book-line />
</a>
</div>
Expand All @@ -30,7 +23,7 @@ onMounted(() => {
<VDPostList />
</Pane>
<Pane>
<PageFrontmatter :frontmatter="frontmatter" />
<PostPanel />
</Pane>
</Splitpanes>
</div>
Expand Down
4 changes: 4 additions & 0 deletions packages/devtools/src/client/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ html,
body {
height: 100%;
}

.dark {
background-color: rgba(12, 16, 21);
}
1 change: 1 addition & 0 deletions packages/devtools/src/client/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './init'
export * from './api'
export * from './get'

Expand Down
27 changes: 27 additions & 0 deletions packages/devtools/src/client/utils/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { nextTick, onMounted } from 'vue'
import type { Router } from 'vue-router'
import { activePath, devtoolsRouter, frontmatter, pageData } from '../composables/app'
import { getWindowProperty } from './get'

export function initDevtoolsClient() {
const __VUE_DEVTOOLS_ROUTER__ = getWindowProperty('__VUE_DEVTOOLS_ROUTER__') as Router
devtoolsRouter.value = __VUE_DEVTOOLS_ROUTER__

devtoolsRouter.value.beforeEach((to, _from, next) => {
activePath.value = to.path
next()
})

// init $frontmatter and $pageData
onMounted(() => {
frontmatter.value = getWindowProperty('$frontmatter')
pageData.value = getWindowProperty('$pageData')
})

devtoolsRouter.value.afterEach(async () => {
await nextTick()
// get target post $frontmatter
frontmatter.value = getWindowProperty('$frontmatter')
pageData.value = getWindowProperty('$pageData')
})
}
3 changes: 2 additions & 1 deletion packages/devtools/src/client/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Vue from '@vitejs/plugin-vue'
import VueRouter from 'unplugin-vue-router/vite'
import VueComponents from 'unplugin-vue-components/vite'
import Unocss from 'unocss/vite'
import { componentsDir } from '@advjs/gui/node'
import { unoConfig } from '../../../../uno.config'

export default defineConfig({
Expand Down Expand Up @@ -57,7 +58,7 @@ export default defineConfig({
include: [/\.vue$/, /\.md$/],
}),
VueComponents({
dirs: ['components'],
dirs: ['components', componentsDir],
dts: join(__dirname, 'components.d.ts'),
}),
Unocss(unoConfig),
Expand Down
35 changes: 35 additions & 0 deletions packages/devtools/src/node/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { ResolvedConfig, ViteDevServer } from 'vite'
import bodyParser from 'body-parser'

import matter from 'gray-matter'
import fs from 'fs-extra'

const prefix = '/valaxy-devtools-api'

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)
}
}

// console.log('update', url, frontmatter)

// console.log('frontmatter', req.url, res)
})
}

0 comments on commit f375568

Please sign in to comment.