TIL: Using Twoslash with Shiki and Astro

Do you want code snippets like below on your Astro site?

Note: you can hover over types to see their definitions.

function function createLabel<T extends number | string>(idOrName: T): NameOrId<T>createLabel<function (type parameter) T in createLabel<T extends number | string>(idOrName: T): NameOrId<T>T extends number | string>(idOrName: T extends number | stringidOrName: function (type parameter) T in createLabel<T extends number | string>(idOrName: T): NameOrId<T>T): type NameOrId<T extends number | string> = T extends number ? IdLabel : NameLabelNameOrId<function (type parameter) T in createLabel<T extends number | string>(idOrName: T): NameOrId<T>T> {
  throw "unimplemented";
}

let let a: NameLabela = function createLabel<"typescript">(idOrName: "typescript"): NameLabelcreateLabel("typescript");

It’s super easy. In your astro.config.ts file, add the following:

import { function rendererRich(options?: RendererRichOptions): TwoslashRenderer
An alternative renderer that providers better prefixed class names, with syntax highlight for the info text.
rendererRich
, function transformerTwoslash(options?: TransformerTwoslashIndexOptions): ShikiTransformer
Factory function to create a Shiki transformer for twoslash integrations.
transformerTwoslash
} from "@shikijs/twoslash";
export default import defineConfigdefineConfig({
markdown: {
    shikiConfig: {
        transformers: ShikiTransformer[];
    };
}
markdown
: {
shikiConfig: {
    transformers: ShikiTransformer[];
}
shikiConfig
: {
transformers: ShikiTransformer[]transformers: [ function transformerTwoslash(options?: TransformerTwoslashIndexOptions): ShikiTransformer
Factory function to create a Shiki transformer for twoslash integrations.
transformerTwoslash
({
TransformerTwoslashOptions.renderer?: TwoslashRenderer | undefined
Custom renderers to decide how each info should be rendered
renderer
: function rendererRich(options?: RendererRichOptions): TwoslashRenderer
An alternative renderer that providers better prefixed class names, with syntax highlight for the info text.
rendererRich
(),
}), ], }, }, });

Import this CSS in your layout:

import "@shikijs/twoslash/style-rich.css";

Add the following CSS and import it in your layout:

// fixes an issue where type popups are cut off
.astro-code {
  overflow: visible !important;
}

Bonus: enable an automatic light & dark mode. Add the following CSS from Shiki’s documentation:

@media (prefers-color-scheme: dark) {
  .shiki,
  .shiki span {
    color: var(--shiki-dark) !important;
    background-color: var(--shiki-dark-bg) !important;
    /* Optional, if you also want font styles */
    font-style: var(--shiki-dark-font-style) !important;
    font-weight: var(--shiki-dark-font-weight) !important;
    text-decoration: var(--shiki-dark-text-decoration) !important;
  }
}

Add the following to your astro.config.ts:

export default import defineConfigdefineConfig({
  
markdown: {
    shikiConfig: {
        theme: string;
        themes: {
            light: string;
            dark: string;
        };
    };
}
markdown
: {
shikiConfig: {
    theme: string;
    themes: {
        light: string;
        dark: string;
    };
}
shikiConfig
: {
theme: stringtheme: "github-dark",
themes: {
    light: string;
    dark: string;
}
themes
: {
light: stringlight: "github-light", dark: stringdark: "github-dark", }, }, }, });

You can try it on this site by toggling your browser’s or operating system’s dark mode.

Check out Shiki’s Twoslash documentation for details.

Recent posts from blogs that I like

Live blog: the 12th day of OpenAI - "Early evals for OpenAI o3"

via Simon Willison

Interiors by Design: Bedrooms

One of the most private areas in a house or apartment, shown here by Degas, Maximilien Luce, Pierre Bonnard, Édouard Vuillard, Eric Ravilious and others.

via The Eclectic Light Company

Things I learned working with artists

As I said in “Lessons I learned working at an art gallery,” I had several observations that I couldn’t fit into that post—so lets continue today.

via Henrik Karlsson