@@ -7,6 +7,15 @@ type TutorialFrame = {
77 levels : T . Level [ ] ;
88} ;
99
10+ const R = {
11+ summary : / ^ # \s (?< tutorialTitle > .* ) [ \n \r ] + (?< tutorialDescription > [ ^ ] * ) / ,
12+ level : / ^ ( # { 2 } \s (?< levelId > L ? \d + \. ? ) \s (?< levelTitle > .* ) [ \n \r ] * ( > \s (?< levelSummary > .* ) ) ? [ \n \r ] + (?< levelContent > [ ^ ] * ) ) / ,
13+ step : / ^ ( # { 3 } \s (?< stepTitle > .* ) [ \n \r ] + (?< stepContent > [ ^ ] * ) ) / ,
14+ hints : / ^ ( # { 4 } \s H I N T S [ \n \r ] + ( [ \* | \- ] \s (?< hintContent > [ ^ ] * ) ) [ \n \r ] + ) + / ,
15+ subtasks : / ^ ( # { 4 } \s S U B T A S K S [ \n \r ] + ( [ \* | \- ] \s (?< subtaskContent > [ ^ ] * ) ) [ \n \r ] + ) + / ,
16+ listItem : / [ \n \r ] + [ \* | \- ] \s / ,
17+ } ;
18+
1019export function parseMdContent ( md : string ) : TutorialFrame | never {
1120 let start : number = - 1 ;
1221 const parts : any [ ] = [ ] ;
@@ -34,9 +43,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
3443 } ;
3544
3645 // Capture summary
37- const summaryMatch = parts
38- . shift ( )
39- . match ( / ^ # \s (?< tutorialTitle > .* ) [ \n \r ] + (?< tutorialDescription > [ ^ ] * ) / ) ;
46+ const summaryMatch = parts . shift ( ) . match ( R . summary ) ;
4047 if ( summaryMatch . groups . tutorialTitle ) {
4148 mdContent . summary . title = summaryMatch . groups . tutorialTitle . trim ( ) ;
4249 }
@@ -49,8 +56,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
4956 // Identify each part of the content
5057 parts . forEach ( ( section : string ) => {
5158 // match level
52- const levelRegex = / ^ ( # { 2 } \s (?< levelId > L ? \d + \. ? ) \s (?< levelTitle > .* ) [ \n \r ] * ( > \s (?< levelSummary > .* ) ) ? [ \n \r ] + (?< levelContent > [ ^ ] * ) ) / ;
53- const levelMatch : RegExpMatchArray | null = section . match ( levelRegex ) ;
59+ const levelMatch : RegExpMatchArray | null = section . match ( R . level ) ;
5460
5561 if ( levelMatch && levelMatch . groups ) {
5662 const levelId = levelMatch . groups . levelId . replace ( "." , "" ) ;
@@ -77,8 +83,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
7783 } ;
7884 } else {
7985 // match step
80- const stepRegex = / ^ ( # { 3 } \s (?< stepTitle > .* ) [ \n \r ] + (?< stepContent > [ ^ ] * ) ) / ;
81- const stepMatch : RegExpMatchArray | null = section . match ( stepRegex ) ;
86+ const stepMatch : RegExpMatchArray | null = section . match ( R . step ) ;
8287 if ( stepMatch && stepMatch . groups ) {
8388 current = {
8489 levelId : current . levelId ,
@@ -91,17 +96,14 @@ export function parseMdContent(md: string): TutorialFrame | never {
9196 content : stepContent . trim ( ) ,
9297 } ;
9398 } else {
94- const hintDetectRegex = / ^ ( # { 4 } \s H I N T S [ \n \r ] + ( [ \* | \- ] \s (?< hintContent > [ ^ ] * ) ) [ \n \r ] + ) + / ;
95- const hintMatch = section . match ( hintDetectRegex ) ;
96- const subtaskDetectRegex = / ^ ( # { 4 } \s S U B T A S K S [ \n \r ] + ( [ \* | \- ] \s (?< subtaskContent > [ ^ ] * ) ) [ \n \r ] + ) + / ;
97- const subtaskMatch = section . match ( subtaskDetectRegex ) ;
98- const listItemregex = / [ \n \r ] + [ \* | \- ] \s / ;
99+ const hintMatch = section . match ( R . hints ) ;
100+ const subtaskMatch = section . match ( R . subtasks ) ;
99101
100102 switch ( true ) {
101103 // parse hints from stepContent
102104 case ! ! hintMatch :
103105 const hints = section
104- . split ( listItemregex )
106+ . split ( R . listItem )
105107 . slice ( 1 ) // remove #### HINTS
106108 . map ( ( h ) => h . trim ( ) ) ;
107109 if ( hints . length ) {
@@ -113,7 +115,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
113115 // parse subtasks from stepContent
114116 case ! ! subtaskMatch :
115117 const subtasks = section
116- . split ( listItemregex )
118+ . split ( R . listItem )
117119 . slice ( 1 ) // remove #### SUBTASKS
118120 . map ( ( h ) => h . trim ( ) ) ;
119121 if ( subtasks . length ) {
0 commit comments