@@ -5,10 +5,14 @@ import {VFile} from 'vfile'
5
5
import { VFileMessage } from 'vfile-message'
6
6
import { statistics } from 'vfile-statistics'
7
7
import { reporter } from 'vfile-reporter'
8
- import { evaluate } from '@mdx-js/mdx'
8
+ import { evaluate , nodeTypes } from '@mdx-js/mdx'
9
9
import remarkGfm from 'remark-gfm'
10
+ import rehypeRaw from 'rehype-raw'
10
11
import remarkFrontmatter from 'remark-frontmatter'
12
+ import remarkDirective from 'remark-directive'
11
13
import remarkMath from 'remark-math'
14
+ import { visit as visitEstree } from 'estree-util-visit'
15
+ import { removePosition } from 'unist-util-remove-position'
12
16
import CodeMirror from 'rodemirror'
13
17
import { basicSetup } from 'codemirror'
14
18
import { markdown as langMarkdown } from '@codemirror/lang-markdown'
@@ -29,30 +33,41 @@ function useMdx(defaults) {
29
33
const [ state , setState ] = useState ( { ...defaults , file : null } )
30
34
const { run : setConfig } = useDebounceFn (
31
35
async ( config ) => {
32
- const file = new VFile ( { basename : 'example.mdx' , value : config . value } )
36
+ const basename = config . formatMd ? 'example.md' : 'example.mdx'
37
+ const file = new VFile ( { basename, value : config . value } )
33
38
34
39
const capture = ( name ) => ( ) => ( tree ) => {
35
40
file . data [ name ] = tree
36
41
}
37
42
38
43
const remarkPlugins = [ ]
39
-
40
44
if ( config . gfm ) remarkPlugins . push ( remarkGfm )
41
45
if ( config . frontmatter ) remarkPlugins . push ( remarkFrontmatter )
42
46
if ( config . math ) remarkPlugins . push ( remarkMath )
43
-
47
+ if ( config . directive ) remarkPlugins . push ( remarkDirective )
44
48
remarkPlugins . push ( capture ( 'mdast' ) )
45
49
50
+ const rehypePlugins = [ ]
51
+ if ( config . rehypeRaw )
52
+ rehypePlugins . push ( [ rehypeRaw , { passThrough : nodeTypes } ] )
53
+ rehypePlugins . push ( capture ( 'hast' ) )
54
+
46
55
try {
47
56
file . result = (
48
57
await evaluate ( file , {
49
58
...runtime ,
50
59
useDynamicImport : true ,
51
60
remarkPlugins,
52
- rehypePlugins : [ capture ( 'hast' ) ] ,
61
+ rehypePlugins,
53
62
recmaPlugins : [ capture ( 'esast' ) ]
54
63
} )
55
64
) . default
65
+
66
+ if ( ! config . position ) {
67
+ removePosition ( file . data . mdast , { force : true } )
68
+ removePosition ( file . data . hast , { force : true } )
69
+ removePositionEsast ( file . data . esast )
70
+ }
56
71
} catch ( error ) {
57
72
const message =
58
73
error instanceof VFileMessage ? error : new VFileMessage ( error )
@@ -107,9 +122,13 @@ export function Editor({children}) {
107
122
const defaultValue = children
108
123
const extensions = useMemo ( ( ) => [ basicSetup , oneDark , langMarkdown ( ) ] , [ ] )
109
124
const [ state , setConfig ] = useMdx ( {
125
+ formatMd : false ,
126
+ position : false ,
110
127
gfm : false ,
111
128
frontmatter : false ,
129
+ directive : false ,
112
130
math : false ,
131
+ rehypeRaw : false ,
113
132
value : defaultValue
114
133
} )
115
134
const onUpdate = useCallback (
@@ -132,7 +151,7 @@ export function Editor({children}) {
132
151
} , [ state ] )
133
152
134
153
return (
135
- < div >
154
+ < div className = "playground-editor" >
136
155
< Tabs className = "frame frame-resizeable" >
137
156
< TabList className = "frame-tab-bar frame-tab-bar-scroll" >
138
157
< Tab
@@ -166,6 +185,41 @@ export function Editor({children}) {
166
185
</ TabPanel >
167
186
< TabPanel className = "tab-panel-scrollable playground-editor-options-tab-panel" >
168
187
< form className = "frame-body frame-body-box" >
188
+ < fieldset >
189
+ < label >
190
+ < input
191
+ type = "radio"
192
+ name = "language"
193
+ checked = { ! state . formatMd }
194
+ onChange = { ( ) => {
195
+ setConfig ( { ...state , formatMd : false } )
196
+ } }
197
+ /> { ' ' }
198
+ Use < code > MDX</ code >
199
+ </ label >
200
+ < span style = { { margin : '1em' } } > </ span >
201
+ < label >
202
+ < input
203
+ type = "radio"
204
+ name = "language"
205
+ checked = { state . formatMd }
206
+ onChange = { ( ) => {
207
+ setConfig ( { ...state , formatMd : true } )
208
+ } }
209
+ /> { ' ' }
210
+ Use < code > CommonMark</ code >
211
+ </ label >
212
+ </ fieldset >
213
+ < label >
214
+ < input
215
+ checked = { state . position }
216
+ type = "checkbox"
217
+ onChange = { ( ) =>
218
+ setConfig ( { ...state , position : ! state . position } )
219
+ }
220
+ /> { ' ' }
221
+ Show positional info
222
+ </ label >
169
223
< label >
170
224
< input
171
225
checked = { state . gfm }
@@ -201,6 +255,32 @@ export function Editor({children}) {
201
255
< code > remark-math</ code >
202
256
</ a >
203
257
</ label >
258
+ < label >
259
+ < input
260
+ checked = { state . directive }
261
+ type = "checkbox"
262
+ onChange = { ( ) =>
263
+ setConfig ( { ...state , directive : ! state . directive } )
264
+ }
265
+ /> { ' ' }
266
+ Use{ ' ' }
267
+ < a href = "https://github.com/remarkjs/remark-directive" >
268
+ < code > remark-directive</ code >
269
+ </ a >
270
+ </ label >
271
+ < label >
272
+ < input
273
+ checked = { state . rehypeRaw }
274
+ type = "checkbox"
275
+ onChange = { ( ) =>
276
+ setConfig ( { ...state , rehypeRaw : ! state . rehypeRaw } )
277
+ }
278
+ /> { ' ' }
279
+ Use{ ' ' }
280
+ < a href = "https://github.com/rehypejs/rehype-raw" >
281
+ < code > rehype-raw</ code >
282
+ </ a >
283
+ </ label >
204
284
</ form >
205
285
</ TabPanel >
206
286
</ Tabs >
@@ -324,3 +404,15 @@ export function Editor({children}) {
324
404
</ div >
325
405
)
326
406
}
407
+
408
+ function removePositionEsast ( tree ) {
409
+ visitEstree ( tree , remove )
410
+ return tree
411
+
412
+ function remove ( node ) {
413
+ delete node . loc
414
+ delete node . start
415
+ delete node . end
416
+ delete node . range
417
+ }
418
+ }
1 commit comments
vercel[bot] commentedon Jun 10, 2023
Successfully deployed to the following URLs:
mdx – ./
mdx-git-main-mdx.vercel.app
mdxjs.com
v2.mdxjs.com
mdx-mdx.vercel.app