Auralinna.blogTero Auralinna's blog about intriguing world of web development.

I'm a Full Stackish developer with a strong passion to a beautiful front end. I have mainly focused on front-end development, responsive web design, back end coding with PHP and Java, Content Management Systems, modern web frameworks and DevOps.

Code syntax highlighting with Angular and Prism.js

28.12.2017

I implemented Prism.js based code syntax highlight feature for my blog. This blog post shows how to use Prism with Angular.

Prism is a lightweight, extensible syntax highlighter, built with modern web standards in mind.

There are few existing Angular solutions for Prism:

But I decided not to use the existing ones because all the solutions use a component which requires code blocks as a content or as a parameter. Content of my blog is fetched from REST API as HTML so I can't (easily) separate code blocks from other content. That's why I decided to see how to implement support for the Prism without existing components. I use Prism's highlightAll method to process all of the pre and code tags once.

Implementing following steps needs a basic knowledge about Angular development.

1. Install Prism from npm

$ npm install prismjs --save

2. Create highlight service

Prism.js dependencies are imported in this service. Here you can add supported languages and additional Prism plugins you might want to use.

import { Injectable, Inject } from '@angular/core';

import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

import 'clipboard';

import 'prismjs';
import 'prismjs/plugins/toolbar/prism-toolbar';
import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-java';
import 'prismjs/components/prism-markup';
import 'prismjs/components/prism-typescript';
import 'prismjs/components/prism-sass';
import 'prismjs/components/prism-scss';

declare var Prism: any;

@Injectable()
export class HighlightService {

  constructor(@Inject(PLATFORM_ID) private platformId: Object) { }

  highlightAll() {
    if (isPlatformBrowser(this.platformId)) {
      Prism.highlightAll();
    }
  }
}

My implementation doesn't support server side rendering at the moment. Code syntax highlighting is enabled only for a browser because Prism.highlightAll uses document which is not available in Node.js. There probably are workarounds for this but I don't see code highlighting that important for server side rendering.

Prism supports 130 languages so I only import the ones I really need.

3. Use highlight service in your component

Then let's add the service into a component which handles data we want to highlight.

Lifecycle hook AfterViewChecked is used here to call the highlight service when view is ready. Method ngAfterViewChecked might be called multiple times. I use highlighted boolean to check if highlighting is already done to prevent multiple highlightAll method calls.

import { Component, OnInit, AfterViewChecked } from '@angular/core';

import { HighlightService } from '../shared/utils/highlight.service';

@Component({
  selector: 'app-blog-post',
  templateUrl: './blog-post.component.html',
  styleUrls: ['./blog-post.component.scss']
})
export class BlogPostComponent implements OnInit, AfterViewChecked {
  
  blogPost: BlogPostInterface;
  highlighted: boolean = false;
  
  constructor(
    ...
    private highlightService: HighlightService) {
  }

  /**
   * Highlight blog post when it's ready
   */
  ngAfterViewChecked() {
    if (this.blogPost && !this.highlighted) {
      this.highlightService.highlightAll();
      this.highlighted = true;
    }
  }

  /**
   * Fetch blog post from API
   */
  ngOnInit() {
    ...
  }
}

This code is just a partial example how to use recently created service in your own component. You need to adapt usage for your custom component.

4. Add Prism styles

Next add Prism styles into your styles.scss. Theme CSS is needed at least. Check my earlier blog post how to change Angular to use SCSS instead of CSS if you don't use SCSS already. Alternatively you can add CSS files directly into your HTML.

@import "~prismjs/plugins/toolbar/prism-toolbar.css";
@import "~prismjs/themes/prism-okaidia";

It should be working now. Please feel free to comment this post if you have questions or suggestions how to improve code base.

Latest blog posts

Latest CodePens

View all CodePens