Skip to content

Commit fecddba

Browse files
authored
Merge pull request #398 from code-hike/lighter-annotations
Use lighter annotations
2 parents b016a0c + 4667c0f commit fecddba

20 files changed

+358
-598
lines changed

packages/mdx/dev/content/assets/bar.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
console.log("one")
22
console.log("two")
33
console.log("three")
4+
// mark
45
console.log("four")
56
console.log("five")
67
console.log("six")

packages/mdx/dev/content/comment-annotations.mdx

+47
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,50 @@ function adipiscing(...elit) {
112112
return elit.map(ipsum => ipsum.sit)
113113
}
114114
```
115+
116+
## Inline comments
117+
118+
```css
119+
body {
120+
margin: 12px; /* mark[11:14] */
121+
}
122+
```
123+
124+
## Other syntaxes
125+
126+
```html hello.html
127+
<!-- mark[6:14] -->
128+
<div>Code Hike</div>
129+
```
130+
131+
```mdx
132+
{/* mark(2) */}
133+
134+
# Lorem
135+
136+
## Foo
137+
138+
# Ipsum {/* mark */}
139+
```
140+
141+
```jsonc
142+
{
143+
// mark[12:20]
144+
"name": "Code Hike"
145+
}
146+
```
147+
148+
```lua
149+
-- mark[8:16]
150+
print("Code Hike")
151+
```
152+
153+
```matlab
154+
% mark[7:15]
155+
disp('Code Hike')
156+
```
157+
158+
```lisp
159+
; mark[9:17]
160+
(print "Code Hike")
161+
```

packages/mdx/dev/content/simple-code.mdx

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ graph LR
1414
--> End1(End)
1515
```
1616

17+
```foobar
18+
// unknown lang
19+
function lorem(ipsum, dolor = 1) {
20+
return ipsum + dolor;
21+
}
22+
```
23+
1724
```js
1825
function lorem(ipsum, dolor = 1) {}
1926
```

packages/mdx/dev/content/test.mdx

-6
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,3 @@ function foobarloremipsumfoobarloremipsumsitametfoobarloremipsumfoobarloremipsum
77
return 8
88
}
99
```
10-
11-
<CH.Preview>
12-
13-
Hello
14-
15-
</CH.Preview>

packages/mdx/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"coverage": "vitest run --coverage"
4545
},
4646
"dependencies": {
47-
"@code-hike/lighter": "0.7.0",
47+
"@code-hike/lighter": "0.7.3",
4848
"node-fetch": "^2.0.0"
4949
},
5050
"devDependencies": {

packages/mdx/src/highlighter/index.tsx

-50
This file was deleted.

packages/mdx/src/index.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
export { attacher as remarkCodeHike } from "./remark/transform"
2-
3-
export { highlight } from "./highlighter"

packages/mdx/src/remark/__snapshots__/comment-data.test.ts.snap

-73
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { CodeAnnotation } from "smooth-code"
2+
import {
3+
LighterAnnotation,
4+
extractLighterAnnotations,
5+
parseLighterAnnotations,
6+
} from "./lighter"
7+
import { annotationsMap } from "../mdx-client/annotations"
8+
9+
const annotationNames = Object.keys(annotationsMap)
10+
11+
export async function splitCodeAndAnnotations(
12+
rawCode: string,
13+
lang: string,
14+
config: { filepath?: string; autoLink?: boolean }
15+
): Promise<{
16+
code: string
17+
annotations: CodeAnnotation[]
18+
focus: string
19+
}> {
20+
let { code, annotations } =
21+
await extractLighterAnnotations(rawCode, lang, [
22+
...annotationNames,
23+
"from",
24+
"focus",
25+
])
26+
27+
// import external code if needed and re-run annotations extraction
28+
const fromAnnotations = annotations.filter(
29+
a => a.name === "from"
30+
)
31+
if (fromAnnotations.length === 1) {
32+
const fromData = fromAnnotations[0].query?.trim()
33+
const [codepath, range] = fromData?.split(/\s+/) || []
34+
const externalFileContent = await readFile(
35+
codepath,
36+
config.filepath,
37+
range
38+
)
39+
40+
const result = await extractLighterAnnotations(
41+
externalFileContent,
42+
lang,
43+
[...annotationNames, "focus"]
44+
)
45+
code = result.code
46+
annotations = result.annotations
47+
}
48+
49+
if (config.autoLink) {
50+
const autoLinkAnnotations = findLinkAnnotations(code)
51+
annotations = [...annotations, ...autoLinkAnnotations]
52+
}
53+
54+
return { code, ...parseLighterAnnotations(annotations) }
55+
}
56+
57+
async function readFile(
58+
externalCodePath: string,
59+
mdxFilePath: string,
60+
range: string | undefined
61+
) {
62+
const annotationContent =
63+
"from " + mdxFilePath + " " + (range || "")
64+
65+
let fs, path
66+
67+
try {
68+
fs = (await import("fs")).default
69+
path = (await import("path")).default
70+
if (!fs || !fs.readFileSync || !path || !path.resolve) {
71+
throw new Error("fs or path not found")
72+
}
73+
} catch (e) {
74+
e.message = `Code Hike couldn't resolve this annotation:
75+
${annotationContent}
76+
Looks like node "fs" and "path" modules are not available.`
77+
throw e
78+
}
79+
80+
// if we don't know the path of the mdx file:
81+
if (mdxFilePath == null) {
82+
throw new Error(
83+
`Code Hike couldn't resolve this annotation:
84+
${annotationContent}
85+
Someone is calling the mdx compile function without setting the path.
86+
Open an issue on CodeHike's repo for help.`
87+
)
88+
}
89+
90+
const dir = path.dirname(mdxFilePath)
91+
const absoluteCodepath = path.resolve(
92+
dir,
93+
externalCodePath
94+
)
95+
96+
let content: string
97+
try {
98+
content = fs.readFileSync(absoluteCodepath, "utf8")
99+
} catch (e) {
100+
e.message = `Code Hike couldn't resolve this annotation:
101+
${annotationContent}
102+
${absoluteCodepath} doesn't exist.`
103+
throw e
104+
}
105+
106+
if (range) {
107+
const [start, end] = range.split(":")
108+
const startLine = parseInt(start)
109+
const endLine = parseInt(end)
110+
if (isNaN(startLine) || isNaN(endLine)) {
111+
throw new Error(
112+
`Code Hike couldn't resolve this annotation:
113+
${annotationContent}
114+
The range is not valid. Should be something like:
115+
${externalCodePath} 2:5`
116+
)
117+
}
118+
const lines = content.split("\n")
119+
content = lines.slice(startLine - 1, endLine).join("\n")
120+
}
121+
122+
return content
123+
}
124+
125+
const urlRegex = /https?:\/\/[\w\-_.~:/?#[\]@!$&*+,;=%]+/g
126+
function findLinkAnnotations(
127+
code: string
128+
): LighterAnnotation[] {
129+
const lines = code.split("\n")
130+
131+
const annotations: LighterAnnotation[] = []
132+
133+
lines.forEach((line, i) => {
134+
let match: RegExpExecArray | null
135+
while ((match = urlRegex.exec(line)) !== null) {
136+
const url = match[0]
137+
const start = match.index
138+
const end = start + url.length
139+
140+
annotations.push({
141+
name: "link",
142+
query: url,
143+
ranges: [
144+
{
145+
lineNumber: i + 1,
146+
fromColumn: start + 1,
147+
toColumn: end + 1,
148+
},
149+
],
150+
})
151+
}
152+
})
153+
154+
return annotations
155+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { CodeAnnotation } from "../smooth-code"
2+
import { annotationsMap } from "../mdx-client/annotations"
3+
4+
export function getAnnotationsFromMetastring(
5+
options: Record<string, string>
6+
) {
7+
const annotations = [] as CodeAnnotation[]
8+
Object.keys(options).forEach(key => {
9+
const Component = annotationsMap[key]
10+
if (Component) {
11+
annotations?.push({ focus: options[key], Component })
12+
}
13+
})
14+
return annotations
15+
}

0 commit comments

Comments
 (0)