javascript 50 lines · 8 steps

Building a syntax highlighter tokenizer

A prioritized list of anchored regexes turns source code into typed tokens, then wraps each in a styled span.

Explained by highlit
1const TOKEN_SPECS = [
2 ["comment", /^\/\/[^\n]*|^\/\*[\s\S]*?\*\//],
3 ["string", /^"(?:\\.|[^"\\])*"|^'(?:\\.|[^'\\])*'|^`(?:\\.|[^`\\])*`/],
4 ["number", /^0[xX][\da-fA-F]+|^\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/],
5 ["keyword", /^\b(?:const|let|var|function|return|if|else|for|while|class|new|import|export|from|await|async)\b/],
6 ["boolean", /^\b(?:true|false|null|undefined)\b/],
7 ["identifier", /^[A-Za-z_$][\w$]*/],
8 ["operator", /^[+\-*/%=<>!&|^~?:]+/],
9 ["punctuation", /^[{}()\[\];,.]/],
10 ["whitespace", /^\s+/],
11];
12 
13const ESCAPES = { "&": "&amp;", "<": "&lt;", ">": "&gt;" };
14const escapeHtml = (str) => str.replace(/[&<>]/g, (c) => ESCAPES[c]);
15 
16function tokenize(source) {
17 const tokens = [];
18 let rest = source;
19 
20 while (rest.length > 0) {
21 let matched = false;
22 
23 for (const [type, pattern] of TOKEN_SPECS) {
24 const match = pattern.exec(rest);
25 if (!match) continue;
26 
27 tokens.push({ type, value: match[0] });
28 rest = rest.slice(match[0].length);
29 matched = true;
30 break;
31 }
32 
33 if (!matched) {
34 tokens.push({ type: "unknown", value: rest[0] });
35 rest = rest.slice(1);
36 }
37 }
38 
39 return tokens;
40}
41 
42function highlight(source) {
43 return tokenize(source)
44 .map(({ type, value }) =>
45 type === "whitespace"
46 ? value
47 : `<span class="tok-${type}">${escapeHtml(value)}</span>`
48 )
49 .join("");
50}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Ordering token rules by specificity lets earlier, greedier patterns win before broader ones can misclassify input.
  2. 2Anchoring every regex with ^ and slicing the matched length turns pattern matching into a forward-consuming scanner.
  3. 3Always escape user text before injecting it into HTML, even inside a display-only tool.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a syntax highlighter tokenizer — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code