1
1
/*
2
+ * @flow strict-local
2
3
* Copyright (C) 2005 Stefan Kestenholz (keschte)
3
4
* Copyright (C) 2015 MetaBrainz Foundation
4
5
*
@@ -12,6 +13,7 @@ import * as ReactDOMServer from 'react-dom/server';
12
13
import getBooleanCookie from '../common/utility/getBooleanCookie' ;
13
14
import { capitalize } from '../common/utility/strings' ;
14
15
16
+ import type { GuessCaseModeT } from './types' ;
15
17
import {
16
18
isPrepBracketWord ,
17
19
isPrepBracketSingleWord ,
@@ -95,7 +97,12 @@ const POSTPROCESS_FIXLIST = [
95
97
] ;
96
98
/* eslint-enable no-multi-spaces */
97
99
98
- function replaceMatch ( matches , inputString , regex , replacement ) {
100
+ function replaceMatch (
101
+ matches : RegExp$matchResult ,
102
+ inputString : string ,
103
+ regex : RegExp ,
104
+ replacement : string ,
105
+ ) : string {
99
106
// get reference to first set of parentheses
100
107
const a = matches [ 1 ] || '' ;
101
108
@@ -112,29 +119,36 @@ function replaceMatch(matches, inputString, regex, replacement) {
112
119
* @param is the input string
113
120
* @param fixes the list of fix objects to apply
114
121
*/
115
- function runFixes ( inputString , fixes ) {
122
+ function runFixes (
123
+ inputString : string ,
124
+ fixes : $ReadOnlyArray < [ RegExp , string ] > ,
125
+ ) : string {
126
+ let output = inputString ;
116
127
fixes . forEach ( function ( fix ) {
117
128
const [ regex , replacement ] = fix ;
118
129
let matches ;
119
130
120
131
if ( regex . global ) {
121
- let oldInputString ;
122
- while ( ( matches = regex . exec ( inputString ) ) ) {
123
- oldInputString = inputString ;
124
- inputString = replaceMatch ( matches , inputString , regex , replacement ) ;
125
- if ( oldInputString === inputString ) {
132
+ let previousOutput ;
133
+ while ( ( matches = regex . exec ( output ) ) ) {
134
+ previousOutput = output ;
135
+ output = replaceMatch ( matches , output , regex , replacement ) ;
136
+ if ( previousOutput === output ) {
126
137
break ;
127
138
}
128
139
}
129
- } else if ( ( matches = inputString . match ( regex ) ) !== null ) {
130
- inputString = replaceMatch ( matches , inputString , regex , replacement ) ;
140
+ } else {
141
+ const matches = output . match ( regex ) ;
142
+ if ( matches !== null ) {
143
+ output = replaceMatch ( matches , output , regex , replacement ) ;
144
+ }
131
145
}
132
146
} ) ;
133
147
134
- return inputString ;
148
+ return output ;
135
149
}
136
150
137
- const DefaultMode = {
151
+ const DefaultMode : GuessCaseModeT = {
138
152
description : '' ,
139
153
140
154
/*
@@ -187,21 +201,24 @@ const DefaultMode = {
187
201
* My Track 12" remix => My Track (12" remix)
188
202
*/
189
203
prepExtraTitleInfo ( words ) {
190
- const lastWord = words . length - 1 ;
204
+ let outputWords = words ;
205
+ const lastWord = outputWords . length - 1 ;
191
206
let wordIndex = lastWord ;
192
207
let handlePreProcess = false ;
193
208
194
209
while ( wordIndex >= 0 && (
195
210
// skip whitespace
196
- ( words [ wordIndex ] === ' ' ) ||
211
+ ( outputWords [ wordIndex ] === ' ' ) ||
197
212
198
213
// vinyl (7" or 12")
199
- ( words [ wordIndex ] === '"' &&
200
- ( words [ wordIndex - 1 ] === '7' || words [ wordIndex - 1 ] === '12' ) ) ||
201
- ( ( words [ wordIndex + 1 ] || '' ) === '"' &&
202
- ( words [ wordIndex ] === '7' || words [ wordIndex ] === '12' ) ) ||
203
-
204
- isPrepBracketWord ( words [ wordIndex ] )
214
+ ( outputWords [ wordIndex ] === '"' &&
215
+ ( outputWords [ wordIndex - 1 ] === '7' ||
216
+ outputWords [ wordIndex - 1 ] === '12' ) ) ||
217
+ ( ( outputWords [ wordIndex + 1 ] || '' ) === '"' &&
218
+ ( outputWords [ wordIndex ] === '7' ||
219
+ outputWords [ wordIndex ] === '12' ) ) ||
220
+
221
+ isPrepBracketWord ( outputWords [ wordIndex ] )
205
222
) ) {
206
223
handlePreProcess = true ;
207
224
wordIndex -- ;
@@ -221,21 +238,21 @@ const DefaultMode = {
221
238
if ( wordIndex < lastWord ) {
222
239
// the word at wi broke out of the loop above, is not extra title info
223
240
wordIndex ++ ;
224
- while ( words [ wordIndex ] === ' ' && wordIndex < lastWord ) {
241
+ while ( outputWords [ wordIndex ] === ' ' && wordIndex < lastWord ) {
225
242
wordIndex ++ ; // skip whitespace
226
243
}
227
244
228
245
/*
229
246
* If we have a single word that needs to be put in parentheses, consult
230
247
* the list of words were we don't do that, otherwise continue.
231
248
*/
232
- const probe = words [ lastWord ] ;
249
+ const probe = outputWords [ lastWord ] ;
233
250
if ( wordIndex === lastWord && isPrepBracketSingleWord ( probe ) ) {
234
251
handlePreProcess = false ;
235
252
}
236
253
237
254
if ( handlePreProcess && wordIndex > 0 && wordIndex <= lastWord ) {
238
- let newWords = words . slice ( 0 , wordIndex ) ;
255
+ let newWords = outputWords . slice ( 0 , wordIndex ) ;
239
256
240
257
if ( newWords [ wordIndex - 1 ] === '(' ) {
241
258
newWords . pop ( ) ;
@@ -246,13 +263,15 @@ const DefaultMode = {
246
263
}
247
264
248
265
newWords . push ( '(' ) ;
249
- newWords = newWords . concat ( words . slice ( wordIndex , words . length ) ) ;
266
+ newWords = newWords . concat (
267
+ outputWords . slice ( wordIndex , outputWords . length ) ,
268
+ ) ;
250
269
newWords . push ( ')' ) ;
251
- words = newWords ;
270
+ outputWords = newWords ;
252
271
}
253
272
}
254
273
255
- return words ;
274
+ return outputWords ;
256
275
} ,
257
276
258
277
/*
@@ -284,7 +303,7 @@ const DefaultMode = {
284
303
} ,
285
304
} ;
286
305
287
- export const English = {
306
+ export const English : GuessCaseModeT = {
288
307
...DefaultMode ,
289
308
description : ReactDOMServer . renderToStaticMarkup ( exp . l (
290
309
`This mode capitalises almost all words, with some words (mainly articles
@@ -303,25 +322,25 @@ export const English = {
303
322
name : 'English' ,
304
323
305
324
runPostProcess ( inputString ) {
306
- inputString = DefaultMode . runPostProcess ( inputString ) ;
325
+ let output = DefaultMode . runPostProcess ( inputString ) ;
307
326
/*
308
327
* This changes key names in titles to follow
309
328
* the English classical music guidelines.
310
329
* See https://musicbrainz.org/doc/Style/Classical/Language/English#Keys
311
330
*/
312
- inputString = inputString . replace (
331
+ output = output . replace (
313
332
/ \b i n ( [ a - g ] ) (?: [ \s - ] ( [ F f ] l a t | [ S s ] h a r p ) ) ? \s ( d o r i a n | l y d i a n | m a j o r | m i n o r | m i x o l y d i a n ) (?: \b | $ ) / ig,
314
333
function ( match , p1 , p2 , p3 ) {
315
334
return 'in ' + p1 . toUpperCase ( ) +
316
335
( p2 ? '-' + p2 . toLowerCase ( ) : '' ) +
317
336
' ' + p3 . toLowerCase ( ) ;
318
337
} ,
319
338
) ;
320
- return inputString ;
339
+ return output ;
321
340
} ,
322
341
} ;
323
342
324
- export const French = {
343
+ export const French : GuessCaseModeT = {
325
344
...DefaultMode ,
326
345
description : ReactDOMServer . renderToStaticMarkup ( exp . l (
327
346
`This mode capitalises titles as sentence mode, but also inserts spaces
@@ -345,7 +364,7 @@ export const French = {
345
364
} ,
346
365
} ;
347
366
348
- export const Sentence = {
367
+ export const Sentence : GuessCaseModeT = {
349
368
...DefaultMode ,
350
369
description : ReactDOMServer . renderToStaticMarkup ( exp . l (
351
370
`This mode capitalises the first word of a sentence, most other words
@@ -360,7 +379,7 @@ export const Sentence = {
360
379
name : 'Sentence' ,
361
380
} ;
362
381
363
- export const Turkish = {
382
+ export const Turkish : GuessCaseModeT = {
364
383
...DefaultMode ,
365
384
description : ReactDOMServer . renderToStaticMarkup ( exp . l (
366
385
`This mode handles the Turkish capitalisation of 'i' ('İ') and 'ı' ('I').
0 commit comments