Skip to content

Commit 6b2cff8

Browse files
committed
Use lighter annotations
1 parent b016a0c commit 6b2cff8

13 files changed

+329
-539
lines changed

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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,44 @@ 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+
# Hello {/* mark */}
133+
```
134+
135+
```jsonc
136+
{
137+
// mark[12:20]
138+
"name": "Code Hike"
139+
}
140+
```
141+
142+
```lua
143+
-- mark[8:16]
144+
print("Code Hike")
145+
```
146+
147+
```matlab
148+
% mark[7:15]
149+
disp('Code Hike')
150+
```
151+
152+
```lisp
153+
; mark[9:17]
154+
(print "Code Hike")
155+
```

packages/mdx/dev/content/test.mdx

Lines changed: 0 additions & 6 deletions
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/src/remark/__snapshots__/comment-data.test.ts.snap

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