diff --git a/apps/website/src/components/docs/sidebar-data.ts b/apps/website/src/components/docs/sidebar-data.ts index b2c3994..c1e22b3 100644 --- a/apps/website/src/components/docs/sidebar-data.ts +++ b/apps/website/src/components/docs/sidebar-data.ts @@ -1,4 +1,5 @@ import { + AnchorIcon, CandyIcon, ClipboardIcon, FileCodeCornerIcon, @@ -133,6 +134,11 @@ export const SidebarLinksData: SidebarLinks[] = [ icon: TextQuoteIcon, href: "/docs/shiki/meta-highlight", }, + { + title: "Line Anchors", + icon: AnchorIcon, + href: "/docs/shiki/line-anchors", + }, { title: "Notation Diff", icon: ListPlusIcon, diff --git a/apps/website/src/components/registry/data.tsx b/apps/website/src/components/registry/data.tsx index 190f889..01b5f71 100644 --- a/apps/website/src/components/registry/data.tsx +++ b/apps/website/src/components/registry/data.tsx @@ -137,6 +137,19 @@ const ShikiTransformers: RegistryComponent[] = [ target: "src/utils/shiki/transformers/add-to-pre-element.ts", }, }, + { + title: "Shiki Transformer - Line Anchors", + fileType: "ts", + group: "shiki", + fileSource: `${utilsFolder}/shiki/transformers/line-anchors.ts`, + shadcnRegistry: { + name: "shiki-line-anchors", + type: "registry:lib", + dependencies: ["shiki"], + registryDependencies: ["shiki-css", "shiki-show-line-numbers"], + target: "src/utils/shiki/transformers/line-anchors.ts", + }, + }, ]; // UI Components: diff --git a/apps/website/src/docs/shiki/line-anchors.mdx b/apps/website/src/docs/shiki/line-anchors.mdx new file mode 100644 index 0000000..cde768a --- /dev/null +++ b/apps/website/src/docs/shiki/line-anchors.mdx @@ -0,0 +1,62 @@ +--- +title: Line Anchors +description: Add clickable anchor links to line numbers for easy reference and sharing. +category: [Shiki, Markdown, MDX] +--- + + + +```ts lineNumbers +import { highlight } from "@/utils/shiki/highlight"; +import { lineAnchors } from "@/utils/shiki/transformers/line-anchors"; + +const code = `console.log('Hello World')`; +const highlighter = await highlight(); +const html = highlighter.codeToHtml(code, { + lang: "javascript", + transformers: [lineAnchors()], +}); +``` + + + +The `lineAnchors` transformer adds clickable anchor links to line numbers. Each line gets an ID like `L1`, `L2`, etc. + +## Installation + +### shadcn/ui + + + +### Manual + +1. Copy the `lineAnchors` transformer into your project: + + + +`shiki-line-anchors` styles are defined in the `shiki.css` file: + + + +2. Import the transformer in your `rehypeShiki` plugin: + +```ts title="Rehype Shiki Options" +import { lineAnchors } from "@/utils/shiki/transformers/line-anchors"; + +const rehypeShikiOptions: RehypeShikiCoreOptions = { + //... + transformers: [lineAnchors()], +}; + +export { rehypeShikiOptions }; +``` + +## Usage + +Once enabled, users can: + +- Click line numbers to navigate to that line +- Share URLs with line anchors: `yoursite.com/docs#L3` +- Link to specific lines: `[See line 5](#L5)` + +The clicked line will be highlighted with a blue background and the URL will update to include the line anchor. diff --git a/apps/website/src/styles/shiki.css b/apps/website/src/styles/shiki.css index 2b49cd7..aaf4aa3 100644 --- a/apps/website/src/styles/shiki.css +++ b/apps/website/src/styles/shiki.css @@ -92,3 +92,24 @@ pre.shiki-has-focused .line:not(.focused) { pre.shiki-has-focused:hover .line:not(.focused) { @apply opacity-100 blur-none; } + +/* Shiki Line Anchors */ +pre.shiki-line-anchors { + scroll-margin-top: 2rem; +} + +pre.shiki-line-anchors .line:target { + @apply relative inline-block w-full bg-blue-300/15 dark:bg-blue-500/15; + &::before { + content: ""; + @apply absolute left-0 top-0 h-full w-1 bg-blue-500 dark:bg-blue-400; + } +} + +pre.shiki-line-numbers.shiki-line-anchors code .line::before { + @apply cursor-pointer select-none transition-colors; +} + +pre.shiki-line-numbers.shiki-line-anchors code .line::before:hover { + @apply text-blue-500 underline dark:text-blue-400; +} diff --git a/apps/website/src/utils/shiki/transformers/line-anchors.ts b/apps/website/src/utils/shiki/transformers/line-anchors.ts new file mode 100644 index 0000000..f9bc440 --- /dev/null +++ b/apps/website/src/utils/shiki/transformers/line-anchors.ts @@ -0,0 +1,33 @@ +import type { ShikiTransformer } from "shiki"; + +/** + * Transformer to add anchor links to line numbers + * Allows users to link to specific lines in code blocks + * Usage: Automatically works with lineNumbers transformer + * Result: Each line gets an id like "L1", "L2", etc. + */ +const lineAnchors = (): ShikiTransformer => { + return { + name: "LineAnchors", + line(node, line) { + // Add id attribute to each line for anchor linking + node.properties.id = `L${line}`; + + // Add data attribute for styling targeted lines + node.properties["data-line"] = line; + }, + pre(node) { + // Add class to enable anchor styling + const existingClass = node.properties.class; + if (Array.isArray(existingClass)) { + existingClass.push("shiki-line-anchors"); + } else if (typeof existingClass === "string") { + node.properties.class = `${existingClass} shiki-line-anchors`; + } else { + node.properties.class = "shiki-line-anchors"; + } + }, + }; +}; + +export { lineAnchors };