使用marked
This commit is contained in:
parent
3710642bc0
commit
15779301fa
7
assets/svg/time.svg
Normal file
7
assets/svg/time.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg t="1745843719544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2701"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
|
||||||
|
<path d="M509.9 64.4c-246.6 0-446.6 200-446.6 446.6 0 246.6 199.9 446.6 446.6 446.6S956.5 757.7 956.5 511c0-246.6-199.9-446.6-446.6-446.6zM627 556.3H502.4c-25 0-45.3-20.3-45.3-45.3V274.3c0-25 20.3-45.3 45.3-45.3s45.3 20.3 45.3 45.3v191.5H627c25 0 45.3 20.3 45.3 45.3S652 556.3 627 556.3z"
|
||||||
|
fill="" p-id="2702"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 676 B |
@ -1,21 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { Editor } from '@bytemd/vue-next'
|
|
||||||
import gfm from '@bytemd/plugin-gfm'
|
|
||||||
|
|
||||||
const content = ref('')
|
|
||||||
const plugins = [gfm()]
|
|
||||||
const handleChange = (v: string) => {
|
|
||||||
content.value = v
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Editor :value="content" :plugins="plugins" @change="handleChange" class="byteMd"/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.byteMd{
|
|
||||||
position: relative;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
124
components/Home/Blog/Marked.vue
Normal file
124
components/Home/Blog/Marked.vue
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {Marked} from 'marked';
|
||||||
|
// 默认导入所有语言
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
import 'highlight.js/styles/atom-one-light.css';
|
||||||
|
// 注册语言
|
||||||
|
// import hljs from 'highlight.js/lib/core';
|
||||||
|
// import javascript from 'highlight.js/lib/languages/javascript';
|
||||||
|
// hljs.registerLanguage('javascript', javascript);
|
||||||
|
|
||||||
|
const marked = new Marked();
|
||||||
|
|
||||||
|
// 自定义行号注入函数
|
||||||
|
const injectLineNumbers = (highlightedCode: string) => {
|
||||||
|
const lines = highlightedCode.split('\n')
|
||||||
|
|
||||||
|
// 移除最后一行空行(常见于代码块末尾的换行)
|
||||||
|
if (lines[lines.length - 1] === '') lines.pop()
|
||||||
|
|
||||||
|
// 为每行添加行号容器
|
||||||
|
return lines.map((line, index) => `<div class="code-line"><span class="line-number">${index + 1}</span><span class="line-content">${line}</span></div>`).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
marked.use({
|
||||||
|
async: true,
|
||||||
|
pedantic: false,
|
||||||
|
gfm: true,
|
||||||
|
silent: true,
|
||||||
|
renderer: {
|
||||||
|
code: ({text, lang}) => {
|
||||||
|
console.log(text);
|
||||||
|
const validLang = hljs.getLanguage(lang) ? lang : 'plaintext'
|
||||||
|
const highlighted = hljs.highlight(text, {language: lang}).value
|
||||||
|
console.log(highlighted)
|
||||||
|
const withLineNumbers = injectLineNumbers(highlighted)
|
||||||
|
return `<pre class="hljs ${validLang}"><code>${withLineNumbers}</code></pre>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const content = ref(`
|
||||||
|
# Hello Vue 3!
|
||||||
|
|
||||||
|
**Markdown 内容示例:**
|
||||||
|
|
||||||
|
- 列表项
|
||||||
|
- 另一项
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// 代码块示例
|
||||||
|
function greet() {
|
||||||
|
console.log('Hello marked!');
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
| 参数 | \t类型 | \t作用 | \t默认值 |
|
||||||
|
|:-----------|:---------|:---------------------------------------------|:----------------|
|
||||||
|
| breaks | \tboolean | \t将换行符 \\n 渲染为 <br>(类似 GitHub) | \tfalse |
|
||||||
|
| gfm | \tboolean | \t启用 GitHub Flavored Markdown 扩展(表格、删除线等) | \ttrue |
|
||||||
|
| headerIds\t | boolean | \t自动为标题添加 id 属性(如 \`<h1 id="hello-world"></h1>\`) | \ttrue |
|
||||||
|
| highlight\t | function | \t代码高亮处理函数,需返回高亮后的 HTML | \tnull |
|
||||||
|
| renderer\t | object | \t自定义渲染器对象(覆盖默认渲染逻辑) | \tnew Renderer() |
|
||||||
|
| sanitize\t | boolean | \t过滤危险 HTML 标签(防止 XSS 攻击) | \tfalse |
|
||||||
|
| sanitizer\t | function | \t自定义 HTML 过滤函数 | \t- |
|
||||||
|
| silent\t | boolean | \t静默模式:忽略解析错误(如未闭合的代码块) | \tfalse |
|
||||||
|
`);
|
||||||
|
|
||||||
|
const compiledMarkdown = ref(await marked.parse(content.value));
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
ref="markdownContainer"
|
||||||
|
class="markdown-content"
|
||||||
|
v-html="compiledMarkdown"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.markdown-content {
|
||||||
|
// 基础样式...
|
||||||
|
|
||||||
|
/* 代码块样式 */
|
||||||
|
:deep(pre) {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
background: #cdcdcd;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: 'Consolas', 'Fira Code', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 确保代码块正确换行 */
|
||||||
|
code {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-line {
|
||||||
|
display: flex;
|
||||||
|
min-height: 1em; /* 防止空行高度塌陷 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-number {
|
||||||
|
width: 40px;
|
||||||
|
padding-right: 12px;
|
||||||
|
color: #666;
|
||||||
|
text-align: right;
|
||||||
|
user-select: none;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-content {
|
||||||
|
flex-grow: 1;
|
||||||
|
white-space: pre-wrap; /* 允许代码换行 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
137
docs/f01-mrkdown/byteMD-Markdown.vue
Normal file
137
docs/f01-mrkdown/byteMD-Markdown.vue
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Editor } from '@bytemd/vue-next'
|
||||||
|
import type { BytemdPlugin } from "bytemd";
|
||||||
|
import gfm from '@bytemd/plugin-gfm'
|
||||||
|
import gfmZhHans from "@bytemd/plugin-gfm/locales/zh_Hans.json";
|
||||||
|
import math from '@bytemd/plugin-math'
|
||||||
|
import highlight from '@bytemd/plugin-highlight'
|
||||||
|
import 'highlight.js/styles/default.css'
|
||||||
|
import mediumZoom from '@bytemd/plugin-medium-zoom'
|
||||||
|
import mermaid from '@bytemd/plugin-mermaid'
|
||||||
|
import breaks from '@bytemd/plugin-breaks'
|
||||||
|
import gemoji from '@bytemd/plugin-gemoji'
|
||||||
|
import rehypeHighlightCodeLines from "rehype-highlight-code-lines";
|
||||||
|
import {useNiMessage} from "~/composables/useNiMessage";
|
||||||
|
const niMessage = useNiMessage()
|
||||||
|
|
||||||
|
// Markdown内容
|
||||||
|
const content = ref('')
|
||||||
|
// 自定义插件
|
||||||
|
const customPlugins = {
|
||||||
|
actions: [{
|
||||||
|
title: '插入时间',
|
||||||
|
icon: h('span', { class: 'iconfont icon-time' }, ['🕒']),
|
||||||
|
handler: {
|
||||||
|
type: 'action',
|
||||||
|
click: (targer) => {
|
||||||
|
// wrapText 环绕式字符,像“”【】《》<>之类的
|
||||||
|
// replaceLines((line) => "- [ ] " + line); // 单向的
|
||||||
|
// editor.focus() 聚焦
|
||||||
|
targer.replaceLines((line) => new Date() + line);
|
||||||
|
targer.editor.focus();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
// 显示代码行号
|
||||||
|
const highlightCodeLinesPlugin = (): BytemdPlugin => {
|
||||||
|
return {
|
||||||
|
rehype: (processor) =>
|
||||||
|
processor
|
||||||
|
// 添加代码行号
|
||||||
|
.use(rehypeHighlightCodeLines, {
|
||||||
|
showLineNumbers: true,
|
||||||
|
lineContainerTagName: "div",
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// 代码复制按钮
|
||||||
|
const codeCopyPlugin = (): BytemdPlugin => {
|
||||||
|
const createCopyDom = (text: any): HTMLElement => {
|
||||||
|
const copyDom = document.createElement("div");
|
||||||
|
copyDom.className = "icon-[ph--copy-bold] absolute right-2 top-2 cursor-pointer";
|
||||||
|
copyDom.addEventListener("click", () => {
|
||||||
|
window.copyToClipboard(text);
|
||||||
|
niMessage.info("复制成功");
|
||||||
|
});
|
||||||
|
return copyDom;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
viewerEffect: ({ markdownBody }) => {
|
||||||
|
// 获取所有code标签
|
||||||
|
const els = markdownBody.querySelectorAll("pre>code");
|
||||||
|
if (els.length === 0) return;
|
||||||
|
|
||||||
|
// 往pre标签中append copy节点
|
||||||
|
els.forEach((itm: HTMLElement) => {
|
||||||
|
itm.parentNode.appendChild(createCopyDom(itm.innerText));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// ByteMD的插件
|
||||||
|
const plugins = [
|
||||||
|
// DFM 任务列表、表格、删除线
|
||||||
|
gfm({locale: gfmZhHans}),
|
||||||
|
// 数学公式
|
||||||
|
math(),
|
||||||
|
// 代码高亮
|
||||||
|
highlight(),
|
||||||
|
// 图片放大
|
||||||
|
mediumZoom(),
|
||||||
|
// Mermaid 图表(流程图、时序图、甘特图等)
|
||||||
|
mermaid(),
|
||||||
|
// 自动将换行符转换为 <br>,支持 GitHub 风格的换行行为
|
||||||
|
breaks(),
|
||||||
|
// 支持 GitHub 风格的表情符号短代码(如 :+1: → 👍)
|
||||||
|
gemoji(),
|
||||||
|
// 代码行号
|
||||||
|
highlightCodeLinesPlugin(),
|
||||||
|
// 代码复制
|
||||||
|
codeCopyPlugin(),
|
||||||
|
// 自定义插件
|
||||||
|
customPlugins,]
|
||||||
|
// 当Markdown内容修改时
|
||||||
|
const handleChange = (v: string) => {
|
||||||
|
content.value = v
|
||||||
|
}
|
||||||
|
// 模式 ['auto', 'split', 'tab'] 自动:根据屏幕宽度,自行选择分屏还是标签选择
|
||||||
|
const mode = ref('auto');
|
||||||
|
// 语言
|
||||||
|
const language = await import('~/node_modules/bytemd/locales/zh_Hans.json')
|
||||||
|
// 编辑器配置
|
||||||
|
const editorConfig = {
|
||||||
|
toolbar: [] // 清空默认工具栏
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Editor class="byteMd"
|
||||||
|
:value="content"
|
||||||
|
:plugins="plugins"
|
||||||
|
:editorConfig
|
||||||
|
:locale="language"
|
||||||
|
@change="handleChange" >
|
||||||
|
<!-- 添加自定义工具栏 -->
|
||||||
|
<template #toolbar="{ editor }">
|
||||||
|
<div class="custom-toolbar">
|
||||||
|
<button
|
||||||
|
title="插入时间"
|
||||||
|
@click="editor.insertContent(`当前时间:${new Date().toLocaleString()}`)">
|
||||||
|
⏰ 插入时间
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Editor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.byteMd{
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
:global(.bytemd) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
77
docs/f01-mrkdown/marked/Marked使用方法.md
Normal file
77
docs/f01-mrkdown/marked/Marked使用方法.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
## 导入
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 只作用于当前空间
|
||||||
|
import { Marked } from 'marked';
|
||||||
|
const marked = new Marked();
|
||||||
|
|
||||||
|
// 全局
|
||||||
|
import { marked } from 'marked';
|
||||||
|
```
|
||||||
|
|
||||||
|
## 核心方法
|
||||||
|
|
||||||
|
| 方法 | 作用 | 示例 |
|
||||||
|
|:--------------------------|:----------------|:-----------------------------------------|
|
||||||
|
| marked.parse(md) | 同步解析 Markdown | await marked.parse('**bold**') |
|
||||||
|
| marked.parse(md, callback)| 异步解析(处理异步高亮等场景) | marked.parse(md, (err, html) => { ... }) |
|
||||||
|
| marked.use(options) | 全局配置 | marked.use({ breaks: true }) |
|
||||||
|
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
```js
|
||||||
|
marked.use({
|
||||||
|
async: true,
|
||||||
|
pedantic: false,
|
||||||
|
gfm: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
| 参数 | 类型 | 作用 | 默认值 |
|
||||||
|
|:-----------|:---------|:---------------------------------------------|:----------------|
|
||||||
|
| breaks | boolean | 将换行符 \n 渲染为 <br>(类似 GitHub) | false |
|
||||||
|
| gfm | boolean | 启用 GitHub Flavored Markdown 扩展(表格、删除线等) | true |
|
||||||
|
| headerIds | boolean | 自动为标题添加 id 属性(如 `<h1 id="hello-world"></h1>`) | true |
|
||||||
|
| highlight | function | 代码高亮处理函数,需返回高亮后的 HTML | null |
|
||||||
|
| renderer | object | 自定义渲染器对象(覆盖默认渲染逻辑) | new Renderer() |
|
||||||
|
| sanitize | boolean | 过滤危险 HTML 标签(防止 XSS 攻击) | false |
|
||||||
|
| sanitizer | function | 自定义 HTML 过滤函数 | - |
|
||||||
|
| silent | boolean | 静默模式:忽略解析错误(如未闭合的代码块) | false |
|
||||||
|
|
||||||
|
## 扩展 Markdown 语法
|
||||||
|
|
||||||
|
## 使用worker多线程
|
||||||
|
|
||||||
|
## 开启 sanitize: true 或使用 DOMPurify 二次过滤
|
||||||
|
|
||||||
|
## 性能优化
|
||||||
|
|
||||||
|
? 建议缓存常用操作
|
||||||
|
|
||||||
|
|
||||||
|
## renderer方法
|
||||||
|
|
||||||
|
| 方法名及参数 | 对应 Markdown 元素 | 默认返回值示例 |
|
||||||
|
|:-----------------------------------|:---------------------|:------------------------------------------|
|
||||||
|
| code(code, language, isEscaped) | 代码块(三个反引号包裹) | `<pre><code class="lang">...</code></pre>` |
|
||||||
|
| blockquote(quote) | 引用块 > | `<blockquote>...</blockquote>` |
|
||||||
|
| html(html) | 原生 HTML 片段 | 直接返回原始 HTML |
|
||||||
|
| heading(text, level, raw, slugger) | 标题 # | `<h1>...</h1>` |
|
||||||
|
| hr() | 分割线 --- | `<hr>` |
|
||||||
|
| list(body, ordered, start) | 列表(有序/无序) | `<ul>...</ul> 或 <ol>...</ol>` |
|
||||||
|
| listitem(text, task, checked) | 列表项 - item | `<li>...</li>` |
|
||||||
|
| checkbox(checked) | 任务列表复选框 - [x] | `<input type="checkbox" checked="">` |
|
||||||
|
| paragraph(text) | 段落 | `<p>...</p>` |
|
||||||
|
| table(header, body) | 表格 | `<table>...</table>` |
|
||||||
|
| tablerow(content) | 表格行 | `<tr>...</tr>` |
|
||||||
|
| tablecell(content, flags) | 表格单元格(flags 含对齐信息) | `<td>...</td> 或 <th>...</th>` |
|
||||||
|
| strong(text) | 加粗 **text** | `<strong>...</strong>` |
|
||||||
|
| em(text) | 斜体 *text* | `<em>...</em>` |
|
||||||
|
| codespan(code) | 行内代码 `code` | `<code>...</code>` |
|
||||||
|
| br() | 换行(两个空格结尾或 br 配置) | `<br>` |
|
||||||
|
| del(text) | 删除线 ~~text~~ | `<del>...</del>` |
|
||||||
|
| link(href, title, text) | 链接 [text](url) | `<a href="...">...</a>` |
|
||||||
|
| image(href, title, text) | 图片  | `<img src="..." alt="...">` |
|
||||||
|
| text(text) | 普通文本 | 直接返回文本(会转义 HTML) |
|
43
docs/f01-mrkdown/marked/highlight.js.md
Normal file
43
docs/f01-mrkdown/marked/highlight.js.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
## 按需导入
|
||||||
|
```js
|
||||||
|
// 导入核心库和所需语言
|
||||||
|
import hljs from 'highlight.js/lib/core';
|
||||||
|
import javascript from 'highlight.js/lib/languages/javascript';
|
||||||
|
import xml from 'highlight.js/lib/languages/xml';
|
||||||
|
|
||||||
|
// 注册语言
|
||||||
|
hljs.registerLanguage('javascript', javascript);
|
||||||
|
hljs.registerLanguage('xml', xml);
|
||||||
|
|
||||||
|
// 使用接口
|
||||||
|
const code = '<div>Test</div>';
|
||||||
|
const result = hljs.highlight(code, { language: 'xml' }).value;
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 全部导入
|
||||||
|
|
||||||
|
```js
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
import 'highlight.js/styles/github.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
关键接口说明
|
||||||
|
- highlightAll()
|
||||||
|
自动检测页面中所有 `<pre><code>` 块的代码语言并高亮。
|
||||||
|
|
||||||
|
- highlight(code, { language })
|
||||||
|
手动指定语言高亮代码(需提前注册对应语言)。
|
||||||
|
|
||||||
|
- highlightAuto(code)
|
||||||
|
自动检测语言并高亮,返回包含语言类型和高亮结果的对象。
|
||||||
|
|
||||||
|
- registerLanguage(langName, languageDefinition)
|
||||||
|
注册自定义或第三方语言模块。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
- 主题切换:替换 CSS 文件路径即可(如 styles/default.min.css → styles/monokai-sublime.min.css)3。
|
||||||
|
|
||||||
|
- TypeScript 类型:安装 @types/highlight.js 或自定义类型声明(参考此方案)6。
|
||||||
|
|
||||||
|
- 性能优化:动态加载语言模块(如通过 import() 动态导入)10。
|
@ -32,7 +32,6 @@ export default defineNuxtConfig({
|
|||||||
'~/assets/css/iconfont.css',
|
'~/assets/css/iconfont.css',
|
||||||
'~/assets/css/transitions.css',
|
'~/assets/css/transitions.css',
|
||||||
'~/assets/css/Ni.css',
|
'~/assets/css/Ni.css',
|
||||||
'bytemd/dist/index.css', // byteMD 编辑器
|
|
||||||
],
|
],
|
||||||
app: {
|
app: {
|
||||||
head: {
|
head: {
|
||||||
|
1633
package-lock.json
generated
1633
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,15 +14,15 @@
|
|||||||
"sqlV": "drizzle-kit studio"
|
"sqlV": "drizzle-kit studio"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bytemd/plugin-gfm": "^1.22.0",
|
|
||||||
"@bytemd/vue-next": "^1.22.0",
|
|
||||||
"@nuxt/eslint": "^1.3.0",
|
"@nuxt/eslint": "^1.3.0",
|
||||||
"bytemd": "^1.22.0",
|
|
||||||
"consola": "^3.4.2",
|
"consola": "^3.4.2",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"dompurify": "^3.2.5",
|
||||||
"drizzle-orm": "^0.42.0",
|
"drizzle-orm": "^0.42.0",
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.25.0",
|
||||||
|
"highlight.js": "^11.11.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"marked": "^15.0.11",
|
||||||
"mysql2": "^3.14.0",
|
"mysql2": "^3.14.0",
|
||||||
"nuxt": "^3.16.2",
|
"nuxt": "^3.16.2",
|
||||||
"redis": "^4.7.0",
|
"redis": "^4.7.0",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="BlogEntity">
|
<div class="BlogEntity">
|
||||||
<HomeBlogMarkdown></HomeBlogMarkdown>
|
<HomeBlogMarked></HomeBlogMarked>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user