完成markdown渲染

main
abab2320 2 weeks ago
parent fffaecb0a3
commit ca4364834b

@ -15,6 +15,7 @@
"element-plus": "^2.9.7",
"highlight.js": "^11.11.1",
"marked": "^15.0.12",
"marked-highlight": "^2.2.1",
"vee-validate": "^4.15.0",
"vue": "^3.5.13",
"vue-router": "^4.5.0",

@ -26,6 +26,9 @@ importers:
marked:
specifier: ^15.0.12
version: 15.0.12
marked-highlight:
specifier: ^2.2.1
version: 2.2.1(marked@15.0.12)
vee-validate:
specifier: ^4.15.0
version: 4.15.0(vue@3.5.13(typescript@5.7.3))
@ -624,6 +627,11 @@ packages:
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
marked-highlight@2.2.1:
resolution: {integrity: sha512-SiCIeEiQbs9TxGwle9/OwbOejHCZsohQRaNTY2u8euEXYt2rYUFoiImUirThU3Gd/o6Q1gHGtH9qloHlbJpNIA==}
peerDependencies:
marked: '>=4 <16'
marked@15.0.12:
resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==}
engines: {node: '>= 18'}
@ -1453,6 +1461,10 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
marked-highlight@2.2.1(marked@15.0.12):
dependencies:
marked: 15.0.12
marked@15.0.12: {}
math-intrinsics@1.1.0: {}

@ -10,14 +10,14 @@ import HeaderBar from './components/HeaderBar.vue'
<style>
/* 设置 body 背景渐变,清除异常布局设置 */
body{
height: 100%;
width:100%;
/*弹性布局,水平垂直居中*/
justify-content: center;
align-items: center;
/*渐变背景*/
background: linear-gradient(200deg, #f3e7e9, #e3eeff);
html, body, #app {
margin: 0;
padding: 0;
height: 100vh;
width: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(200deg, #f3e7e9, #e3eeff);
overflow: hidden;
}
</style>

@ -15,14 +15,6 @@
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
@ -90,6 +82,16 @@ button {
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}
.flow-container{
padding:4%;
margin:0;
display: flex;
flex-direction: column;
width: 92%;
height: 100%;
overflow:auto;
}
#app {
width: 100vw;
height: 100vh;

@ -0,0 +1,113 @@
<template>
<div class="markdown-body" v-html="compiledMarkdown" />
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { marked } from 'marked'
import { markedHighlight } from 'marked-highlight'
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css' // 'atom-one-dark.css'
// props
const props = defineProps<{
content: string
}>()
const compiledMarkdown = ref('')
// marked
marked.use(
markedHighlight({
langPrefix: 'hljs language-',
highlight(code: string, lang: string): string {
if (lang && hljs.getLanguage(lang)) {
return hljs.highlight(code, { language: lang }).value
}
return hljs.highlightAuto(code).value
}
})
)
// Markdown
async function renderMarkdown() {
compiledMarkdown.value = await marked.parse(props.content || '')
}
// props.content
watch(() => props.content, renderMarkdown, { immediate: true })
</script>
<style scoped>
.markdown-body {
font-size: 16px;
line-height: 1.8;
word-break: break-word;
color: #1a1a1a;
h1, h2, h3, h4 {
font-weight: bold;
margin: 1.2em 0 0.6em;
}
h1 { font-size: 1.8em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.2em; }
a {
color: #0366d6;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
code {
background: #f6f8fa;
padding: 0.2em 0.4em;
border-radius: 4px;
font-family: 'Courier New', Courier, monospace;
}
pre {
background: #f6f8fa;
padding: 1em;
border-radius: 6px;
overflow-x: auto;
}
blockquote {
border-left: 4px solid #dfe2e5;
padding-left: 1em;
color: #6a737d;
margin: 1em 0;
}
ul, ol {
padding-left: 2em;
margin: 0.5em 0;
}
img {
max-width: 100%;
height: auto;
border-radius: 6px;
margin: 0.5em 0;
}
table {
border-collapse: collapse;
width: 100%;
margin: 1em 0;
}
th, td {
border: 1px solid #dfe2e5;
padding: 0.6em 1em;
}
th {
background-color: #f6f8fa;
}
}
</style>

@ -1,11 +1,16 @@
<template>
<div class="markdown-body">
<h1>这是 Markdown 标题</h1>
<p>这是一段内容这里是模拟 Markdown 的渲染文本</p>
<img src="@/assets/images/LogPage1.jpg" alt="预览图片" />
<MarkdownRender :content="content" />
</div>
</template>
<script setup lang="ts">
import MarkdownRender from '@/components/MarkdownRender.vue';
defineProps<{
content: string
}>();
</script>
<style scoped lang="scss">
.markdown-body {
font-family: 'Georgia', serif;

@ -28,7 +28,7 @@ function goTo(tag: string) {
<style scoped lang="scss">
.post-sidebar {
font-size: 16px;
font-size: 20px;
.top-tags {
margin-top: 8px;
@ -39,7 +39,7 @@ function goTo(tag: string) {
list-style-type: none;
padding: 0;
&:hover {
font-size:20px;
font-size:24px;
color:#8a63d2;
}
}
@ -51,7 +51,7 @@ function goTo(tag: string) {
margin: 6px 0;
cursor: pointer;
&:hover {
font-size:20px;
font-size:24px;
color:#8a63d2;
}
}

@ -1,4 +1,5 @@
<template>
<div class = "flow-container">
<div class="forum-home">
<!-- 左侧主内容区 -->
<div class="left-section card">
@ -28,13 +29,16 @@
/>
</div>
</div>
<!-- 右侧今日行程 -->
<div class="right-section">
<h2>📅 今日行程</h2>
<ScheduleCard />
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
@ -84,7 +88,7 @@ const posts = [
tags: ['Ant Design', '设计语言', '蚂蚁金服'],
excerpt: '段落示意:这是帖子的部分具体内容……',
link: '/post/5'
}
},
]
</script>
@ -92,15 +96,13 @@ const posts = [
.forum-home {
display: flex;
width:92%;
padding-top:750px;
gap: 40px; // 🔧
.left-section {
flex: 3;
display: flex;
flex-direction: column;
margin-right: 350px;
margin-right:10%;
gap: 30px; // 🔧
background: linear-gradient(to bottom right, #f7f1ff, #ffffff);
}
@ -142,7 +144,7 @@ const posts = [
.right-section {
flex: 1;
position:fixed;
margin-left:75%;
margin-left:77%;
height: 830px;
min-width: 350px;
padding: 16px;

@ -304,14 +304,6 @@ async function login(){
padding: 0;
}
body{
height: 100vh;;
/*弹性布局,水平垂直居中*/
justify-content: center;
align-items: center;
/*渐变背景*/
background: linear-gradient(200deg, #f3e7e9, #2a4b7c);
}
.container{
background-color: #fff;

@ -1,4 +1,5 @@
<template>
<div class = "flow-container">
<div class = "post-detail-page">
<!-- 左侧分类 包含分类 -->
<SidebarCategory class="sidebar card" />
@ -9,6 +10,7 @@
<!-- 右侧作者信息 -->
<AuthorInfo class="author-info card" :author="post.author" />
</div>
</div>
</template>
<script setup lang = "ts">
@ -25,7 +27,37 @@ const postId = ref<number>(parseInt(route.params.id as string))
const post = ref({
id: postId.value,
title: '帖子标题示例',
content: '这是帖子的详细内容支持HTML或markdown',
content: `
# 欢迎来到论坛
这是一个使用 **Vue3** + **Vite** + **TypeScript** 搭建的论坛系统
## 功能清单
- 支持 Markdown 渲染
- 高亮代码块
- 响应式布局
- 用户评论系统
## 示例代码
\`\`\`ts
function greet(name: string): string {
return \`Hello, \${name}!\`
}
console.log(greet('Vue'))
\`\`\`
## 引用与链接
> 学习不是人生的全部但如果连学习都掌握不了你还能做什么
请访问 [Vue 官方文档](https://vuejs.org)
## 图片测试
![Vue Logo](https://vuejs.org/images/logo.png)
`,
author: {
id: 1,
name: '张三',
@ -35,6 +67,7 @@ const post = ref({
tags: ['Vue3', '论坛开发', '学习笔记']
})
//
onMounted(() => {
// TODO: fetch(`/api/post/${postId.value}`)
@ -45,14 +78,11 @@ onMounted(() => {
<style scoped lang="scss">
.post-detail-page {
display:flex;
padding-top:550px;
width:92%;
gap:16px;
.sidebar{
flex:1;
flex:2;
position:sticky;
top:20px;
height: fit-content;
border-radius: 8px;
padding: 16px;
@ -66,7 +96,7 @@ onMounted(() => {
}
.author-info{
flex:2;
flex:3;
position:sticky;
flex-shrink:0;
height:fit-content;

Loading…
Cancel
Save