Typescript
Include Typescript compiler's information in your code blocks using Typescript Twoslash.
content.md
```tsconst hi = "Hello"const msg = `${hi}, world`// ^?// @errors: 2588msg = 123```
const = "Hello"const = `${}, world`const msg: "Hello, world"= 123Cannot assign to 'msg' because it is a constant.
Implementation
We use the twoslash library to extract the typescript compiler's information from the code block. For more information, check the twoslash docs.
npm i twoslash
In the Code
component we run typescript and transform twoslash queries and hovers into Code Hike annotations, that then use handlers similar to Callout and Tooltip.
code.tsx
import { RawCode, Pre, highlight, AnnotationHandler } from "codehike/code"import { createTwoslasher } from "twoslash"const twoslasher = createTwoslasher({fsMap: new Map(),compilerOptions: {},})async function Code({ codeblock }: { codeblock: RawCode }) {// run typescript:const { hovers, code, queries, errors } = twoslasher(codeblock.value,codeblock.lang,)// highlight code:const highlighted = await highlight({ ...codeblock, value: code },"github-dark",)hovers.forEach(({ text, line, character, length }) => {highlighted.annotations.push({name: "tooltip",query: text,lineNumber: line + 1,fromColumn: character + 1,toColumn: character + length,})})queries.forEach(({ text, line, character }) => {highlighted.annotations.push({name: "callout",query: text,fromLineNumber: line + 1,toLineNumber: line + 1,data: { character },})})errors.forEach(({ text, line, character }) => {highlighted.annotations.push({name: "callout",query: text,fromLineNumber: line + 1,toLineNumber: line + 1,data: { character, className: "text-red-400" },})})return (<PreclassName=""code={highlighted}handlers={[tooltip, callout]}/>)}import {TooltipProvider,Tooltip,TooltipTrigger,TooltipContent,TooltipArrow,} from "@/components/ui/tooltip"const tooltip: AnnotationHandler = {name: "tooltip",Inline: async ({ children, annotation }) => {const { query, data } = annotationconst highlighted = await highlight({ value: query, lang: "ts", meta: "" },"github-dark",)return (<TooltipProvider delayDuration={300}><Tooltip><TooltipTrigger className="">{children}</TooltipTrigger><TooltipContent className="" sideOffset={0}><Pre code={highlighted} className="" /><TooltipArrow className="" /></TooltipContent></Tooltip></TooltipProvider>)},}const callout: AnnotationHandler = {name: "callout",Block: ({ annotation, children }) => {const { character, className } = annotation.datareturn (<>{children}<divstyle={{ minWidth: `${character + 4}ch` }}className={"w-fit border bg-zinc-900 border-current rounded px-2 relative -ml-[1ch] mt-1 whitespace-break-spaces" +" " +className}><divstyle={{ left: `${character + 1}ch` }}className=""/>{annotation.query}</div></>)},}