loading...
OverScore Media

Nuxt, Meet Prism

mtpiercey profile image Matthew Piercey Updated on ・4 min read

A deep dive into projects with Nuxt.js (7 Part Series)

1) Nuxt, Meet Vuetify 2) Nuxt, Meet Anime 3 ... 5 3) Nuxt, Meet Disqus 4) Nuxt, Meet Prism 5) Nuxt, Meet Plyr 6) Nuxt, Meet Vue-Picture-Swipe 7) Nuxt, Meet Particles

This article is part of a series on my experiences with Nuxt.js that I built into the nuxt-toolkit by OverScore Media

GitHub logo overscore-media / nuxt-toolkit

A bunch of useful example code snippets for use with Nuxt.js

See a live example at https://nuxt-toolkit.overscore.media! :]


Ah, syntax highlighting. The beauty of code made manifest!

Syntax highlighting can make or break a site in terms of UI, IMO, since all too often I see nasty or downright-broken code blocks on websites that should frankly know better... But every now and then there's something of such pure magic that it makes it all worth it.

There are a bunch of ways of getting syntax highlighting to work with JavaScript. This is one way of many, but it's the way I did it. Take that as you will.

Look into the Prism

Prism is my favourite syntax highlighting library. It's really quite nice when you get it all set up. Admittedly, to get it to work the way I like it, I ended up importing a bunch of CSS and quite a bit of JS that I probably didn't end up needing, and which definitely added to my Nuxt project's bundle size considerably (and it's an absolute nightmare to try to make it play nice with things like PurgeCSS), but... Tradeoffs? I mean, would you rather have a slightly-slower-but-still-fairly-zippy site that looks beautiful or a super-fast site that looks "meh"? I don't know. Fight about it in the comments, I guess? _(ツ)_/¯

Ready?

If you are ready to start, and you want to do it my way for some reason, first import the libraries you'll need to make it happen.

yarn add prismjs clipboard or npm install --save prismjs clipboard

Next, bundle it all up in a Nuxt plugin, like ~/plugins/prism.js. Choose your own Prism theme, language supports, and plugins. Fair warning, there are a lot of them from which to choose. You might be here for a while...

/* eslint-disable no-template-curly-in-string */
/* eslint-disable no-undef */
import 'clipboard' // For the copy to clipboard plugin
import Prism from 'prismjs'
import Vue from 'vue'

// Include a theme:
import 'prismjs/themes/prism-tomorrow.css'

// Include language support: (optional)
import 'prismjs/components/prism-scss'
import 'prismjs/components/prism-markup'
import 'prismjs/components/prism-ruby'

// Include the toolbar plugin: (optional)
import 'prismjs/plugins/toolbar/prism-toolbar'
import 'prismjs/plugins/toolbar/prism-toolbar.css'

// Include the autolinker plugin: (optional)
import 'prismjs/plugins/autolinker/prism-autolinker'
import 'prismjs/plugins/autolinker/prism-autolinker.css'

// Include the line numbers plugin: (optional)
import 'prismjs/plugins/line-numbers/prism-line-numbers'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'

// Include the line highlight plugin: (optional)
import 'prismjs/plugins/line-highlight/prism-line-highlight'
import 'prismjs/plugins/line-highlight/prism-line-highlight.css'

// Include some other plugins: (optional)
import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard'
import 'prismjs/plugins/highlight-keywords/prism-highlight-keywords'
import 'prismjs/plugins/show-language/prism-show-language'
import 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace'

Vue.component('prism', {
  props: {
    lang: {
      type: String,
      default: 'js'
    }
  },
  mounted () {
    Prism.highlightAll()
  },
  template: '<div class="prism"><pre class="line-numbers" :class="`language-${lang}`"><code><slot></slot></code></pre></div>'
})

Next, add it to your nuxt.config.js like so:

// ...
plugins: [
  { src: '~/plugins/prism', mode: client' }
]
// ...

Use it for realsies

Try out something like this to make sure it works:

<prism lang="scss">
.VueToNuxtLogo {
  display: inline-block;
  animation: turn 2s linear forwards 1s;
  transform: rotateX(180deg);
  position: relative;
  overflow: hidden;
  height: 180px;
  width: 245px;
}
</prism>

Caveat(s)

Fair warning - if you're using this to display HTML or any sort of XML-y markup, you may run into issues if you don't put escaped markup inside the <prism> block. Try converting your markup to escaped markup with an online converter or something.

Also, PurgeCSS and Prism don't like each other all that much, so if you happen to be using them together, prepare to have your wonderful styling ripped away by Purge's unrelenting scourge, all in the name of bundle size reduction... Granted, there is probably a ton of unused CSS if you happen to do it this way, but Purge is overly-aggressive. Now, you can add some words to your PurgeCSS whitelist, but honestly it's a mess and I haven't figured out a better solution, and you'll probably have to manually add classes to make things work... Or just don't use Purge (or don't do it this way). Your call. Either way, almost every solution causes new problems, so you can't really avoid making these difficult choices if you want to have some nice things.

  purgeCSS: {
    enabled: true, // True means it's always on in dev/build/generate mode
    // The two below options achieve the happy medium between Prism.js and PurgeCSS
    // If you're having trouble with code highlighting, try adding the pertinent clases to the whitelist
    whitelistPatternsChildren: [/token$/],
    whitelist: [
      'pre', 'code', 'prism', 'line-numbers', 'tag', 'toolbar-item', 'toolbar',
      'code-toolbar', 'span', 'button', 'line-numbers-rows', 'url-link', 'attr-name', 'attr-value', 'punctuation',
      'keyword', 'keyword-let', 'operator', 'string'
    ]
  },

Also, if you're using Vuetify, this code will remove some of the default styling so your code blocks don't look weird:

code {
  box-shadow: 0 !important;
  &::before {
    content: '' !important;
  }
}

Anyway, stay safe and healthy, everybody. Keep on coding!

A deep dive into projects with Nuxt.js (7 Part Series)

1) Nuxt, Meet Vuetify 2) Nuxt, Meet Anime 3 ... 5 3) Nuxt, Meet Disqus 4) Nuxt, Meet Prism 5) Nuxt, Meet Plyr 6) Nuxt, Meet Vue-Picture-Swipe 7) Nuxt, Meet Particles

Posted on by:

mtpiercey profile

Matthew Piercey

@mtpiercey

Christian, entrepreneur, 3D Printing hobbyist, web designer, sci-writer, student, and meme connoisseur.

OverScore Media

OverScore Media is a decentralized design and software development agency. We are a small (but growing) group of passionate coders, makers, and designers dedicated to creating unique, hand-crafted experiences.

Discussion

markdown guide
 

Hey Matthew, thanks for sharing this. I was actually looking into adding Prism to my Gridsome website today and this post saved me a lot of digging through their docs. Cheers!

 

Nice! Yep, it's a jungle out there... Glad I was able to help; good luck with Gridsome!