TIL: Using Twoslash with Shiki and Astro

| View comments on Hacker News

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 function defineConfig(config: AstroUserConfig): AstroUserConfig
See the full Astro Configuration API Documentation https://astro.build/config
defineConfig
({
AstroUserConfig.markdown?: {
    shikiConfig?: Partial<ShikiConfig>;
    syntaxHighlight?: "shiki" | "prism" | false;
    remarkPlugins?: RemarkPlugins;
    rehypePlugins?: RehypePlugins;
    gfm?: boolean;
    smartypants?: boolean;
    remarkRehype?: RemarkRehype;
} | undefined
@docs@kindheading@nameMarkdown Options
markdown
: {
shikiConfig?: Partial<ShikiConfig> | undefined
@docs@namemarkdown.shikiConfig@typeraw{Partial<ShikiConfig>}@descriptionShiki configuration options. See [the Markdown configuration docs](https://docs.astro.build/en/guides/markdown-content/#shiki-configuration) for usage.
shikiConfig
: {
transformers?: ShikiTransformer[] | undefinedtransformers: [ 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 function defineConfig(config: AstroUserConfig): AstroUserConfig
See the full Astro Configuration API Documentation https://astro.build/config
defineConfig
({
AstroUserConfig.markdown?: {
    shikiConfig?: Partial<ShikiConfig>;
    syntaxHighlight?: "shiki" | "prism" | false;
    remarkPlugins?: RemarkPlugins;
    rehypePlugins?: RehypePlugins;
    gfm?: boolean;
    smartypants?: boolean;
    remarkRehype?: RemarkRehype;
} | undefined
@docs@kindheading@nameMarkdown Options
markdown
: {
shikiConfig?: Partial<ShikiConfig> | undefined
@docs@namemarkdown.shikiConfig@typeraw{Partial<ShikiConfig>}@descriptionShiki configuration options. See [the Markdown configuration docs](https://docs.astro.build/en/guides/markdown-content/#shiki-configuration) for usage.
shikiConfig
: {
theme?: ThemePresets | ThemeRegistration | ThemeRegistrationRaw | undefinedtheme: "github-dark", themes?: Record<string, ThemePresets | ThemeRegistration | ThemeRegistrationRaw> | undefinedthemes: { light: "github-light"light: "github-light", dark: "github-dark"dark: "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

Xecast Episode 1: Origins and Techaro

Your browser does not support the audio element.

Download MP3

Also catch Xecast on YouTube (I'll make a proper podcast feed soon, trying to de-scope so I can actually get things done).

<Mimi>

These show notes were generated using Google Gemini 1.5 Pro. Should this podcast take off, we'll find a be...

via Xe Iaso

What can I do if IMlangConvertCharset is unable to convert from code page 28591 directly to UTF-8?

You can do the conversion in two steps using things you already have. The post What can I do if IMlangConvertCharset is unable to convert from code page 28591 directly to UTF-8? appeared first on The Old New Thing.

via The Old New Thing

Swimming in July

Just the pure physical joy of thrashing your arms around in water. To fill the kid’s buckets and throw it at the sun—the way the water falls apart into drops, and then into mist, the way a rainbow appears for a second and is gone.

via Henrik Karlsson