1
1
import * as marked from 'marked' ;
2
-
3
2
import slugify from 'slugify' ;
4
- import { MDComponent } from '../components/Markdown/Markdown' ;
3
+
5
4
import { highlight , html2Str } from '../utils' ;
5
+ import { AppStore } from './AppStore' ;
6
6
import { SECTION_ATTR } from './MenuStore' ;
7
7
8
8
const renderer = new marked . Renderer ( ) ;
@@ -14,9 +14,14 @@ marked.setOptions({
14
14
} ,
15
15
} ) ;
16
16
17
- export const COMPONENT_REGEXP = '^\\s*<!-- ReDoc-Inject:\\s+?{component}\\s+?-->\\s*$' ;
18
- export function buildComponentComment ( name : string ) {
19
- return `<!-- ReDoc-Inject: <${ name } > -->` ;
17
+ export const LEGACY_REGEXP = '^\\s*<!-- ReDoc-Inject:\\s+?{component}\\s+?-->\\s*$' ;
18
+ export const MDX_COMPONENT_REGEXP = '^\\s*<{component}\\s*?/>\\s*$' ;
19
+ export const COMPONENT_REGEXP = '(?:' + LEGACY_REGEXP + '|' + MDX_COMPONENT_REGEXP + ')' ;
20
+
21
+ export interface MDXComponentMeta {
22
+ component : React . ComponentType ;
23
+ propsSelector : ( store ?: AppStore ) => any ;
24
+ attrs ?: object ;
20
25
}
21
26
22
27
export interface MarkdownHeading {
@@ -26,6 +31,10 @@ export interface MarkdownHeading {
26
31
description ?: string ;
27
32
}
28
33
34
+ export function buildComponentComment ( name : string ) {
35
+ return `<!-- ReDoc-Inject: <${ name } > -->` ;
36
+ }
37
+
29
38
export class MarkdownRenderer {
30
39
headings : MarkdownHeading [ ] = [ ] ;
31
40
currentTopHeading : MarkdownHeading ;
@@ -130,20 +139,30 @@ export class MarkdownRenderer {
130
139
return res ;
131
140
}
132
141
142
+ // TODO: rewrite this completelly! Regexp-based 👎
143
+ // Use marked ecosystem
133
144
renderMdWithComponents (
134
145
rawText : string ,
135
- components : Dict < MDComponent > ,
146
+ components : Dict < MDXComponentMeta > ,
136
147
raw : boolean = true ,
137
- ) : Array < string | MDComponent > {
148
+ ) : Array < string | MDXComponentMeta > {
138
149
const componentDefs : string [ ] = [ ] ;
139
- const anyCompRegexp = new RegExp ( COMPONENT_REGEXP . replace ( '{component}' , '(.*?)' ) , 'gmi' ) ;
150
+ const names = '(?:' + Object . keys ( components ) . join ( '|' ) + ')' ;
151
+
152
+ const anyCompRegexp = new RegExp (
153
+ COMPONENT_REGEXP . replace ( / { c o m p o n e n t } / g, '(<?' + names + '.*?)' ) ,
154
+ 'gmi' ,
155
+ ) ;
140
156
let match = anyCompRegexp . exec ( rawText ) ;
141
157
while ( match ) {
142
- componentDefs . push ( match [ 1 ] ) ;
158
+ componentDefs . push ( match [ 1 ] || match [ 2 ] ) ;
143
159
match = anyCompRegexp . exec ( rawText ) ;
144
160
}
145
161
146
- const splitCompRegexp = new RegExp ( COMPONENT_REGEXP . replace ( '{component}' , '.*?' ) , 'mi' ) ;
162
+ const splitCompRegexp = new RegExp (
163
+ COMPONENT_REGEXP . replace ( / { c o m p o n e n t } / g, names + '.*?' ) ,
164
+ 'mi' ,
165
+ ) ;
147
166
const htmlParts = rawText . split ( splitCompRegexp ) ;
148
167
const res : any [ ] = [ ] ;
149
168
for ( let i = 0 ; i < htmlParts . length ; i ++ ) {
@@ -171,6 +190,40 @@ function parseComponent(
171
190
) : {
172
191
componentName ?: string ;
173
192
attrs : any ;
193
+ } {
194
+ if ( htmlTag . startsWith ( '<' ) ) {
195
+ return legacyParse ( htmlTag ) ;
196
+ }
197
+
198
+ const match = / ( [ \w _ - ] + ) ( \s + [ \w _ - ] + \s * = { [ ^ } ] * ?} ) * / . exec ( htmlTag ) ;
199
+ if ( match === null || match . length <= 1 ) {
200
+ return { componentName : undefined , attrs : { } } ;
201
+ }
202
+ const componentName = match [ 1 ] ;
203
+ const attrs = { } ;
204
+ for ( let i = 2 ; i < match . length ; i ++ ) {
205
+ if ( ! match [ i ] ) {
206
+ continue ;
207
+ }
208
+ const [ name , value ] = match [ i ]
209
+ . trim ( )
210
+ . split ( '=' )
211
+ . map ( p => p . trim ( ) ) ;
212
+
213
+ // tslint:disable-next-line
214
+ attrs [ name ] = value . startsWith ( '{' ) ? eval ( value . substr ( 1 , value . length - 2 ) ) : eval ( value ) ;
215
+ }
216
+ return {
217
+ componentName,
218
+ attrs,
219
+ } ;
220
+ }
221
+
222
+ function legacyParse (
223
+ htmlTag : string ,
224
+ ) : {
225
+ componentName ?: string ;
226
+ attrs : any ;
174
227
} {
175
228
const match = / < ( [ \w _ - ] + ) .* ?> / . exec ( htmlTag ) ;
176
229
if ( match === null || match . length <= 1 ) {
0 commit comments