forked from code-hike/codehike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2.transform-code.ts
More file actions
102 lines (89 loc) · 2.62 KB
/
Copy path2.transform-code.ts
File metadata and controls
102 lines (89 loc) · 2.62 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
102
import { Code, Root } from "mdast"
import { visit } from "unist-util-visit"
import { getObjectAttribute } from "./estree.js"
import { parseCode } from "./1.1.remark-list-to-section.js"
import { CodeHikeConfig } from "./config.js"
export async function transformAllCode(tree: Root, config: CodeHikeConfig) {
const newTree = await transformAllInlineCode(tree, config)
return transformAllCodeBlocks(newTree, config)
}
async function transformAllCodeBlocks(tree: Root, config: CodeHikeConfig) {
if (!config.components?.code) {
return tree
}
const nodes: Code[] = []
visit(tree, "code", (node) => {
if (config?.ignoreCode && config.ignoreCode(node as any)) {
// ignoring this codeblock
return
}
nodes.push(node)
})
await Promise.all(
nodes.map(async (code: any) => {
Object.assign(code, {
type: "mdxJsxFlowElement",
name: config?.components?.code || "Code",
attributes: [
{
type: "mdxJsxAttribute",
name: "codeblock",
value: getObjectAttribute(await parseCode(code, config)),
},
],
children: [],
})
delete code.value
delete code.lang
delete code.meta
}),
)
return tree
}
async function transformAllInlineCode(tree: Root, config: CodeHikeConfig) {
if (!config.components?.inlineCode) {
return tree
}
const promises: Promise<void>[] = []
visit(tree, "emphasis", (node) => {
if (
// only nodes with one inlineCode child and maybe some text nodes
!node.children ||
node.children.filter((c) => c.type === "inlineCode").length !== 1 ||
node.children.some((c) => c.type !== "inlineCode" && c.type !== "text")
) {
return
}
const text = node.children
.filter((c) => c.type === "text")
.map((c: any) => c.value)
.join(" ")
const codeNode = node.children.find((c) => c.type === "inlineCode") as any
const value = codeNode?.value || ""
// split the first word from the rest
const lang = text.split(/\s+/)[0]
const meta = text.slice(lang.length).trim()
promises.push(
(async () => {
const code = await parseCode(
{ value, lang: lang || "jsx", meta },
config,
)
Object.assign(node, {
type: "mdxJsxTextElement",
name: config.components!.inlineCode,
attributes: [
{
type: "mdxJsxAttribute",
name: "codeblock",
value: getObjectAttribute(code),
},
],
children: [],
})
})(),
)
})
await Promise.all(promises)
return tree
}