程式碼上色!highlight.js in Nuxt

Nuxt
highlight.js

在網路技術文章內寫了程式碼卻沒上色,會讓人感覺瞬間降了一個層次


談到程式碼/語法上色,絕對是highlight.js這個library為首選


安裝

npm install highlight.js --save


客製化highlight.js plugin

檔案放在~/plugins/highlight.js,名稱可自訂

import hljs from 'highlight.js/lib/core.js'
import xml from 'highlight.js/lib/languages/xml'
import scss from 'highlight.js/lib/languages/scss'
import javascript from 'highlight.js/lib/languages/javascript'
import bash from 'highlight.js/lib/languages/bash'
import 'highlight.js/styles/tomorrow-night-bright.css'

import Vue from 'vue'

// register languages
hljs.registerLanguage('xml', xml)
hljs.registerLanguage('scss', scss)
hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('bash', bash)

Vue.directive('highlight', function (el) {
  let elements = el.querySelectorAll('pre.ql-syntax')
  elements.forEach((element) => {
    hljs.highlightElement(element)
  })
})


第六行import你想要的上色主題樣式,預覽可看這裡


querySelectorAll內的'pre.ql-syntax' 乃客製化重點


取決於你的customized editor吐出來的html轉譯結果


我使用的vue-quill-editor吐出來是<pre>帶ql-syntax class


若使用其他editor套件,舉例來說,若吐出來是<pre><code>...</code></pre>


那就需要修改成'pre > code' 之類的相對應的選擇語法


舊版本使用hljs.highlightBlock()在v12.0會被遺棄,故這裡更新為hljs.highlightElement()


修改nuxt.config.js

plugins: [
  { src: '~plugins/highlight.js', ssr: true },
],


於component、page中使用

擷取一小段code作範例,使用上很簡單,要渲染的地方加上v-highlight即可

<section class="overflow-x-hidden">
    <div id="content" v-highlight v-html="content"></div>
</section>


BONUS: 修改被highlight.js渲染的區塊的CSS

預設渲染區塊的樣式沒有border-radious


外加其他一些CSS小細節想改,此時須用到CSS deep selector!


這裡直接貼上Hamsterism使用的修改樣式,單就highlight.js的話,乃/deep/ .hljs

<style lang="scss" scoped>
#content {
  /deep/ blockquote {
    border-left: 4px solid $hamsterism-btn-color-primary;
    margin-bottom: 5px;
    margin-top: 5px;
    padding: 0.5rem 1rem;
    color: $hamsterism-text-color-dark;
    background-color: $hamsterism-btn-color-secondary-light;
  }
  /deep/ code {
    font-size: 85%;
    padding: 2px 4px;
    background-color: $hamsterism-btn-color-secondary-light;
    border-radius: 3px;
  }
  /deep/ img {
    max-width: 100%;
    display: block;
    margin: auto;
  }
  /deep/ .hljs {
    border-radius: 5px;
    padding: 1rem;
    margin: 0.5rem 0;
    background-color: $hamsterism-bg-color-primary;
  }
}
</style>


在編輯頁面的部份,我沒法將highlight.js嵌入vue-quill-editor,故改以在editor外,另新增「預覽畫面」<div>的方式,在送出前來檢視文章編輯情況。



後記

Nuxt官網使用的上色library為Prism


其實由本文中的程式碼上色不難看出,highlight.js的自動判定語言有其缺陷存在


雖然我已限定只有bash、scss、xml、javascript四種語言


但判定上常常會抓錯(按F12看上色區塊被添加的css class可知)


由於我的部落格使用的是透過editor產出的raw html code


目前暫時無法做到指定區塊為特定語言渲染

(也許透過自定義highlight.js語言判定可實現吧?)


只能讓highlight.js統一抓'pre.ql-syntax' 內的結果


若看官們有什麼更好的workaround,歡迎來信交流!

© 2021 Hamsterism. All rights reserved github