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 | string
idOrName: 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 : NameLabel
NameOrId<function (type parameter) T in createLabel<T extends number | string>(idOrName: T): NameOrId<T>
T> {
throw "unimplemented";
}
let let a: NameLabel
a = function createLabel<"typescript">(idOrName: "typescript"): NameLabel
createLabel("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 defineConfig
defineConfig({
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 renderedrenderer: 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 defineConfig
defineConfig({
markdown: {
shikiConfig: {
theme: string;
themes: {
light: string;
dark: string;
};
};
}
markdown: {
shikiConfig: {
theme: string;
themes: {
light: string;
dark: string;
};
}
shikiConfig: {
theme: string
theme: "github-dark",
themes: {
light: string;
dark: string;
}
themes: {
light: string
light: "github-light",
dark: string
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.