Skip to main content

Word Highlighting

3 min readStableIntermediate

Wrap a string in forward slashes in the metastring and every occurrence of it inside the block picks up an amber marker. The text between the slashes is matched literally, so you can call out an identifier, a config key, or a whole phrase without learning a pattern syntax.

Quick Start

One identifier, marked everywhere it appears.

TypeScript
TypeScript
const secret = process.env.JWT_SECRET
const encoded = new TextEncoder().encode(secret)
app/features/code/word-highlighting.mdx
MDX
```typescript /secret/
const secret = process.env.JWT_SECRET
const encoded = new TextEncoder().encode(secret)
```

Adding Options

The pattern may contain spaces, so a whole phrase works as well as a single word.

TypeScript
TypeScript
// TODO: wire up the cache
export async function getPage(slug: string) {
  return readFile(`./app/${slug}.mdx`, 'utf-8')
}
app/features/code/word-highlighting.mdx
MDX
```typescript /TODO: wire up the cache/
// TODO: wire up the cache
export async function getPage(slug: string) {
  return readFile(`./app/${slug}.mdx`, 'utf-8')
}
```

Advanced

Matching is by substring and it respects case, which is easy to see in one block: user, userId, and username all light up, while getUser stays plain because of its capital U. Line highlighting and a title work alongside it.

lib/session.ts
TypeScript
const user = await getUser(userId)
const username = user.name
console.log(`signed in as ${username}`)
app/features/code/word-highlighting.mdx
MDX
```typescript {2} title="lib/session.ts" /user/
const user = await getUser(userId)
const username = user.name
console.log(`signed in as ${username}`)
```

Options

/pattern/string

Marks every occurrence of the text between the slashes. The text is treated as a literal string, not a regular expression, so ., *, (, and $ match themselves.

Rules the parser follows

  • The opening slash must sit at the start of the metastring or right after a space, and the closing slash must be followed by a space or the end of the metastring. title="a.ts" /db/ works; /db/expandable does not.
  • The pattern can hold spaces, punctuation, and digits, but never a forward slash or a backslash — those characters end the pattern early.
  • Matching is case-sensitive and unanchored, so user matches inside username. Narrow the pattern when that isn't what you want.
  • Only the first pattern in a metastring is used. In /db/ /cache/, cache is ignored.
  • Every match on every line is marked. There's no per-line form of this option; use line highlighting when you want to emphasize a specific row instead.

Where matching stops

The marker is applied after syntax highlighting, over each run of plain text between the highlighter's tags. Two consequences fall out of that:

  • A pattern that straddles two syntax tokens won't match. new TextEncoder is a keyword followed by a class name, so it is never one run of text — pattern TextEncoder on its own works fine.
  • A pattern containing <, >, or & won't match either, because the highlighter escapes those three characters into HTML entities before the marker runs. Quotes and every other character are left alone and match normally.
Was this page helpful?