TIL: Using Twoslash with Shiki and Astro
| View comments on Hacker NewsDo 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 function defineConfig(config: AstroUserConfig): AstroUserConfig
See the full Astro Configuration API Documentation
https://astro.build/configdefineConfig({
AstroUserConfig.markdown?: {
shikiConfig?: Partial<ShikiConfig>;
syntaxHighlight?: "shiki" | "prism" | false;
remarkPlugins?: RemarkPlugins;
rehypePlugins?: RehypePlugins;
gfm?: boolean;
smartypants?: boolean;
remarkRehype?: RemarkRehype;
} | undefined
markdown: {
shikiConfig?: Partial<ShikiConfig> | undefined
shikiConfig: {
transformers?: ShikiTransformer[] | undefined
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 function defineConfig(config: AstroUserConfig): AstroUserConfig
See the full Astro Configuration API Documentation
https://astro.build/configdefineConfig({
AstroUserConfig.markdown?: {
shikiConfig?: Partial<ShikiConfig>;
syntaxHighlight?: "shiki" | "prism" | false;
remarkPlugins?: RemarkPlugins;
rehypePlugins?: RehypePlugins;
gfm?: boolean;
smartypants?: boolean;
remarkRehype?: RemarkRehype;
} | undefined
markdown: {
shikiConfig?: Partial<ShikiConfig> | undefined
shikiConfig: {
theme?: ThemePresets | ThemeRegistration | ThemeRegistrationRaw | undefined
theme: "github-dark",
themes?: Record<string, ThemePresets | ThemeRegistration | ThemeRegistrationRaw> | undefined
themes: {
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.