以前寫過一篇關於代碼塊渲染添加自定義行號的文章:markdown-it和highlight.js的結合渲染代碼,並添加自定義行號 。css
不過在以後的渲染使用過程當中因爲效果不是很好,因此從新改版,並藉此機會添加複製代碼功能。html
本博客採用的後端是 node.js 框架 Express,在使用 markdown-it 渲染 md 文件的時候,選擇在添加文章或者更新文章的時候由 md 生成 html。前端
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
highlight: function (str, lang) {
// 當前時間加隨機數生成惟一的id標識
const codeIndex = parseInt(Date.now()) + Math.floor(Math.random() * 10000000)
// 複製功能主要使用的是 clipboard.js
let html = `<button class="copy-btn" type="button" data-clipboard-action="copy" data-clipboard-target="#copy${codeIndex}">複製</button>`
const linesLength = str.split(/\n/).length - 1
// 生成行號
let linesNum = '<span aria-hidden="true" class="line-numbers-rows">'
for (let index = 0; index < linesLength; index++) {
linesNum = linesNum + '<span></span>'
}
linesNum += '</span>'
if (lang && hljs.getLanguage(lang)) {
try {
// highlight.js 高亮代碼
const preCode = hljs.highlight(lang, str, true).value
html = html + preCode
if (linesLength) {
html += '<b class="name">' + lang + '</b>'
}
// 將代碼包裹在 textarea 中,因爲防止textarea渲染出現問題,這裏將 "<" 用 "<" 代替,不影響複製功能
return `<pre class="hljs"><code>${html}</code>${linesNum}</pre><textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${str.replace(/<\/textarea>/g, '</textarea>')}</textarea>`
} catch (error) {
console.log(error)
}
}
const preCode = md.utils.escapeHtml(str)
html = html + preCode
return `<pre class="hljs"><code>${html}</code>${linesNum}</pre><textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${str.replace(/<\/textarea>/g, '</textarea>')}</textarea>`
}
})
複製代碼
import Clipboard from 'clipboard'
export default {
...
data () {
return {
...
clipboard: ''
}
},
mounted () {
this.$nextTick(() => {
this.clipboard = new Clipboard('.copy-btn')
// 複製成功失敗的提示
this.clipboard.on('success', (e) => {
this.$message.success('複製成功')
})
this.clipboard.on('error', (e) => {
this.$message.error('複製成功失敗')
})
})
},
...
destroyed () {
this.clipboard.destroy()
}
}
複製代碼
pre.hljs {
padding: 12px 2px 12px 40px !important;
border-radius: 5px !important;
position: relative;
font-size: 14px !important;
line-height: 22px !important;
overflow: hidden !important;
code {
display: block !important;
margin: 0 10px !important;
overflow-x: auto !important;
&::-webkit-scrollbar {
z-index: 11;
width: 6px;
}
&::-webkit-scrollbar:horizontal {
height: 6px;
}
&::-webkit-scrollbar-thumb {
border-radius: 5px;
width: 6px;
background: #666;
}
&::-webkit-scrollbar-corner,&::-webkit-scrollbar-track {
background: #1E1E1E;
}
&::-webkit-scrollbar-track-piece {
background: #1E1E1E;
width: 6px
}
}
.line-numbers-rows {
position: absolute;
pointer-events: none;
top: 12px;
bottom: 12px;
left: 0;
font-size: 100%;
width: 40px;
text-align: center;
letter-spacing: -1px;
border-right: 1px solid rgba(0, 0, 0, .66);
user-select: none;
counter-reset: linenumber;
span {
pointer-events: none;
display: block;
counter-increment: linenumber;
&:before {
content: counter(linenumber);
color: #999;
display: block;
text-align: center;
}
}
}
b.name {
position: absolute;
top: 2px;
right: 50px;
z-index: 10;
color: #999;
pointer-events: none;
}
.copy-btn {
position: absolute;
top: 2px;
right: 4px;
z-index: 10;
color: #333;
cursor: pointer;
background-color: #fff;
border: 0;
border-radius: 2px;
}
}
複製代碼
自定義行號主要使用的是CSS計數方面的知識,感興趣能夠查看 css計數器 。vue