<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue Markdown 渲染器</title>
<!-- 样式依赖 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/github-dark.min.css">
<!-- Vue 2.x 生产环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.min.js"></script>
<!-- 脚本依赖 -->
<script src="https://cdn.jsdelivr.net/npm/markdown-it@13.0.1/dist/markdown-it.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-base64@3.7.5/base64.min.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
<div class="markdown-body" v-html="compiledMarkdown" @click="handleClick"></div>
</div>
<script>
// 初始化消息提示
//Vue.use(ELEMENT);
// 初始化 Markdown 处理器
const md = new markdownit({
linkify: true,
highlight: function (code, language) {
const safeCode = code.replace('', '');
const codeSource = Base64.encode(safeCode);
const validLang = !!language && hljs.getLanguage(language);
try {
const highlighted = validLang
? hljs.highlight(safeCode, { language }).value
: hljs.highlightAuto(safeCode).value;
return `
<pre class="code-block-wrapper">
<div class="code-block-header">
<span class="code-lang">${(language || 'text').toUpperCase()}</span>
<a class="code-copy" data-action="copy" data-code="${codeSource}">复制代码</a>
</div>
<code class="hljs">${highlighted}</code>
</pre>
`;
} catch (e) {
console.error('代码高亮错误:', e);
return `<pre><code>${code}</code></pre>`;
}
}
})
// md.use(window.mila, {
// attrs: {
// target: '_blank',
// rel: 'noopener noreferrer'
// }
// })
// md.use(markdownitKatex, {
// blockClass: 'katex-block',
// errorColor: '#ff4444'
// });
// 创建 Vue 实例
new Vue({
el: '#app',
data: {
textContent: `# Markdown 示例
\`\`\`javascript
// 代码示例
function greet(name) {
console.log(\`Hello \${name}!\`);
}
\`\`\``,
isWriting: false
},
computed: {
compiledMarkdown() {
let content = this.textContent.trim();
if (this.isWriting) {
content += '';
}
return md.render(content);
}
},
methods: {
handleClick(event) {
if (event.target.dataset.action === 'copy') {
const encoded = event.target.dataset.code;
const decoded = Base64.decode(encoded);
this.$copyText(decoded)
.then(() => this.$message.success('复制成功'))
.catch(() => this.$message.error('复制失败'));
}
}
}
});
</script>
<style>
*{ box-sizing: border-box; margin:0; padding:0;}
body{ padding:12px; }
.markdown-body { display: block; background-color: transparent; font-size: 14px; box-sizing: border-box; }
.markdown-body p { white-space: pre-wrap; text-align: left; padding-top:5px; }
.markdown-body p:last-child { margin-bottom: 0; }
.markdown-body img[alt=cursor] { width: 5px; height: 20px; position: relative; top: 4px; left: 2px; }
.markdown-body ol { list-style-type: decimal; }
.markdown-body ul { list-style-type: disc; }
.markdown-body h1 { padding-top:10px; font-size:22px; }
.markdown-body h2 { padding-top:10px; font-size:18px; }
.markdown-body h3 { padding-top:10px; font-size:15px; }
.markdown-body hr { border:none; height:1px; background:#ddd; margin:5px 0; }
.markdown-body code{ margin:0; padding:0;}
.markdown-body > pre { background-color: #2b2b2b; border-radius:5px; overflow: hidden; margin-top:12px; transition: background 0.1s ease-in-out; text-align: left; border-radius:3px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; font-feature-settings: normal; font-variation-settings: normal; }
.markdown-body .code-block-wrapper { position: relative; }
.markdown-body .code-block-header { background:#333; padding: 5px 1rem; display: flex; justify-content:space-between; align-items: center; color: #b3b3b3; font-size:14px; }
.markdown-body .code-block-header a { cursor: pointer; margin-left: 0.5rem; user-select: none; color:#b3b3b3; }
.markdown-body .code-block-header a:hover { color: #65a665; }
.markdown-body .code-block-wrapper { display: block; width: 100%; }
</style>
</body>
</html>
HTML 加载markdown 和代码高亮
于 2025-04-19 12:15:39 首次发布