@@ -17,6 +17,12 @@ type Code = WithAttr & {
17
17
text : string ;
18
18
} ;
19
19
20
+ type Link = WithAttr & {
21
+ type : "Link" ;
22
+ content : Inline [ ] ;
23
+ target : string ;
24
+ } ;
25
+
20
26
type Emph = {
21
27
type : "Emph" ;
22
28
content : Inline [ ] ;
@@ -36,14 +42,15 @@ type Span = WithAttr & {
36
42
content : Inline [ ] ;
37
43
} ;
38
44
39
- type Inline = Code | Emph | Str | Space | Span | Shortcode ;
45
+ type Inline = Code | Emph | Str | Space | Span | Shortcode | Link ;
40
46
const isCode = ( inline : Inline ) : inline is Code => inline . type === "Code" ;
41
47
const isEmph = ( inline : Inline ) : inline is Emph => inline . type === "Emph" ;
42
48
const isStr = ( inline : Inline ) : inline is Str => inline . type === "Str" ;
43
49
const isSpace = ( inline : Inline ) : inline is Space => inline . type === "Space" ;
44
50
const isSpan = ( inline : Inline ) : inline is Span => inline . type === "Span" ;
45
51
const isShortcode = ( inline : Inline ) : inline is Shortcode =>
46
52
inline . type === "Shortcode" ;
53
+ const isLink = ( inline : Inline ) : inline is Link => inline . type === "Link" ;
47
54
48
55
type Para = {
49
56
type : "Para" ;
@@ -69,6 +76,16 @@ class RenderContext {
69
76
indent : number ;
70
77
content : string [ ] ;
71
78
79
+ renderLink ( link : Link ) {
80
+ this . content . push ( "[" ) ;
81
+ for ( const inline of link . content ) {
82
+ this . renderInline ( inline ) ;
83
+ }
84
+ this . content . push ( "]" ) ;
85
+ this . content . push ( "(" + link . target + ")" ) ;
86
+ this . renderAttr ( link . attr ) ;
87
+ }
88
+
72
89
renderAttr ( attr ?: Attr ) {
73
90
if ( attr === undefined ) {
74
91
return ;
@@ -131,6 +148,9 @@ class RenderContext {
131
148
if ( isShortcode ( inline ) ) {
132
149
this . renderShortcode ( inline ) ;
133
150
}
151
+ if ( isLink ( inline ) ) {
152
+ this . renderLink ( inline ) ;
153
+ }
134
154
}
135
155
136
156
renderPara ( para : Para ) {
@@ -180,7 +200,9 @@ class GeneratorContext {
180
200
emph : number ;
181
201
code : number ;
182
202
span : number ;
203
+ link : number ;
183
204
shortcode : number ;
205
+ targetShortcode : number ;
184
206
} ;
185
207
186
208
sizes : {
@@ -228,6 +250,11 @@ class GeneratorContext {
228
250
return newContext ;
229
251
}
230
252
253
+ generatePunctuation ( ) {
254
+ const punctuations = [ "." , "!" , "?" , "," , ";" , ":" ] ;
255
+ return punctuations [ ~ ~ ( Math . random ( ) * punctuations . length ) ] ;
256
+ }
257
+
231
258
////////////////////////////////////////////////////////////////////////////////
232
259
// Attr-related functions
233
260
@@ -298,6 +325,9 @@ class GeneratorContext {
298
325
if ( Math . random ( ) < this . probabilities . emph ) {
299
326
return "Emph" ;
300
327
}
328
+ if ( Math . random ( ) < this . probabilities . link ) {
329
+ return "Link" ;
330
+ }
301
331
if ( Math . random ( ) < this . probabilities . shortcode ) {
302
332
return "InlineShortcode" ;
303
333
}
@@ -367,12 +397,42 @@ class GeneratorContext {
367
397
} ;
368
398
}
369
399
400
+ generateTarget ( ) : string {
401
+ let target = this . freshId ( ) ;
402
+ if ( Math . random ( ) < this . probabilities . targetShortcode ) {
403
+ const shortcode = this . generateInlineShortcode ( ) ;
404
+ target = `${ target } -{{< ${ shortcode . content } >}}` ;
405
+ }
406
+ return target ;
407
+ }
408
+
409
+ generateLink ( ) : Link {
410
+ const small = this . smaller ( ) ;
411
+ const contentSize = ~ ~ ( Math . random ( ) * small . sizes . inline ) + 1 ;
412
+ const content : Inline [ ] = [ ] ;
413
+
414
+ for ( let i = 0 ; i < contentSize ; i ++ ) {
415
+ const inline = small . generateInline ( ) ;
416
+ if ( inline ) {
417
+ content . push ( inline ) ;
418
+ }
419
+ }
420
+
421
+ return {
422
+ attr : this . randomAttr ( ) ,
423
+ type : "Link" ,
424
+ content,
425
+ target : this . generateTarget ( ) ,
426
+ } ;
427
+ }
428
+
370
429
generateInline ( ) {
371
430
const dispatch = {
372
431
Str : ( ) => this . generateStr ( ) ,
373
432
Code : ( ) => this . generateCode ( ) ,
374
433
Emph : ( ) => this . generateEmph ( ) ,
375
434
Span : ( ) => this . generateSpan ( ) ,
435
+ Link : ( ) => this . generateLink ( ) ,
376
436
InlineShortcode : ( ) => this . generateInlineShortcode ( ) ,
377
437
Null : ( ) => { } ,
378
438
} ;
@@ -401,16 +461,14 @@ class GeneratorContext {
401
461
} else {
402
462
content . push ( {
403
463
type : "Str" ,
404
- text : "." ,
464
+ text : small . generatePunctuation ( ) ,
405
465
} ) ;
406
466
}
407
467
} else {
408
- if ( i === sentenceSize - 1 ) {
409
- content . push ( {
410
- type : "Str" ,
411
- text : "." ,
412
- } ) ;
413
- }
468
+ content . push ( {
469
+ type : "Str" ,
470
+ text : small . generatePunctuation ( ) ,
471
+ } ) ;
414
472
}
415
473
}
416
474
} ;
@@ -467,7 +525,9 @@ class GeneratorContext {
467
525
code : 0.5 ,
468
526
span : 0.5 ,
469
527
emph : 0.5 ,
528
+ link : 0.5 ,
470
529
shortcode : 0.5 ,
530
+ targetShortcode : 0.25 ,
471
531
} ;
472
532
this . sizes = {
473
533
inline : 10 ,
0 commit comments