@@ -4,12 +4,12 @@ import { transformSections } from "./section"
4
4
import { transformSpotlights } from "./spotlight"
5
5
import { transformScrollycodings } from "./scrollycoding"
6
6
import { transformSlideshows } from "./slideshow"
7
+ import { transformInlineCodes } from "./inline-code"
8
+ import { transformPreviews } from "./preview"
9
+
7
10
import { valueToEstree } from "./to-estree"
8
11
import { CH_CODE_CONFIG_VAR_NAME } from "./unist-utils"
9
- import { transformPreviews } from "./preview"
10
- import { transformInlineCodes } from "./inline-code"
11
- import { EsmNode , SuperNode , visit } from "./nodes"
12
- import { chUsage } from "./ch-usage"
12
+ import { JsxNode , SuperNode , visit } from "./nodes"
13
13
14
14
type CodeHikeConfig = {
15
15
theme : any
@@ -18,66 +18,93 @@ type CodeHikeConfig = {
18
18
showCopyButton ?: boolean
19
19
}
20
20
21
- export function remarkCodeHike (
22
- unsafeConfig : CodeHikeConfig
23
- ) {
21
+ const transforms = [
22
+ transformPreviews ,
23
+ transformScrollycodings ,
24
+ transformSpotlights ,
25
+ transformSlideshows ,
26
+ transformSections ,
27
+ transformInlineCodes ,
28
+ transformEditorNodes ,
29
+ transformCodeNodes ,
30
+ ]
31
+
32
+ export function transform ( unsafeConfig : CodeHikeConfig ) {
24
33
return async ( tree : SuperNode ) => {
25
34
const config = addConfigDefaults ( unsafeConfig )
26
- // TODO add opt-in config
27
- let hasCodeHikeImport = false
28
- visit ( tree , "mdxjsEsm" , ( node : EsmNode ) => {
29
- if (
30
- node . value . startsWith (
31
- `import { CH } from "@code-hike/mdx`
32
- )
33
- ) {
34
- hasCodeHikeImport = true
35
- }
36
- } )
37
35
38
36
try {
39
- await transformPreviews ( tree )
40
- await transformScrollycodings ( tree , config )
41
- await transformSpotlights ( tree , config )
42
- await transformSlideshows ( tree , config )
43
- await transformSections ( tree , config )
44
- await transformInlineCodes ( tree , config )
45
- await transformEditorNodes ( tree , config )
46
- await transformCodeNodes ( tree , config )
37
+ for ( const transform of transforms ) {
38
+ await transform ( tree , config )
39
+ }
47
40
} catch ( e ) {
48
41
console . error ( "error running remarkCodeHike" , e )
49
42
throw e
50
43
}
51
44
52
- const usage = chUsage ( tree )
45
+ const usedCodeHikeComponents =
46
+ getUsedCodeHikeComponentNames ( tree )
53
47
54
- if ( usage . length > 0 ) {
48
+ if ( usedCodeHikeComponents . length > 0 ) {
55
49
addConfig ( tree , config )
56
50
57
- if ( config . autoImport && ! hasCodeHikeImport ) {
58
- addSmartImport ( tree , usage )
51
+ if ( config . autoImport ) {
52
+ addSmartImport ( tree , usedCodeHikeComponents )
59
53
}
60
54
}
61
55
}
62
56
}
63
57
58
+ /**
59
+ * Add defaults and normalize config
60
+ */
64
61
function addConfigDefaults (
65
62
config : Partial < CodeHikeConfig > | undefined
66
63
) : CodeHikeConfig {
64
+ // TODO warn when config looks weird
67
65
return {
68
66
...config ,
69
67
theme : config ?. theme || { } ,
70
68
autoImport : config ?. autoImport === false ? false : true ,
71
69
}
72
70
}
73
71
72
+ /**
73
+ * Returns a the list of component names
74
+ * used inside the tree
75
+ * that looks like `<CH.* />`
76
+ */
77
+ function getUsedCodeHikeComponentNames (
78
+ tree : SuperNode
79
+ ) : string [ ] {
80
+ const usage = [ ]
81
+ visit (
82
+ tree ,
83
+ [ "mdxJsxFlowElement" , "mdxJsxTextElement" ] ,
84
+ ( node : JsxNode ) => {
85
+ if (
86
+ node . name &&
87
+ node . name . startsWith ( "CH." ) &&
88
+ ! usage . includes ( node . name )
89
+ ) {
90
+ usage . push ( node . name )
91
+ }
92
+ }
93
+ )
94
+ return usage
95
+ }
96
+
97
+ /**
98
+ * Creates a `chCodeConfig` variable node in the tree
99
+ * so that the components can access the config
100
+ */
74
101
function addConfig (
75
102
tree : SuperNode ,
76
103
config : CodeHikeConfig
77
104
) {
78
105
tree . children . unshift ( {
79
106
type : "mdxjsEsm" ,
80
- value : " export const chCodeConfig = {}" ,
107
+ value : ` export const ${ CH_CODE_CONFIG_VAR_NAME } = {}` ,
81
108
data : {
82
109
estree : {
83
110
type : "Program" ,
@@ -108,10 +135,17 @@ function addConfig(
108
135
} )
109
136
}
110
137
111
- function addSmartImport ( tree : SuperNode , usage : string [ ] ) {
138
+ /**
139
+ * Add an import node at the start of the tree
140
+ * importing all the components used
141
+ */
142
+ function addSmartImport (
143
+ tree : SuperNode ,
144
+ componentNames : string [ ]
145
+ ) {
112
146
const specifiers = [
113
147
"annotations" ,
114
- ...usage . map ( name => name . slice ( "CH." . length ) ) ,
148
+ ...componentNames . map ( name => name . slice ( "CH." . length ) ) ,
115
149
]
116
150
117
151
tree . children . unshift ( {
@@ -202,41 +236,3 @@ function addSmartImport(tree: SuperNode, usage: string[]) {
202
236
} ,
203
237
} )
204
238
}
205
-
206
- function addImportNode ( tree : SuperNode ) {
207
- tree . children . unshift ( {
208
- type : "mdxjsEsm" ,
209
- value :
210
- 'import { CH } from "@code-hike/mdx/dist/components.cjs.js"' ,
211
- data : {
212
- estree : {
213
- type : "Program" ,
214
- body : [
215
- {
216
- type : "ImportDeclaration" ,
217
- specifiers : [
218
- {
219
- type : "ImportSpecifier" ,
220
- imported : {
221
- type : "Identifier" ,
222
- name : "CH" ,
223
- } ,
224
- local : {
225
- type : "Identifier" ,
226
- name : "CH" ,
227
- } ,
228
- } ,
229
- ] ,
230
- source : {
231
- type : "Literal" ,
232
- value :
233
- "@code-hike/mdx/dist/components.cjs.js" ,
234
- raw : '"@code-hike/mdx/dist/components.cjs.js"' ,
235
- } ,
236
- } ,
237
- ] ,
238
- sourceType : "module" ,
239
- } ,
240
- } ,
241
- } )
242
- }
0 commit comments