Skip to content

Commit d4ddd98

Browse files
authored
Merge pull request #460 from code-hike/api-reference
Add API reference page
2 parents dd58267 + b173464 commit d4ddd98

File tree

10 files changed

+365
-29
lines changed

10 files changed

+365
-29
lines changed

apps/web/app/docs/[[...slug]]/preview-implementation.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { z } from "zod"
44
import { Demo } from "@/components/demo"
55
import { Pre, RawCode, highlight } from "codehike/code"
66
import { CopyButton } from "@/components/copy-button"
7+
import { ComponentPackLink } from "@/components/component-pack-link"
78

89
const ContentSchema = Block.extend({
910
demo: Block,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ArrowRight } from "lucide-react"
2+
3+
export function ComponentPackLink() {
4+
return (
5+
<div className="border border-pink-500 rounded-lg p-5 my-6 bg-zinc-800">
6+
Don't have time to build it yourself? Get a documentation component
7+
library customized for your tech stack and design system.
8+
<button className="bg-pink-500 text-white rounded-lg px-4 py-1 mt-2 block">
9+
Get the Docs Kit{" "}
10+
<span
11+
className="text-xs ml-2 line-through"
12+
style={{ textDecorationThickness: "2px" }}
13+
>
14+
60% off
15+
</span>{" "}
16+
<ArrowRight size={20} className="inline-block" />
17+
</button>
18+
</div>
19+
)
20+
}

apps/web/content/blog/content-presentation-gap.mdx

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ authors: [pomber]
66
draft: true
77
---
88

9+
import { Demo } from "./content-presentation-gap"
10+
11+
Notice: content means Markdown, presentation means UI components. So, another title could be "The Markdown-React gap".
12+
913
Let's tart with an example.
1014

11-
> demo (roman emperors)
15+
<Demo />
1216

1317
This is a UI pattern commonly referred as scrollytelling, where the content is presented in a way that is tightly coupled with the user's scroll position.
1418

@@ -19,6 +23,8 @@ It's also used for technical content like [Stripe's API reference](https://strip
1923
A component to implement this pattern is not super hard to build, usually it's a combination of an intersection observer and position sticky.
2024

2125
```tsx
26+
import { useEffect, useRef, useState } from "react"
27+
2228
type Props = {
2329
steps: {
2430
content: React.ReactNode
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"use client"
2+
3+
import { useEffect, useRef, useState } from "react"
4+
5+
export function Demo() {
6+
return (
7+
<div className="border">
8+
<Scrollytelling
9+
steps={[
10+
{
11+
content: (
12+
<div>
13+
<h1>Augustus</h1>
14+
<p>
15+
Augustus was the first Roman emperor, reigning from 27 BC
16+
until his death in AD 14.
17+
</p>
18+
</div>
19+
),
20+
sticker: (
21+
<img src="/blog/build-time-components.png" alt="Augustus" />
22+
),
23+
},
24+
{
25+
content: (
26+
<div>
27+
<h1>Nero</h1>
28+
<p>
29+
Nero was the last Roman emperor of the Julio-Claudian dynasty.
30+
</p>
31+
</div>
32+
),
33+
sticker: <img src="/blog/v1.png" alt="Nero" />,
34+
},
35+
{
36+
content: (
37+
<div>
38+
<h1>Trajan</h1>
39+
<p>Trajan was Roman emperor from 98 to 117.</p>
40+
</div>
41+
),
42+
sticker: <img src="/blog/fine-grained-markdown.png" alt="Trajan" />,
43+
},
44+
]}
45+
/>
46+
</div>
47+
)
48+
}
49+
50+
type Props = {
51+
steps: {
52+
content: React.ReactNode
53+
sticker: React.ReactNode
54+
}[]
55+
}
56+
function Scrollytelling({ steps }: Props) {
57+
const [currentStep, setCurrentStep] = useState(0)
58+
const ref = useRef<HTMLDivElement>(null)
59+
60+
useEffect(() => {
61+
const observer = new IntersectionObserver(
62+
([entry]) => {
63+
if (entry.isIntersecting) {
64+
setCurrentStep(parseInt(entry.target.id))
65+
}
66+
},
67+
{
68+
rootMargin: "-48% 0px",
69+
threshold: 0.01,
70+
root: ref.current,
71+
},
72+
)
73+
74+
steps.forEach((_, i) => {
75+
observer.observe(document.getElementById(i.toString())!)
76+
})
77+
78+
return () => observer.disconnect()
79+
}, [])
80+
81+
return (
82+
<div ref={ref} className="flex max-h-64 overflow-auto relative p-4">
83+
<div>
84+
{steps.map((step, i) => (
85+
<div
86+
key={i}
87+
id={i.toString()}
88+
style={{ opacity: i === currentStep ? 1 : 0.2 }}
89+
>
90+
{step.content}
91+
</div>
92+
))}
93+
<div style={{ height: 48 }} />
94+
</div>
95+
<div style={{ position: "sticky", top: 0 }}>
96+
{steps[currentStep].sticker}
97+
</div>
98+
</div>
99+
)
100+
}

apps/web/content/blog/the-curse-of-markdown.mdx

+2-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ Tradeoffs: https://youtu.be/zqhE-CepH2g?si=7iYgDUjAhJNVmYJN&t=446
2525

2626
examples of websites that mdx allow:
2727

28-
- josh's blog
29-
- react docs
28+
- interactive blogs
29+
- interactive docs
3030

3131
---
3232

@@ -36,5 +36,3 @@ Examples are:
3636

3737
- stripe
3838
- swiftui
39-
- nanda
40-
- pudding

apps/web/content/docs/api.mdx

+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
---
2+
title: API Reference
3+
description: Comprehensive list of codehike's API
4+
---
5+
6+
import { Usage } from "./api"
7+
8+
## `codehike/mdx`
9+
10+
```tsx
11+
import { remarkCodeHike, recmaCodeHike } from "codehike/mdx"
12+
```
13+
14+
### `remarkCodeHike`
15+
16+
A remark plugin that transform codeblocks and inline code into the specified components.
17+
18+
- from annotation
19+
- you have to provide the components
20+
21+
```tsx
22+
import { remarkCodeHike, recmaCodeHike } from "codehike/mdx"
23+
24+
/** @type {import('codehike/mdx').CodeHikeConfig} */
25+
const chConfig = {
26+
components: { code: "MyCode", inlineCode: "MyInlineCode" },
27+
ignoreCode: (codeblock) => codeblock.lang === "mermaid",
28+
syntaxHighlighting: { theme: "github-dark" },
29+
}
30+
31+
// what you do with the `mdxOptions` depends on what you use to handle mdx
32+
const mdxOptions = {
33+
remarkPlugins: [[remarkCodeHike, chConfig], ...otherRemarkPlugins],
34+
recmaPlugins: [[recmaCodeHike, chConfig]],
35+
}
36+
```
37+
38+
#### `CodeHikeConfig.components.code`
39+
40+
If you specify a component for `code`, the `remarkCodeHike` plugin will replace code blocks with that component. The language, meta, and value of the code block will be passed inside a `codeblock` prop.
41+
42+
<Usage>
43+
44+
## !caption
45+
46+
How `remarkCodeHike` compiles codeblocks using the `code` component
47+
48+
## !left
49+
50+
```tsx your-config.js
51+
const chConfig = {
52+
// !mark[/MyCode/] 1
53+
components: { code: "MyCode" },
54+
}
55+
```
56+
57+
{/* prettier-ignore */}
58+
````mdx content.mdx
59+
# Hello
60+
61+
{/* !mark[/js|lorem ipsum|console.log\(1\)/gm] 5 */}
62+
```js lorem ipsum
63+
console.log(1)
64+
```
65+
````
66+
67+
## !right
68+
69+
{/* prettier-ignore */}
70+
```jsx compiled output -w
71+
export default function Content(props = {}) {
72+
// !mark[/MyCode/gm] 1
73+
// !mark[/js|lorem ipsum|console.log\(1\)/gm] 5
74+
const { MyCode } = props.components
75+
return (
76+
<>
77+
<h1>Hello</h1>
78+
<MyCode codeblock={{
79+
lang: "js",
80+
meta: "lorem ipsum",
81+
value: "console.log(1)"
82+
}} />
83+
</>
84+
)
85+
}
86+
```
87+
88+
</Usage>
89+
90+
FAQ
91+
92+
- how to pass the components to the `Content` component?
93+
- how to syntax highlight the code?
94+
95+
#### `CodeHikeConfig.components.inlineCode`
96+
97+
If you specify a component for `inlineCode`, the `remarkCodeHike` plugin will replace inline code with that component. The value of the inline code will be passed inside a `codeblock` prop.
98+
99+
Code Hike uses a special syntax to define inline code ``_`code`_``. This syntax also allows you to specify the language and meta for inline code ``_py lorem ipsum`print 5`_``, will give you _`{lang: "py", meta: "lorem ipsum", value: "print 5"}`_.
100+
101+
<Usage>
102+
103+
## !caption
104+
105+
How `remarkCodeHike` compiles inline code using the `inlineCode` component
106+
107+
## !left
108+
109+
```tsx your-config.js
110+
const chConfig = {
111+
// !mark[/MyInlineCode/] 1
112+
components: { inlineCode: "MyInlineCode" },
113+
}
114+
```
115+
116+
{/* prettier-ignore */}
117+
````mdx content.mdx -w
118+
# Hello
119+
120+
Case 1: `var x = 10`
121+
122+
Case 2: _`var x = 10`_
123+
124+
Case 3: _css`a { color: #123 }`_
125+
````
126+
127+
## !right
128+
129+
{/* prettier-ignore */}
130+
```jsx compiled output -w
131+
export default function Content(props = {}) {
132+
// !mark[/MyInlineCode/gm] 1
133+
const { MyInlineCode } = props.components
134+
return (
135+
<>
136+
<h1>Hello</h1>
137+
<p>Case 1: <code>var x = 10</code></p>
138+
<p>Case 2:
139+
<MyInlineCode codeblock={{
140+
lang: "jsx",
141+
value: "var x = 10"
142+
}} />
143+
</p>
144+
<p>Case 3:
145+
<MyInlineCode codeblock={{
146+
lang: "css",
147+
value: "a { color: #123 }"
148+
}} />
149+
</p>
150+
</>
151+
)
152+
}
153+
```
154+
155+
</Usage>
156+
157+
#### `CodeHikeConfig.ignoreCode`
158+
159+
#### `CodeHikeConfig.syntaxHighlighting`
160+
161+
### `recmaCodeHike`
162+
163+
A recma plugin that parses code hike blocks.
164+
165+
## `codehike`
166+
167+
```tsx
168+
import { parse } from "codehike"
169+
```
170+
171+
## `codehike/blocks`
172+
173+
```tsx
174+
import {
175+
parseRoot,
176+
parseProps,
177+
Block,
178+
CodeBlock,
179+
HighlightedCodeBlock,
180+
ImageBlock,
181+
} from "codehike/blocks"
182+
```
183+
184+
## `codehike/code`
185+
186+
```tsx
187+
import {
188+
highlight,
189+
Pre,
190+
Inline,
191+
InnerPre,
192+
InnerLine,
193+
InnerToken,
194+
getPreRef,
195+
} from "codehike/code"
196+
```
197+
198+
## `codehike/utils`
199+
200+
```tsx
201+
import {
202+
SelectionProvider,
203+
Selectable,
204+
Selection,
205+
useSelectedIndex,
206+
} from "codehike/utils/selection"
207+
208+
import {
209+
TokenTransitionsSnapshot,
210+
calculateTransitions,
211+
getStartingSnapshot,
212+
} from "codehike/utils/token-transitions"
213+
```

0 commit comments

Comments
 (0)