Plus ยท CodeHighlight

CodeHighlight

Highlight code blocks in the page according to syntax

When to use

Semi CodeHighlight component is built on Shiki, which uses the same TextMate grammars as VS Code. The languages to highlight are registered by the application, so the bundle only contains the grammars it registers; an unregistered language is shown as plain text. Colors default to Shiki's built-in github-light and github-dark themes, follow Semi's light and dark mode, and can be replaced with other themes.

Demos

How to introduce

import { CodeHighlight } from '@fibrous/semi-ui-solid';

Register languages and themes

Grammars and themes come from the shiki package, so install shiki in the project first. Call CodeHighlight.register once at the application entry: every CodeHighlight can then use those languages.

The code blocks of MarkdownRender, Chat, AIChatDialogue and Sidebar use them too.

A language passed as () => import(...) is fetched when the first code block is highlighted, and then every registered language is fetched, not only the one that block uses. Available languages, their names and aliases are listed in the Shiki language list, and themes in the Shiki theme list. Blocks mounted before the registration highlight again once it happens.

import { CodeHighlight } from '@fibrous/semi-ui-solid';

CodeHighlight.register({
    languages: [() => import('shiki/langs/javascript.mjs'), () => import('shiki/langs/css.mjs')],
    // optional, replaces the default github-light and github-dark
    themes: { light: () => import('shiki/themes/min-light.mjs'), dark: () => import('shiki/themes/nord.mjs') },
});

Basic usage

Pass the code plain text to code, and the name or alias of a registered language to language.


import * as React from 'react'
const Test = ()=>{
    const handleClick = ()=>{
        alert("Click")
    }
    return <div onClick={handleClick}>test</div>
}
Code
import { CodeHighlight } from '@fibrous/semi-ui-solid';

export default function CodeHighlightDemo() {
    return (
        <CodeHighlight
            language="javascript"
            code={`
import * as React from 'react'
const Test = ()=>{
    const handleClick = ()=>{
        alert("Click")
    }
    return <div onClick={handleClick}>test</div>
}`}
        />
    );
}

CSS

.grid {
    .semi-row,
    .semi-row-flex {
        text-align: center;
        .semi-col {
            min-height: 30px;
            line-height: 30px;
            background: var(--semi-color-primary-light-default);
            outline: 1px solid var(--semi-color-primary-light-active);
        }
    }
}
Code
import { CodeHighlight } from '@fibrous/semi-ui-solid';

export default function CodeHighlightDemo() {
    return (
        <CodeHighlight
            language="css"
            code={`.grid {
    .semi-row,
    .semi-row-flex {
        text-align: center;
        .semi-col {
            min-height: 30px;
            line-height: 30px;
            background: var(--semi-color-primary-light-default);
            outline: 1px solid var(--semi-color-primary-light-active);
        }
    }
}
`}
        />
    );
}

Languages for a single block

A language only a few blocks need can be passed to those blocks through languages instead of being registered for the whole application; themes likewise replaces the themes of one block. Declare both values outside the component, so a new array or object on every render does not trigger another highlight. For example, to highlight the Vala language used to write the front-end UI of GTK programs

public class ExampleApp : Gtk.Application {
    public ExampleApp () {
        Object (application_id: "com.example.App");
    }

    public override void activate () {
        var win = new Gtk.ApplicationWindow (this);

        var btn = new Gtk.Button.with_label ("Hello World");
        btn.clicked.connect (win.close);

        win.child = btn;
        win.present ();
    }

    public static int main (string[] args) {
        var app = new ExampleApp ();
        return app.run (args);
    }
}
Code
import { CodeHighlight } from '@fibrous/semi-ui-solid';

const languages = [() => import('shiki/langs/vala.mjs')];

export default function CodeHighlightDemo() {
    return (
        <CodeHighlight
            languages={languages}
            language="vala"
            code={`public class ExampleApp : Gtk.Application {
    public ExampleApp () {
        Object (application_id: "com.example.App");
    }

    public override void activate () {
        var win = new Gtk.ApplicationWindow (this);

        var btn = new Gtk.Button.with_label ("Hello World");
        btn.clicked.connect (win.close);

        win.child = btn;
        win.present ();
    }

    public static int main (string[] args) {
        var app = new ExampleApp ();
        return app.run (args);
    }
}
`}
        />
    );
}

API

Props

PropertyDescriptionTypeDefault
codePlain text of the code, treated as an empty string when omitted. After code changes the new text shows first and is replaced once highlighting finishes.string-
languageLanguage, which must be registered or passed through languages.string-
languagesExtra Shiki grammars for this block; once loaded, other blocks can use them too. Assigning a new array reference highlights the block again.LanguageInput[]-
lineNumberWhether to show line numbers.booleantrue
themesReplaces the Shiki themes of this block for light and dark mode.CodeHighlightThemes-

class, style, ref and native attributes (such as id and aria-label) land on the root div, which stays the same element before and after highlighting.

Static methods

MethodDescriptionType
CodeHighlight.registerRegisters languages for every CodeHighlight and replaces the default themes; can be called repeatedly, languages add up and themes override(options: { languages?: LanguageInput[]; themes?: { light?: ThemeInput; dark?: ThemeInput } }) => void

Accessibility

  • With aria-label or aria-labelledby and no role on the root, the root gets role="group" (a generic element cannot be named); a role you pass wins

Design Tokens