forked from code-hike/codehike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpre.tsx
More file actions
101 lines (92 loc) · 2.6 KB
/
Copy pathpre.tsx
File metadata and controls
101 lines (92 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { forwardRef } from "react"
import {
AnnotationHandler,
CodeAnnotation,
InlineProps,
PreComponent,
Tokens,
isBlockAnnotation,
isInlineAnnotation,
} from "./types.js"
import { AddRefIfNedded } from "./pre-ref.js"
import { renderLines } from "./block.js"
import { toLineGroups, toLines } from "./lines.js"
import { InnerPre } from "./inner.js"
export const Inline = ({ code, ...rest }: InlineProps) => {
let { tokens } = code
if (!tokens) {
throw new Error(
"Missing tokens in inline code. Use the `highlight` function to generate the tokens.",
)
}
return (
<code {...rest}>
{tokens.map((t, i) => {
if (typeof t === "string") {
return t
}
const [value, color, rest = {}] = t
return (
<span key={i} style={{ color, ...rest }}>
{value}
</span>
)
})}
</code>
)
}
export const Pre: PreComponent = forwardRef(
({ code, handlers = [], ...rest }, ref) => {
let { tokens, themeName, lang, annotations } = code
if (!tokens) {
throw new Error(
"Missing tokens in code block. Use the `highlight` function to generate the tokens.",
)
}
handlers
.filter((c) => c.transform)
.forEach((c) => {
annotations = annotations.flatMap((a) =>
c.name != a.name ? a : c.transform!(a as any) || [],
)
})
const annotationNames = new Set(annotations.map((a) => a.name))
const hs = handlers.filter(
(h) => !h.onlyIfAnnotated || annotationNames.has(h.name),
)
const stack = buildPreStack(hs)
const merge = { _stack: stack, _ref: ref as any }
return (
<InnerPre merge={merge} data-theme={themeName} data-lang={lang} {...rest}>
<PreContent tokens={tokens} handlers={hs} annotations={annotations} />
</InnerPre>
)
},
)
function PreContent({
tokens,
handlers,
annotations,
}: {
tokens: Tokens
handlers: AnnotationHandler[]
annotations: CodeAnnotation[]
}) {
const lines = toLines(tokens)
const blockAnnotations = annotations.filter(isBlockAnnotation)
const inlineAnnotations = annotations.filter(isInlineAnnotation)
const groups = toLineGroups(lines, blockAnnotations)
return renderLines({
linesOrGroups: groups,
handlers,
inlineAnnotations,
})
}
function buildPreStack(handlers: AnnotationHandler[]) {
const noRefStack = handlers.map(({ Pre }) => Pre!).filter(Boolean)
const refStack = handlers.map(({ PreWithRef }) => PreWithRef!).filter(Boolean)
if (refStack.length > 0) {
refStack.unshift(AddRefIfNedded as any)
}
return [...noRefStack, ...refStack]
}