feat: support dynamic excerpt render & move custom styles to theme, close #577

This commit is contained in:
YunYouJun 2025-07-15 00:19:51 +08:00
parent 55c65b6227
commit 95cc709d19
11 changed files with 108 additions and 52 deletions

View File

@ -47,10 +47,19 @@ const postTitleClass = computed(() => {
<div flex="~ grow col" w="full" justify="center" items="center">
<div v-if="post.excerpt_type === 'text'" py="1" />
<div
v-if="post.excerpt" class="markdown-body" op="90" text="left" w="full" p="x-8 y-2"
v-html="post.excerpt"
/>
<template v-if="post.excerpt">
<div
v-if="post.excerpt_type === 'html'"
class="markdown-body" op="90" text="left" w="full" p="x-8 y-2"
>
<ValaxyDynamicComponent :template-str="post.excerpt" />
</div>
<div
v-else
class="markdown-body" op="90" text="left" w="full" p="x-8 y-2"
v-html="post.excerpt"
/>
</template>
<div v-else m="b-5" />
</div>
<!-- <div m="b-5" /> -->

View File

@ -60,8 +60,9 @@ function goToLink() {
>
<div class="gap-1" flex="~">
<div
v-if="fm.icon"
class="size-4"
:class="fm.icon || ''"
:class="fm.icon"
/>
<span class="truncate"> {{ $tO(fm.title || '') }}</span>
</div>

View File

@ -32,13 +32,13 @@
ul {
list-style: initial;
li > p {
li>p {
margin-bottom: 0;
}
}
ol {
> li {
>li {
list-style: decimal;
}
}
@ -122,3 +122,41 @@
}
}
}
@media (width <=767.9px) {
.markdown-body {
padding: 0.5rem;
}
}
@include mobile {
.markdown-body {
div[class*="language-"] {
position: relative;
// left: 50%;
// right: 50%;
// margin-left: -50vw !important;
// margin-right: -50vw !important;
// width: 100vw !important;
margin-top: 16px;
margin-bottom: 0;
margin-left: -24px;
margin-right: -24px;
height: auto;
}
}
}
@media (width <=639.9px) {
.markdown-body .vp-code-group .tabs,
.markdown-body .vp-code-group div[class*="language-"] {
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw !important;
margin-right: -50vw !important;
width: 100vw !important;
height: auto;
}
}

View File

@ -0,0 +1,33 @@
<script setup lang="ts">
import type { Component } from 'vue'
import { compile, defineAsyncComponent, onMounted, shallowRef } from 'vue'
const props = withDefaults(
defineProps<{
templateStr: string
data?: Record<string, any>
}>(),
{
data: () => ({}),
},
)
const dynamicComponent = shallowRef<Component | null>(null)
async function createComponent() {
const render = compile(props.templateStr)
const componentDefinition = {
render,
data: () => props.data,
}
dynamicComponent.value = defineAsyncComponent(() => Promise.resolve(componentDefinition))
}
onMounted(() => {
createComponent()
})
</script>
<template>
<component :is="dynamicComponent" />
</template>

View File

@ -1,16 +1,13 @@
<script setup lang="ts">
// import { useValaxyI18n } from 'valaxy'
import { useI18n } from 'vue-i18n'
defineProps<{
title: string
content: string
}>()
const { t } = useI18n()
</script>
<template>
<span>
{{ t(title) }}
</span>
{{ t(content) }}
</template>

View File

@ -1,4 +1,3 @@
import type { ViteSSGContext } from 'vite-ssg'
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders'
import { dataSymbol, initValaxyConfig, valaxyConfigSymbol } from 'valaxy'
import { setupLayouts } from 'virtual:generated-layouts'
@ -9,10 +8,8 @@ import { routes } from 'vue-router/auto-routes'
import App from './App.vue'
import { initData } from './app/data'
import AppLink from './components/AppLink.vue'
import setupMain from './setup/main'
import { setupValaxyDevTools } from './utils/dev'
/**
* user styles
@ -23,14 +20,6 @@ import 'uno.css'
const valaxyConfig = initValaxyConfig()
/**
* register global components
* @param ctx
*/
export function registerComponents(ctx: ViteSSGContext) {
ctx.app.component('AppLink', AppLink)
}
const { redirectRoutes, useVueRouter } = valaxyConfig.value.runtimeConfig.redirects
if (useVueRouter)
routes.push(...redirectRoutes)
@ -84,7 +73,6 @@ export const createApp = ViteSSG(
app.provide(valaxyConfigSymbol, valaxyConfig)
registerComponents(ctx)
setupMain(ctx, valaxyConfig)
},
)

View File

@ -0,0 +1,13 @@
import type { ViteSSGContext } from 'vite-ssg'
import AppLink from '../components/AppLink.vue'
import ValaxyTranslate from '../components/builtin/ValaxyTranslate.vue'
/**
* register global components
* @param ctx
*/
export function registerGlobalComponents(ctx: ViteSSGContext) {
ctx.app.component('AppLink', AppLink)
ctx.app.component('VT', ValaxyTranslate)
}

View File

@ -9,6 +9,7 @@ import type { ViteSSGContext } from 'vite-ssg'
import type { ComputedRef } from 'vue'
import { consola } from 'consola'
import { registerGlobalComponents } from '../modules/components'
import { install as installFloatingVue } from '../modules/floating-vue'
import { install as installNprogress } from '../modules/nprogress'
import { install as installPinia } from '../modules/pinia'
@ -20,6 +21,7 @@ export default function setupMain(ctx: ViteSSGContext, config: ComputedRef<Valax
// eslint-disable-next-line unused-imports/no-unused-vars
const injection_arg = ctx
registerGlobalComponents(ctx)
installValaxy(ctx, config)
installUnhead(ctx)
installPinia(ctx)

View File

@ -18,15 +18,7 @@ html:not(.dark) .vp-code-dark {
@include mobile {
.markdown-body {
div[class*="language-"] {
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw !important;
margin-right: -50vw !important;
width: 100vw !important;
margin-top: 16px;
margin-bottom: 0;
height: auto;
margin: 0 var(--va-code-mobile-margin-x, -1rem);
}
}
}
@ -42,17 +34,6 @@ html:not(.dark) .vp-code-dark {
.markdown-body li div[class*="language-"] {
border-radius: 6px 0 0 6px;
}
.markdown-body .vp-code-group .tabs,
.markdown-body .vp-code-group div[class*="language-"] {
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw !important;
margin-right: -50vw !important;
width: 100vw !important;
height: auto;
}
}
.markdown-body {
@ -273,4 +254,4 @@ html:not(.dark) .vp-code-dark {
[class*='language-'].folded>button.collapse {
display: block;
}
}
}

View File

@ -102,9 +102,3 @@
font-size: 32px;
}
}
@media (width <=767.9px) {
.markdown-body {
padding: 1rem;
}
}

View File

@ -34,7 +34,7 @@ function createContainer(key: string, block: BlockItem = {}, md: MarkdownItAsync
if (block.icon)
iconTag = `<i class="icon ${block.icon}" ${block.color ? `style="color: ${block.color}"` : ''}></i>`
const title = `<ValaxyContainerBlockTitle title="blocks.${key}" />`
const title = `<VT content="blocks.${key}" />`
const titleClass
= `custom-block-title${info ? '' : ' custom-block-title-default'}`