Skip to content

Commit 9d29fde

Browse files
authored
Merge pull request #8 from uvenkatateja/feat/add-line-anchors-transformer
feat: add line anchors transformer for shiki
2 parents fb3ec79 + 39aaa3e commit 9d29fde

5 files changed

Lines changed: 135 additions & 0 deletions

File tree

apps/website/src/components/docs/sidebar-data.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
AnchorIcon,
23
CandyIcon,
34
ClipboardIcon,
45
FileCodeCornerIcon,
@@ -133,6 +134,11 @@ export const SidebarLinksData: SidebarLinks[] = [
133134
icon: TextQuoteIcon,
134135
href: "/docs/shiki/meta-highlight",
135136
},
137+
{
138+
title: "Line Anchors",
139+
icon: AnchorIcon,
140+
href: "/docs/shiki/line-anchors",
141+
},
136142
{
137143
title: "Notation Diff",
138144
icon: ListPlusIcon,

apps/website/src/components/registry/data.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,19 @@ const ShikiTransformers: RegistryComponent[] = [
137137
target: "src/utils/shiki/transformers/add-to-pre-element.ts",
138138
},
139139
},
140+
{
141+
title: "Shiki Transformer - Line Anchors",
142+
fileType: "ts",
143+
group: "shiki",
144+
fileSource: `${utilsFolder}/shiki/transformers/line-anchors.ts`,
145+
shadcnRegistry: {
146+
name: "shiki-line-anchors",
147+
type: "registry:lib",
148+
dependencies: ["shiki"],
149+
registryDependencies: ["shiki-css", "shiki-show-line-numbers"],
150+
target: "src/utils/shiki/transformers/line-anchors.ts",
151+
},
152+
},
140153
];
141154

142155
// UI Components:
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
title: Line Anchors
3+
description: Add clickable anchor links to line numbers for easy reference and sharing.
4+
category: [Shiki, Markdown, MDX]
5+
---
6+
7+
<Showcase>
8+
9+
```ts lineNumbers
10+
import { highlight } from "@/utils/shiki/highlight";
11+
import { lineAnchors } from "@/utils/shiki/transformers/line-anchors";
12+
13+
const code = `console.log('Hello World')`;
14+
const highlighter = await highlight();
15+
const html = highlighter.codeToHtml(code, {
16+
lang: "javascript",
17+
transformers: [lineAnchors()],
18+
});
19+
```
20+
21+
</Showcase>
22+
23+
The `lineAnchors` transformer adds clickable anchor links to line numbers. Each line gets an ID like `L1`, `L2`, etc.
24+
25+
## Installation
26+
27+
### shadcn/ui
28+
29+
<CopyShadcnCommand name="shiki-line-anchors" />
30+
31+
### Manual
32+
33+
1. Copy the `lineAnchors` transformer into your project:
34+
35+
<ShowSource component="shiki-line-anchors" />
36+
37+
`shiki-line-anchors` styles are defined in the `shiki.css` file:
38+
39+
<DocCard folder="shiki" document="highlighter" anchor="styles" />
40+
41+
2. Import the transformer in your `rehypeShiki` plugin:
42+
43+
```ts title="Rehype Shiki Options"
44+
import { lineAnchors } from "@/utils/shiki/transformers/line-anchors";
45+
46+
const rehypeShikiOptions: RehypeShikiCoreOptions = {
47+
//...
48+
transformers: [lineAnchors()],
49+
};
50+
51+
export { rehypeShikiOptions };
52+
```
53+
54+
## Usage
55+
56+
Once enabled, users can:
57+
58+
- Click line numbers to navigate to that line
59+
- Share URLs with line anchors: `yoursite.com/docs#L3`
60+
- Link to specific lines: `[See line 5](#L5)`
61+
62+
The clicked line will be highlighted with a blue background and the URL will update to include the line anchor.

apps/website/src/styles/shiki.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,24 @@ pre.shiki-has-focused .line:not(.focused) {
9292
pre.shiki-has-focused:hover .line:not(.focused) {
9393
@apply opacity-100 blur-none;
9494
}
95+
96+
/* Shiki Line Anchors */
97+
pre.shiki-line-anchors {
98+
scroll-margin-top: 2rem;
99+
}
100+
101+
pre.shiki-line-anchors .line:target {
102+
@apply relative inline-block w-full bg-blue-300/15 dark:bg-blue-500/15;
103+
&::before {
104+
content: "";
105+
@apply absolute left-0 top-0 h-full w-1 bg-blue-500 dark:bg-blue-400;
106+
}
107+
}
108+
109+
pre.shiki-line-numbers.shiki-line-anchors code .line::before {
110+
@apply cursor-pointer select-none transition-colors;
111+
}
112+
113+
pre.shiki-line-numbers.shiki-line-anchors code .line::before:hover {
114+
@apply text-blue-500 underline dark:text-blue-400;
115+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { ShikiTransformer } from "shiki";
2+
3+
/**
4+
* Transformer to add anchor links to line numbers
5+
* Allows users to link to specific lines in code blocks
6+
* Usage: Automatically works with lineNumbers transformer
7+
* Result: Each line gets an id like "L1", "L2", etc.
8+
*/
9+
const lineAnchors = (): ShikiTransformer => {
10+
return {
11+
name: "LineAnchors",
12+
line(node, line) {
13+
// Add id attribute to each line for anchor linking
14+
node.properties.id = `L${line}`;
15+
16+
// Add data attribute for styling targeted lines
17+
node.properties["data-line"] = line;
18+
},
19+
pre(node) {
20+
// Add class to enable anchor styling
21+
const existingClass = node.properties.class;
22+
if (Array.isArray(existingClass)) {
23+
existingClass.push("shiki-line-anchors");
24+
} else if (typeof existingClass === "string") {
25+
node.properties.class = `${existingClass} shiki-line-anchors`;
26+
} else {
27+
node.properties.class = "shiki-line-anchors";
28+
}
29+
},
30+
};
31+
};
32+
33+
export { lineAnchors };

0 commit comments

Comments
 (0)