MUI Docs Infra

Warning

This is an internal project, and is not intended for public use. No support or stability guarantees are provided.

Enhance Code Inline

A rehype plugin that improves the visual appearance of inline <code> elements by wrapping HTML/JSX tag patterns in styled spans and reclassifying misidentified tokens.


Overview

The enhanceCodeInline plugin transforms syntax-highlighted inline code in three ways:

  1. Tag bracket wrapping: Identifies patterns where < or </ precedes a highlighted tag name followed by >, and wraps the entire tag (brackets + tag-name span + any attributes) in a new wrapper span. The original pl-* spans are preserved intact inside — no semantic information is destroyed.
  2. Token reclassification: Corrects misidentified token classes from the upstream syntax highlighter. For example, function is sometimes classified as pl-en (entity name) but should be styled as pl-k (keyword).
  3. Built-in type enhancement (TypeScript only): Reclassifies standalone type keywords like string, number, boolean, and void from pl-smi/pl-k to pl-c1 di-bt, matching the output that extendSyntaxTokens produces for these keywords in type-annotation context.

Wrapper Classes

The wrapper class depends on the inner tag-name span:

Inner classWrapper classMeaning
pl-entdi-htHTML tag (e.g. <div>, <span>)
pl-c1di-jtJSX component tag (e.g. <Box>, <Stack>)

Key Features

  • Wrapper spans: Groups <, tag-name span, attributes, and > under a di-ht or di-jt wrapper without destroying the inner pl-* spans
  • Token reclassification: Fixes misidentified token classes (e.g., function from pl-enpl-k)
  • Built-in type enhancement: Reclassifies standalone TypeScript built-in type keywords (pl-smipl-c1 di-bt), gated to TypeScript languages only
  • Consecutive tag handling: Properly processes multiple tags in sequence like <div><span>
  • Attribute preservation: Maintains all original classes and attributes on inner spans
  • Safe processing: Only modifies inline code, not code blocks within <pre> elements

Installation

This plugin is part of @mui/internal-docs-infra and doesn't need separate installation.


Usage

Basic Usage

import { unified } from 'unified';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';
import enhanceCodeInline from '@mui/internal-docs-infra/pipeline/enhanceCodeInline';

const processor = unified()
  .use(rehypeParse, { fragment: true })
  .use(enhanceCodeInline)
  .use(rehypeStringify);

const result = await processor.process(
  '<code class="language-tsx">&lt;<span class="pl-ent">div</span>&gt;</code>',
);

console.log(String(result));
// Output: <code class="language-tsx"><span class="di-ht">&lt;<span class="pl-ent">div</span>&gt;</span></code>

With transformHtmlCodeInline

This plugin is designed to run after syntax highlighting has been applied:

import transformHtmlCodeInline from '@mui/internal-docs-infra/pipeline/transformHtmlCodeInline';
import enhanceCodeInline from '@mui/internal-docs-infra/pipeline/enhanceCodeInline';

const processor = unified()
  .use(rehypeParse, { fragment: true })
  .use(transformHtmlCodeInline)
  .use(enhanceCodeInline) // Must come after highlighting
  .use(rehypeStringify);

Transformation Examples

HTML Entity Tags (pl-ent → di-ht)

<!-- Input (after syntax highlighting) -->
<code class="language-tsx">&lt;<span class="pl-ent">div</span>&gt;</code>

<!-- Output: wrapped in di-ht, inner pl-ent preserved -->
<code class="language-tsx"
  ><span class="di-ht">&lt;<span class="pl-ent">div</span>&gt;</span></code
>

JSX Component Tags (pl-c1 → di-jt)

<!-- Input -->
<code class="language-tsx">&lt;<span class="pl-c1 di-jsx">Box</span>&gt;</code>

<!-- Output: wrapped in di-jt, inner pl-c1 di-jsx preserved -->
<code class="language-tsx"
  ><span class="di-jt">&lt;<span class="pl-c1 di-jsx">Box</span>&gt;</span></code
>

Closing Tags

<!-- Input -->
<code class="language-tsx">&lt;/<span class="pl-ent">div</span>&gt;</code>

<!-- Output -->
<code class="language-tsx"
  ><span class="di-ht">&lt;/<span class="pl-ent">div</span>&gt;</span></code
>

Multiple Consecutive Tags

<!-- Input -->
<code>&lt;<span class="pl-ent">div</span>&gt;&lt;<span class="pl-c1 di-jsx">Box</span>&gt;</code>

<!-- Output: each gets its own wrapper class -->
<code
  ><span class="di-ht">&lt;<span class="pl-ent">div</span>&gt;</span
  ><span class="di-jt">&lt;<span class="pl-c1 di-jsx">Box</span>&gt;</span></code
>

Tags with Attributes

Tags with attributes are fully supported — everything from the opening < to the closing > or /> is wrapped:

<!-- Input -->
<code>&lt;<span class="pl-c1 di-jsx">Box</span> flag option={true} /&gt;</code>

<!-- Output -->
<code
  ><span class="di-jt"
    >&lt;<span class="pl-c1 di-jsx">Box</span> flag option={true} /&gt;</span
  ></code
>
<!-- Input -->
<code>&lt;<span class="pl-ent">div</span> className="test"&gt;</code>

<!-- Output -->
<code
  ><span class="di-ht">&lt;<span class="pl-ent">div</span> className="test"&gt;</span></code
>

How It Works

Pattern Matching

The plugin looks for this specific pattern in inline code elements:

  1. Text node ending with < or </
  2. Span element with class pl-ent or pl-c1
  3. Text node containing >, />, or />

When all three conditions are met, it wraps the bracket text, the tag-name span, and any trailing text up to the closing bracket into a new wrapper span (di-ht or di-jt).

Processing Flow

Input:  text("<")  +  span.pl-ent("div")  +  text(" className='x'>")
                          ↓
Output: span.di-ht( "<" + span.pl-ent("div") + " className='x'>" )

Queue-Based Processing

The plugin uses a queue-based approach to handle consecutive tags:

  1. Children are placed in a processing queue
  2. When a pattern is matched and enhanced, remaining text after > is re-queued
  3. This allows patterns like ><span> to be processed correctly

Edge Cases

Self-Closing Tags

Self-closing tags are fully supported, with or without a space before />:

<!-- Input: with space -->
<code>&lt;<span class="pl-ent">br</span> /&gt;</code>

<!-- Output -->
<code
  ><span class="di-ht">&lt;<span class="pl-ent">br</span> /&gt;</span></code
>
<!-- Input: without space -->
<code>&lt;<span class="pl-ent">input</span>/&gt;</code>

<!-- Output -->
<code
  ><span class="di-ht">&lt;<span class="pl-ent">input</span>/&gt;</span></code
>

Code Blocks

Code inside <pre> elements is skipped to avoid interfering with block code formatting:

<!-- Input: NOT processed -->
<pre><code>&lt;<span class="pl-ent">div</span>&gt;</code></pre>

<!-- Output: unchanged -->
<pre><code>&lt;<span class="pl-ent">div</span>&gt;</code></pre>

Missing Brackets

Spans without matching brackets are left unchanged:

<!-- Missing < -->
<code><span class="pl-ent">div</span>&gt;</code>
<!-- unchanged -->

<!-- Missing > -->
<code>&lt;<span class="pl-ent">div</span></code>
<!-- unchanged -->

Token Reclassification

The upstream syntax highlighter sometimes assigns the wrong token class. The plugin corrects these using a reclassification map. Currently, function is reclassified from pl-en (entity name) to pl-k (keyword):

<!-- Input -->
<code><span class="pl-en">function</span></code>

<!-- Output -->
<code><span class="pl-k">function</span></code>

This ensures function receives keyword styling rather than entity name styling.

Built-in Type Enhancement (TypeScript only)

Starry Night tokenizes standalone type keywords inconsistently in inline code. When there is no surrounding type context (like a type annotation), keywords like string become pl-smi (identifier) and void becomes pl-k (keyword) — rather than the pl-c1 (constant) they receive in expressions like type x = string.

This plugin reclassifies those tokens to pl-c1 di-bt for TypeScript-family languages (language-ts, language-tsx, language-typescript), matching the behavior of extendSyntaxTokens in block code:

<!-- Input: standalone "string" in TSX inline code -->
<code class="language-tsx"><span class="pl-smi">string</span></code>

<!-- Output: reclassified to pl-c1 di-bt -->
<code class="language-tsx"><span class="pl-c1 di-bt">string</span></code>
<!-- Input: standalone "void" in TSX inline code -->
<code class="language-tsx"><span class="pl-k">void</span></code>

<!-- Output: reclassified to pl-c1 di-bt -->
<code class="language-tsx"><span class="pl-c1 di-bt">void</span></code>

The enhancement is not applied in these cases:

  • Non-TypeScript languages: JavaScript, CSS, or code without a language class are left unchanged
  • void as an operator: When void appears alongside other tokens (e.g., void fn()), it is kept as pl-k since it is the unary void operator, not a type keyword
  • Already pl-c1: Tokens already classified as pl-c1 (e.g., in type x = string) are left for extendSyntaxTokens to handle

Why This Enhancement?

Without this plugin, HTML tags in inline code have their brackets unstyled:

/* Before: only the tag name gets color */
<span class="pl-ent">div</span>  /* colored */
<                               /* default text color */
>                               /* default text color */

/* After: wrapper span allows styling the entire tag */
<span class="di-ht">&lt;<span class="pl-ent">div</span>&gt;</span>

The wrapper span (di-ht or di-jt) lets CSS style the brackets together with the tag name, while the inner pl-* span is preserved for semantic styling. This also lets CSS distinguish HTML tags from JSX component tags.

Token reclassification fixes cases where the upstream highlighter misidentifies tokens — for example, function being styled as an entity name instead of a keyword.


Plugin Order

This plugin should run after other code enhancement plugins:

  1. transformHtmlCodeInline - Applies syntax highlighting
  2. enhanceCodeTypes - Links type references to documentation
  3. enhanceCodeInline - Consolidates tag brackets, reclassifies tokens (this plugin)

Running it earlier would prevent the pattern from matching since the highlighting spans wouldn't exist yet.