@@ -3,6 +3,16 @@ import { Section } from "./Section";
33import { Line } from "./Line" ;
44import { chunk , flatten , trim } from "lodash" ;
55import { Part } from "./Part" ;
6+ import { Measure } from "./Measure" ;
7+
8+ const SECTION_REGEX = / # \s * ( [ ^ $ ] * ) / ;
9+ const ATTRIBUTE_REGEX = / @ ( \w * ) = ( [ ^ % ] * ) / ;
10+ const CUSTOM_ATTRIBUTE_REGEX = / ! ( \w * ) = ( [ ^ % ] * ) / ;
11+ const CHORDS_AND_LYRICS_REGEX = / ( \[ [ \w # b / ] + ] ) ? ( [ \w \s ' , . ! ( ) _ \- " ] * ) / gi;
12+
13+ const MEASURES_REGEX = / ( [ [ \w # b / \] + \] \s ] + ) [ | ] * / gi;
14+ const CHORDS_REGEX = / \[ ( [ \w # b + / ] + ) ] ? / gi;
15+ const COMMENT_REGEX = / > \s * ( [ ^ $ ] * ) / ;
616
717export class SongPro {
818 static parse ( text ) {
@@ -11,9 +21,7 @@ export class SongPro {
1121
1222 const lines = text . split ( "\n" ) ;
1323
14- for ( let i = 0 ; i < lines . length ; i ++ ) {
15- const text = lines [ i ] ;
16-
24+ for ( const text of lines ) {
1725 if ( text . startsWith ( "@" ) ) {
1826 this . processAttribute ( song , text ) ;
1927 } else if ( text . startsWith ( "!" ) ) {
@@ -29,7 +37,7 @@ export class SongPro {
2937 }
3038
3139 static processAttribute ( song , line ) {
32- const matches = / @ ( \w * ) = ( [ ^ % ] * ) / . exec ( line ) ;
40+ const matches = ATTRIBUTE_REGEX . exec ( line ) ;
3341
3442 if ( matches == null ) {
3543 return ;
@@ -39,7 +47,7 @@ export class SongPro {
3947 }
4048
4149 static processCustomAttribute ( song , line ) {
42- const matches = / ! ( \w * ) = ( [ ^ % ] * ) / . exec ( line ) ;
50+ const matches = CUSTOM_ATTRIBUTE_REGEX . exec ( line ) ;
4351
4452 if ( matches == null ) {
4553 return ;
@@ -49,7 +57,7 @@ export class SongPro {
4957 }
5058
5159 static processSection ( song , line ) {
52- const matches = / # \s * ( [ ^ $ ] * ) / . exec ( line ) ;
60+ const matches = SECTION_REGEX . exec ( line ) ;
5361
5462 if ( matches == null ) {
5563 return ;
@@ -74,33 +82,60 @@ export class SongPro {
7482
7583 const line = new Line ( ) ;
7684
77- let captures = this . scan ( text , / ( \[ [ \w # b / ] + ] ) ? ( [ \w \s ' , . ! ( ) _ \- " ] * ) / gi) ;
78- captures = flatten ( captures ) ;
79- const groups = chunk ( captures , 2 ) ;
85+ if ( text . startsWith ( "|-" ) ) {
86+ line . tablature = text ;
87+ } else if ( text . startsWith ( "| " ) ) {
88+ let captures = this . scan ( text , MEASURES_REGEX ) ;
89+ captures = flatten ( captures ) ;
8090
81- for ( let i = 0 ; i < groups . length ; i ++ ) {
82- const group = groups [ i ] ;
83- let chord = group [ 0 ] ;
84- let lyric = group [ 1 ] ;
91+ const measures = [ ] ;
8592
86- const part = new Part ( ) ;
93+ for ( const capture of captures ) {
94+ let chords = this . scan ( capture , CHORDS_REGEX ) ;
95+ chords = flatten ( chords ) ;
8796
88- if ( chord ) {
89- chord = chord . replace ( "[" , "" ) . replace ( "]" , "" ) ;
97+ const measure = new Measure ( ) ;
98+ measure . chords = chords ;
99+ measures . push ( measure ) ;
90100 }
91101
92- if ( chord === undefined ) {
93- chord = "" ;
94- }
95- if ( lyric === undefined ) {
96- lyric = "" ;
102+ line . measures = measures ;
103+ } else if ( text . startsWith ( ">" ) ) {
104+ const matches = COMMENT_REGEX . exec ( text ) ;
105+
106+ if ( matches == null ) {
107+ return ;
97108 }
98109
99- part . chord = trim ( chord ) ;
100- part . lyric = trim ( lyric ) ;
110+ line . comment = matches [ 1 ] . trim ( ) ;
111+ } else {
112+ let captures = this . scan ( text , CHORDS_AND_LYRICS_REGEX ) ;
113+ captures = flatten ( captures ) ;
114+ const groups = chunk ( captures , 2 ) ;
115+
116+ for ( const group of groups ) {
117+ let chord = group [ 0 ] ;
118+ let lyric = group [ 1 ] ;
119+
120+ const part = new Part ( ) ;
121+
122+ if ( chord ) {
123+ chord = chord . replace ( "[" , "" ) . replace ( "]" , "" ) ;
124+ }
125+
126+ if ( chord === undefined ) {
127+ chord = "" ;
128+ }
129+ if ( lyric === undefined ) {
130+ lyric = "" ;
131+ }
132+
133+ part . chord = trim ( chord ) ;
134+ part . lyric = trim ( lyric ) ;
101135
102- if ( ! ( part . chord === "" && part . lyric === "" ) ) {
103- line . parts . push ( part ) ;
136+ if ( ! ( part . chord === "" && part . lyric === "" ) ) {
137+ line . parts . push ( part ) ;
138+ }
104139 }
105140 }
106141
0 commit comments