Skip to content

Commit f9480c0

Browse files
authored
Merge pull request #358 from code-hike/autolink
Autolink option
2 parents 4c8f649 + 345ae60 commit f9480c0

File tree

7 files changed

+78
-2
lines changed

7 files changed

+78
-2
lines changed

packages/mdx/dev/content/autolink.mdx

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
```py
2+
import requests
3+
4+
# URL: https://api.example.com/data
5+
# Invalid URL: http://invalid_domain.123
6+
urls = ["https://typicode.com/todos/1", "https://typicode.com/todos/2"]
7+
responses = [requests.get(url) for url in urls]
8+
```
9+
10+
<CH.Code lineNumbers={true} autoLink={false}>
11+
12+
```ruby mark=3:5
13+
require 'net/http'
14+
15+
url = URI.parse('https://www.ruby-lang.org/en/')
16+
url = URI.parse 'https://www.ruby-lang.org/en/'
17+
url = URI.parse 'https://www.ruby-lang.org/en/'asdasd;
18+
response = Net::HTTP.get_response(url)
19+
puts response.body
20+
```
21+
22+
</CH.Code>

packages/mdx/dev/files.ts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export async function getCode(file: any, config = {}) {
3636
autoImport: false,
3737
skipLanguages: ["", "mermaid"],
3838
showCopyButton: true,
39+
autoLink: true,
3940
theme,
4041
...config,
4142
},

packages/mdx/src/remark/annotations.ts

+44-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { wrapChildren } from "./to-estree"
44
import { annotationsMap } from "../mdx-client/annotations"
55
import { JsxNode as JsxNode, SuperNode } from "./nodes"
66
import { getCommentData } from "./comment-data"
7+
import { CodeHikeConfig } from "./config"
78

89
export function getAnnotationsFromMetastring(
910
options: Record<string, string>
@@ -18,7 +19,10 @@ export function getAnnotationsFromMetastring(
1819
return annotations
1920
}
2021

21-
export function extractAnnotationsFromCode(code: Code) {
22+
export function extractAnnotationsFromCode(
23+
code: Code,
24+
config: CodeHikeConfig
25+
) {
2226
const { lines } = code
2327
let lineNumber = 1
2428
const annotations = [] as CodeAnnotation[]
@@ -50,9 +54,48 @@ export function extractAnnotationsFromCode(code: Code) {
5054
lineNumber++
5155
}
5256
}
57+
58+
// extract links
59+
if (config.autoLink) {
60+
lineNumber = 1
61+
while (lineNumber <= lines.length) {
62+
const line = lines[lineNumber - 1]
63+
const lineContent = line.tokens
64+
.map(t => t.content)
65+
.join("")
66+
67+
const urls = extractURLsFromLine(lineContent)
68+
urls.forEach(({ url, start, end }) => {
69+
const Component = annotationsMap["link"]
70+
const focus = `${lineNumber}[${start + 1}:${end}]`
71+
annotations.push({
72+
Component,
73+
focus,
74+
data: url,
75+
})
76+
})
77+
lineNumber++
78+
}
79+
}
5380
return [annotations, focusList.join(",")] as const
5481
}
5582

83+
const urlRegex = /https?:\/\/[\w\-_.~:/?#[\]@!$&*+,;=%]+/g
84+
function extractURLsFromLine(line: string) {
85+
const urls = []
86+
let match: RegExpExecArray | null
87+
88+
while ((match = urlRegex.exec(line)) !== null) {
89+
const url = match[0]
90+
const start = match.index
91+
const end = start + url.length
92+
93+
urls.push({ url, start, end })
94+
}
95+
96+
return urls
97+
}
98+
5699
export function extractJSXAnnotations(
57100
node: SuperNode,
58101
index: number,

packages/mdx/src/remark/code.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ async function mapFile(
130130
code = await getCodeFromExternalFileIfNeeded(code, config)
131131

132132
const [commentAnnotations, commentFocus] =
133-
extractAnnotationsFromCode(code)
133+
extractAnnotationsFromCode(code, config)
134134

135135
const options = parseMetastring(
136136
typeof node.meta === "string" ? node.meta : ""

packages/mdx/src/remark/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type CodeHikeConfig = {
55
skipLanguages: string[]
66
showExpandButton?: boolean
77
showCopyButton?: boolean
8+
autoLink?: boolean
89
staticMediaQuery?: string
910
// path to the current file, internal use only
1011
filepath?: string

playground/src/app.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ function App() {
2929
config: {
3030
lineNumbers: false,
3131
showCopyButton: false,
32+
autoLink: false,
3233
theme: "material-darker",
3334
},
3435
};

playground/src/editor.jsx

+8
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ function ConfigEditor({ config, onChange }) {
104104
/>
105105
Copy Button
106106
</label>
107+
<label>
108+
<input
109+
type="checkbox"
110+
checked={config.autoLink}
111+
onChange={(e) => onChange({ ...config, autoLink: e.target.checked })}
112+
/>
113+
Auto Link
114+
</label>
107115
<label>
108116
Theme:
109117
<br />

0 commit comments

Comments
 (0)