hilight + 行番号を表示したものをゴールとして目指します。
参考にした記事、コードは下記です
highlight.jsで行ごとに区切りつつハイライトする
highlightjs/vue-plugin
行番号 + ハイライト を行う関数を作る
highlight.jsで行ごとに区切りつつハイライトする
を参考にすると、
単純に行区切りにhilightを適用しても、うまくいかないことがわかります。
そこで
let state = null
const result = hljs.highlight('markdown', row, true, state)
state = result.top
とし、
result.top
を継承することで行違いのhilightを働かせることができます。
これを利用し、
function lineByLineHighilght (language, body) {
let state = null
const output = []
const bodySplit = body.split('\n')
let maxLength = String(bodySplit.length).length
for (let line = 0; line < bodySplit.length; line++) {
const row = bodySplit[line]
const result = hljs.highlight(language, row, true, state)
let setLineNumber = `<div style="float: left; width: ${maxLength}7px;"><span style="float: right; padding-right: 5px;">${line}:</span></div>`
let setLine = `<div class="lineNumber">${setLineNumber}<span class="line-value">${result.value}</span></div>`
if (result.value.length === 0) {
setLine = `<div class="lineNumber">${setLineNumber}</div></br>`
}
state = result.top
output.push(setLine)
}
return output.join('')
}
とすることで、行番号を付与することができます。
ちなみに、
if (result.value.length === 0) {
setLine = `<div class="lineNumber">${setLineNumber}</div></br>`
}
の部分ですが、これはresult.value.length === 0
の時、改行されない問題が合ったので行ってます。
( もっと上手い解決策があれば教えてください:) )
VueJs上でhilight + 行番号表示を行う
vueのコンポーネントとして、hilightJsを扱えれば一番良く、
また公式側でvueでhilight.jsを扱えるようになっています。
hilight.js
ただ、今回はこのままでは扱えないので、
highlightjs/vue-pluginの中身を参考にし、
import hljs from 'highlight.js'
function hasValueOrEmptyAttribute (value) {
return Boolean(value || value === '')
}
function lineByLineHighilght (language, body) {
let state = null
const output = []
const bodySplit = body.split('\n')
let maxLength = String(bodySplit.length).length
for (let line = 0; line < bodySplit.length; line++) {
const row = bodySplit[line]
const result = hljs.highlight(language, row, true, state)
let setLineNumber = `<div style="float: left; width: ${maxLength}7px;"><span style="float: right; padding-right: 5px;">${line}:</span></div>`
let setLine = `<div class="lineNumber">${setLineNumber}<span class="line-value">${result.value}</span></div>`
if (result.value.length === 0) {
setLine = `<div class="lineNumber">${setLineNumber}</div></br>`
}
state = result.top
output.push(setLine)
}
return output.join('')
}
const Component = {
props: ['language', 'code'],
data: function () {
return {
detectedLanguage: '',
unknownLanguage: false
}
},
computed: {
className () {
if (this.unknownLanguage) return ''
return 'hljs ' + this.detectedLanguage
},
highlighted () {
return lineByLineHighilght(this.language, this.code)
},
ignoreIllegals () {
return true
}
},
render (createElement) {
return createElement('pre', {}, [
createElement('code', {
class: this.className,
domProps: { innerHTML: this.highlighted }
})
])
}
}
export default {
install (Vue) {
Vue.component('highlightjs', Component)
},
component: Component
}
このように行うことで、任意なvueファイルで
<highlightjs language="HTML" :code="code"/>
と、
その任意のvueファイルが扱われる以前にrenderされているか、もしくは
その任意のファイル自身で
import hljs from '@/plugins/highlightVue.js'
Vue.use(hljs)
とすると、
下記のような結果にhilight + 行番号表示が行えます