Vue+ts+markdown-it代码高亮复制行号
2023-12-29 16:53:52
Vue+ts+markdown-it代码高亮复制行号
通过markdown-it 自定义显示markdown组件,实现代码复制按钮和行号显示
安装
// 安装markdown解析器
yarn add markdown-it
// 安装代码高亮highlight组件
yarn add highlight.js
.d.ts
// 简单声明module 防止ts引入报错
declare module 'markdown-it'
declare module 'highlight.js'
code代码框复制实现
通过在markdown-it
的highlight
中处理高亮时在合适的位置插入如下html
代码
// 复制按钮html codeId时<core>标签的id
`<div class="toolbar" onclick='window.copyCode("${codeId}")'><img alt="复制" src="${src}"/><div>${
txt ? txt : ''
}</div></div>`
在window
下挂载全局方法copyCode
window.copyCode = function (codeId: string) {
//复制实现
}
行号
通过在markdown-it
的highlight
中处理高亮时在合适的位置插入如下html
代码
`<ul class="line-box">${lis}</ul>`
获取行号lis
var lis = ''
if (array) {// str 是highlight中源码str.split('\n')分割后集合
for (var i = 1; i <= array.length; i++) {
lis += `<li>${i}</li>`
}
}
markdown
import { defineComponent, onMounted, ref, watch } from 'vue'
import MarkdownIt from 'markdown-it'
import 'highlight.js/styles/atom-one-dark.css'
import 'highlight.js/lib/common'
import './index.less'
import hljs from 'highlight.js'
export default defineComponent({
name: 'MarkDownBox',
props: {
message: {
type: String,
default: ''
},
showLine: {
type: Boolean,
defalut: true
}
},
emits: ['copyCode'],
setup(props, { emit, slots }) {
const mdHtml = ref()
window.copyCode = function (codeId: string) {
emit('copyCode', document.getElementById(codeId)?.innerText)
}
var md = MarkdownIt({
highlight: function (str: string, lang: string, langAttrs: any) {
const hasLang = lang && hljs.getLanguage(lang)
const codes = str.split('\n')
const id = getUUID()
const toolBox = getCodeToolBox(hasLang, lang,id)
if (hasLang) {
try {
return `<pre>${toolBox}<div class="code-box">
${props.showLine != false ? getLineBox(codes) : ''}
<code id="${id}" class="hljs language-${lang}">${hljs.highlight(lang, str, true).value}</code>
</div></pre>`
} catch (__) {}
}
return `<pre>${toolBox}<div class="code-box">${
props.showLine != false ? getLineBox(codes) : ''
}<code id="${id}" class="hljs">${md.utils.escapeHtml(str)}</code></div></pre>`
}
})
const getLineBox = (array: Array<string>) => {
var lis = ''
if (array) {
for (var i = 1; i <= array.length; i++) {
lis += `<li>${i}</li>`
}
}
return `<ul class="line-box">${lis}</ul>`
}
const getCodeToolBox = (hasLang: boolean, lang: string, codeId: string) => {
return `<div class="tool-box" >
${hasLang ? ` <div class="code-lang">${lang}</div>` : ''}
${getCodeTool(`window.copyCode('${codeId}')`, require('@/assets/images/icon_copy.png'), '复制')}
</div>`
}
const getCodeTool = (clickFun: string, src: string, txt: string) => {
return `<div class="toolbar" onclick="${clickFun}"><img alt="复制" src="${src}"/><div>${
txt ? txt : ''
}</div></div>`
}
watch(
() => props.message,
(val) => {
markdown(val)
}
)
const markdown = (msg: string) => {
mdHtml.value = md.render( msg )
}
onMounted(() => {
markdown(props.message)
})
return () => {
return (
<div
v-html={mdHtml.value}
</div>
)
}
}
})
index.less
pre {
display: flex;
flex-direction: column;
width: 100%;
margin: 10px 0px;
border: none;
border-radius: 6px;
background-color: rgb(34, 34, 34) !important;
overflow-x: auto;
color: #fff;
}
pre code {
background-color: #292b33 !important;
padding: 12px;
width: 100%;
}
.code-box {
display: flex;
width: 100%;
}
.line-box {
color: #cdcdcd;
text-align: right;
padding: 12px 8px !important;
font-size: 14px;
font-family: 'Courier New', Courier, monospace;
border-right: 1px solid #7d7d7d;
}
.tool-box {
width: 100%;
padding: 4px 12px;
display: flex;
align-items: center;
justify-content: flex-end;
color: white;
font-size: 14px;
.code-lang {
flex: auto;
}
.toolbar {
display: flex;
align-items: center;
padding-left: 4px;
img {
width: 18px;
height: 18px;
margin-right: 1px;
}
}
}
文章来源:https://blog.csdn.net/TomCat0916/article/details/135289329
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!