Bego Solutions

How I got Synthax Higlighting for Typescript to Work

The problem

I’m a full stack developer and I usually work with elixir, typescript, html and css. My FE framework of choice is Vue.

This blog is built with NimblePublisher which uses markdown and relies on Makeup for synthax highlgithing in code blocks.

Makeup does not support highlighting for Typescript, CSS, SCSS or .vue single file components, 1st or 3rd party.

The research

I looked at what’s available out there first

The makeup base library is part of the elixir_makeup organisation, which owns a few more repositories

I’ll probably be using most of these, but for me to really be happy, I’d need a few more to cover javascript, typscript, css, scss and vue.

So I did some looking around to see what 3rd party addons there are.

Javascript/Typescript

There are actually two libraries

The first one seems to be further ahead, but both are definitely WIP and rarely active, so I’m not sure they are good targets for contribution.

Other languages

There are a few more for other languages, some of which are interesting to me

Some of these are in more advanced state than others.

There is also a cookiecutter (python generator library) template for a makeup lexer

But no CSS, no SCSS, no Typescript and definitely no Vue

makeup_js actually claims it will support typescript in the future, but doesn’t seem to right now. Still, that makes it a good kickoff point, since even as is, it pretty decently highlights.

Milestone 0: Starting makeup_ts

The milestone 1 goal is to fork makeup_js, name it makeup_ts and extend it with types support. I can then offer the fork as a contribution PR to the base library and see if it gets merged, while giving me something to work with.

But before I do that, I find it easier to just work with code locally, so that’s going to be milestone 0 for me and that’s the state I got this code highlighted in.

// basic declarations highlight types
const foo: Foo = 'bar'

// arrow functions are kind of ok (=> is an operator)
const bar = () => undefined

// named functions with types are also ok
function baz (param: number): number {
    return param + 5;
}

// classes work sufficiently for me (I rarely use them)
class SomeClass {
    constructor(params: Foo, otherParams: Bar)
}

// casting using <> works
const a = <string>('c')

const a = 'b' as const
const a = 'b' as 'a' | 'b'

// generics work ok
const generic = <T extends number>(a: T): number => a * 5

/**
 * also multiline comments
 */

It required a bit of tweaking and cleanup of the original .ex file for makeupjs, but it _works so milestone 0 is done.

Milestone 1: Make a fork

The next step is to make this an external library, so that’s exactly what I did.

I forked makeup_js, renamed it to makeup_ts and it’s now available on github.

I also went ahead and published the package on hexdocs at packages/makeup_ts.

It’s rudimentary, but it’s something to start with at least.

Milestone 2: Use it, tweak it, work on it

I have working typescript code higlighing in my blog now, so I’m happy.

The next step for me here is to use it to write more articles, tweak it when I encounter issues and make it faster/better as I go.

For example, with makeup, makeup_elixir and makeup_ts attached to my repo, I seem to get a memory usage spike as the app starts up, so I was forced to add swap to my 256mb fly.io instance to get around it. There’s probably something in makeup_ts causing it.