Skip to content

Commit 3230713

Browse files
Implement the european notation (#1067)
* Implement the european notation Resolves #401 Actually in the code the european notation is referred as "solfege" and it's treated like other ChordType notations, like "symbol" and "numeric" * Fix eslint issues * Add ChordsOverWordsFormatter test Also little refactor and fixed a "Am" to "Lam" in key_config.ts * eslint: fix errors * fix whitespaces * Revert packages updates --------- Co-authored-by: Martijn Versluis <[email protected]>
1 parent b8903f1 commit 3230713

File tree

73 files changed

+3557
-153
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3557
-153
lines changed

README.md

+44-2
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ See https://www.chordpro.org/chordpro/directives-key/</p></dd>
533533
See https://www.chordpro.org/chordpro/directives-env_chorus/</p></dd>
534534
<dt><a href="#CHORD_STYLE">CHORD_STYLE</a> : <code>string</code></dt>
535535
<dd><p>Chord type directive. Determines the type of chords used in the rendered chord sheet.
536-
Possible values are 'symbol', 'numeral' and 'number'</p></dd>
536+
Possible values are 'solfege', 'symbol', 'numeral' and 'number'</p></dd>
537537
<dt><a href="#BRIDGE">BRIDGE</a> : <code>string</code></dt>
538538
<dd><p>Used to mark a paragraph as bridge</p></dd>
539539
<dt><a href="#CHORUS">CHORUS</a> : <code>string</code></dt>
@@ -1405,6 +1405,9 @@ Inherits from [ChordSheetParser](#ChordSheetParser)</p>
14051405
* [.toChordSymbol([referenceKey])](#Chord+toChordSymbol)[<code>Chord</code>](#Chord)
14061406
* [.toChordSymbolString([referenceKey])](#Chord+toChordSymbolString) ⇒ <code>string</code>
14071407
* [.isChordSymbol()](#Chord+isChordSymbol) ⇒ <code>boolean</code>
1408+
* [.toChordSolfege([referenceKey])](#Chord+toChordSolfege)[<code>Chord</code>](#Chord)
1409+
* [.toChordSolfegeString([referenceKey])](#Chord+toChordSolfegeString) ⇒ <code>string</code>
1410+
* [.isChordSolfege()](#Chord+isChordSolfege) ⇒ <code>boolean</code>
14081411
* [.toNumeric([referenceKey])](#Chord+toNumeric)[<code>Chord</code>](#Chord)
14091412
* [.toNumeral([referenceKey])](#Chord+toNumeral)[<code>Chord</code>](#Chord)
14101413
* [.toNumeralString([referenceKey])](#Chord+toNumeralString) ⇒ <code>string</code>
@@ -1460,6 +1463,41 @@ When the chord is already a chord symbol, it will return a string version of the
14601463
### chord.isChordSymbol() ⇒ <code>boolean</code>
14611464
<p>Determines whether the chord is a chord symbol</p>
14621465

1466+
**Kind**: instance method of [<code>Chord</code>](#Chord)
1467+
<a name="Chord+toChordSolfege"></a>
1468+
1469+
### chord.toChordSolfege([referenceKey]) ⇒ [<code>Chord</code>](#Chord)
1470+
<p>Converts the chord to a chord solfege, using the supplied key as a reference.
1471+
For example, a numeric chord <code>#4</code> with reference key <code>Mi</code> will return the chord symbol <code>La#</code>.
1472+
When the chord is already a chord solfege, it will return a clone of the object.</p>
1473+
1474+
**Kind**: instance method of [<code>Chord</code>](#Chord)
1475+
**Returns**: [<code>Chord</code>](#Chord) - <p>the chord solfege</p>
1476+
1477+
| Param | Type | Default | Description |
1478+
| --- | --- | --- | --- |
1479+
| [referenceKey] | [<code>Key</code>](#Key) \| <code>string</code> \| <code>null</code> | <code></code> | <p>the reference key. The key is required when converting a numeric or numeral.</p> |
1480+
1481+
<a name="Chord+toChordSolfegeString"></a>
1482+
1483+
### chord.toChordSolfegeString([referenceKey]) ⇒ <code>string</code>
1484+
<p>Converts the chord to a chord solfege string, using the supplied key as a reference.
1485+
For example, a numeric chord <code>#4</code> with reference key <code>E</code> will return the chord solfege <code>A#</code>.
1486+
When the chord is already a chord solfege, it will return a string version of the chord.</p>
1487+
1488+
**Kind**: instance method of [<code>Chord</code>](#Chord)
1489+
**Returns**: <code>string</code> - <p>the chord solfege string</p>
1490+
**See**: {toChordSolfege}
1491+
1492+
| Param | Type | Default | Description |
1493+
| --- | --- | --- | --- |
1494+
| [referenceKey] | [<code>Key</code>](#Key) \| <code>string</code> \| <code>null</code> | <code></code> | <p>the reference key. The key is required when converting a numeric or numeral.</p> |
1495+
1496+
<a name="Chord+isChordSolfege"></a>
1497+
1498+
### chord.isChordSolfege() ⇒ <code>boolean</code>
1499+
<p>Determines whether the chord is a chord solfege</p>
1500+
14631501
**Kind**: instance method of [<code>Chord</code>](#Chord)
14641502
<a name="Chord+toNumeric"></a>
14651503

@@ -1545,6 +1583,10 @@ For example, a chord symbol A# with reference key E will return the numeric chor
15451583
### chord.normalize([key], [options]) ⇒ [<code>Chord</code>](#Chord)
15461584
<p>Normalizes the chord root and bass notes:</p>
15471585
<ul>
1586+
<li>Fab becomes Mi</li>
1587+
<li>Dob becomes Si</li>
1588+
<li>Si# becomes Do</li>
1589+
<li>Mi# becomes Fa</li>
15481590
<li>Fb becomes E</li>
15491591
<li>Cb becomes B</li>
15501592
<li>B# becomes C</li>
@@ -1898,7 +1940,7 @@ See https://www.chordpro.org/chordpro/directives-env_chorus/</p>
18981940

18991941
## CHORD\_STYLE : <code>string</code>
19001942
<p>Chord type directive. Determines the type of chords used in the rendered chord sheet.
1901-
Possible values are 'symbol', 'numeral' and 'number'</p>
1943+
Possible values are 'solfege', 'symbol', 'numeral' and 'number'</p>
19021944

19031945
**Kind**: global constant
19041946
**See**: https://github.com/bettermusic/ChordSheetJS/issues/352

bin/generate_scales

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
const fs = require('fs');
44

5-
const { FLAT, MAJOR, MINOR, NO_MODIFIER, NUMERAL, NUMERIC, SHARP, SYMBOL } = require('../src/constants');
5+
const { FLAT, MAJOR, MINOR, NO_MODIFIER, NUMERAL, NUMERIC, SHARP, SYMBOL, SOLFEGE } = require('../src/constants');
66
const { default: SCALES } = require('../data/scales');
77

88
const MODIFIERS = { 'NO_MODIFIER': NO_MODIFIER, 'SHARP': SHARP, 'FLAT': FLAT };
9-
const KEY_TYPES = { 'SYMBOL': SYMBOL, 'NUMERIC': NUMERIC, 'NUMERAL': NUMERAL };
9+
const KEY_TYPES = { 'SYMBOL': SYMBOL, 'SOLFEGE': SOLFEGE, 'NUMERIC': NUMERIC, 'NUMERAL': NUMERAL };
1010
const MODES = { 'MAJOR': MAJOR, 'MINOR': MINOR };
1111

1212
const keyToGradeMapping = `
@@ -29,6 +29,7 @@ const keyToGradeMapping = `
2929
NUMERIC,
3030
SHARP,
3131
SYMBOL,
32+
SOLFEGE
3233
} from './constants';
3334
3435
export const KEY_TO_GRADE: Record<ChordType, Record<Mode, Record<ModifierMaybe, Record<string, number>>>> = {

data/scales.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,30 @@ import {
88
NUMERAL,
99
NUMERIC,
1010
SHARP,
11+
SOLFEGE,
1112
SYMBOL,
1213
} from '../src/constants';
1314

15+
const AmericanScale = {
16+
[NO_MODIFIER]: ['C', null, 'D', null, 'E', 'F', null, 'G', null, 'A', null, 'B' ],
17+
[SHARP]: ['B#', 'C#', null, 'D#', null, 'E#', 'F#', null, 'G#', null, 'A#', null],
18+
[FLAT]: [null, 'Db', null, 'Eb', 'Fb', null, 'Gb', null, 'Ab', null, 'Bb', 'Cb'],
19+
};
20+
21+
const SolfegeScale = {
22+
[NO_MODIFIER]: ['Do', null, 'Re', null, 'Mi', 'Fa', null, 'Sol', null, 'La', null, 'Si' ],
23+
[SHARP]: ['Si#', 'Do#', null, 'Re#', null, 'Mi#', 'Fa#', null, 'Sol#', null, 'La#', null],
24+
[FLAT]: [null, 'Reb', null, 'Mib', 'Fab', null, 'Solb', null, 'Lab', null, 'Sib', 'Dob'],
25+
};
26+
1427
const SCALES = {
1528
[SYMBOL]: {
16-
[NO_MODIFIER]: ['C', null, 'D', null, 'E', 'F', null, 'G', null, 'A', null, 'B' ],
17-
[SHARP]: ['B#', 'C#', null, 'D#', null, 'E#', 'F#', null, 'G#', null, 'A#', null],
18-
[FLAT]: [null, 'Db', null, 'Eb', 'Fb', null, 'Gb', null, 'Ab', null, 'Bb', 'Cb'],
29+
[MINOR]: AmericanScale,
30+
[MAJOR]: AmericanScale,
31+
},
32+
[SOLFEGE]: {
33+
[MINOR]: SolfegeScale,
34+
[MAJOR]: SolfegeScale,
1935
},
2036
[NUMERIC]: {
2137
[MINOR]: {
@@ -43,8 +59,4 @@ const SCALES = {
4359
},
4460
};
4561

46-
const symbolScales = SCALES[SYMBOL];
47-
SCALES[SYMBOL][MAJOR] = symbolScales;
48-
SCALES[SYMBOL][MINOR] = symbolScales;
49-
5062
export default SCALES;

src/chord.ts

+55
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
NUMERAL,
99
NUMERIC,
1010
SYMBOL,
11+
SOLFEGE,
1112
} from './constants';
1213

1314
interface ChordProperties {
@@ -110,6 +111,56 @@ class Chord implements ChordProperties {
110111
return this.is(SYMBOL);
111112
}
112113

114+
/**
115+
* Converts the chord to a chord solfege, using the supplied key as a reference.
116+
* For example, a numeric chord `#4` with reference key `Mi` will return the chord symbol `La#`.
117+
* When the chord is already a chord solfege, it will return a clone of the object.
118+
* @param {Key|string|null} [referenceKey=null] the reference key. The key is required when converting a
119+
* numeric or numeral.
120+
* @returns {Chord} the chord solfege
121+
*/
122+
toChordSolfege(referenceKey: Key | string | null = null): Chord {
123+
if (this.isChordSolfege()) {
124+
return this.clone();
125+
}
126+
127+
const keyObj = Key.wrapOrFail(referenceKey);
128+
129+
let chordSolfegeChord = new Chord({
130+
suffix: this.suffix ? normalizeChordSuffix(this.suffix) : null,
131+
root: this.root?.toChordSolfege(keyObj) || null,
132+
bass: this.bass?.toChordSolfege(keyObj) || null,
133+
});
134+
135+
if (this.root?.isMinor()) {
136+
chordSolfegeChord = chordSolfegeChord.makeMinor();
137+
}
138+
139+
chordSolfegeChord = chordSolfegeChord.normalize(referenceKey);
140+
return chordSolfegeChord;
141+
}
142+
143+
/**
144+
* Converts the chord to a chord solfege string, using the supplied key as a reference.
145+
* For example, a numeric chord `#4` with reference key `E` will return the chord solfege `A#`.
146+
* When the chord is already a chord solfege, it will return a string version of the chord.
147+
* @param {Key|string|null} [referenceKey=null] the reference key. The key is required when converting a
148+
* numeric or numeral.
149+
* @returns {string} the chord solfege string
150+
* @see {toChordSolfege}
151+
*/
152+
toChordSolfegeString(referenceKey: Key | string | null = null): string {
153+
return this.toChordSolfege(referenceKey).toString();
154+
}
155+
156+
/**
157+
* Determines whether the chord is a chord solfege
158+
* @returns {boolean}
159+
*/
160+
isChordSolfege(): boolean {
161+
return this.is(SOLFEGE);
162+
}
163+
113164
/**
114165
* Converts the chord to a numeric chord, using the supplied key as a reference.
115166
* For example, a chord symbol A# with reference key E will return the numeric chord #4.
@@ -216,6 +267,10 @@ class Chord implements ChordProperties {
216267

217268
/**
218269
* Normalizes the chord root and bass notes:
270+
* - Fab becomes Mi
271+
* - Dob becomes Si
272+
* - Si# becomes Do
273+
* - Mi# becomes Fa
219274
* - Fb becomes E
220275
* - Cb becomes B
221276
* - B# becomes C

src/chord_sheet/tag.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,13 @@ export const CHORUS = 'chorus';
226226

227227
/**
228228
* Chord type directive. Determines the type of chords used in the rendered chord sheet.
229-
* Possible values are 'symbol', 'numeral' and 'number'
229+
* Possible values are 'solfege', 'symbol', 'numeral' and 'number'
230230
* @see https://github.com/bettermusic/ChordSheetJS/issues/352
231231
* @type {string}
232232
*/
233233
export const CHORD_STYLE = 'chord_style';
234234

235-
export type ChordType = 'symbol' | 'numeral' | 'number' | null;
235+
export type ChordType = 'symbol' | 'numeral' | 'number' | 'solfege' | null;
236236

237237
const CHORDFONT_SHORT = 'cf';
238238
const CHORDSIZE_SHORT = 'cs';

src/constants.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export type ParagraphType = 'bridge' | 'chorus' | 'grid' | 'indeterminate' | 'no
5252
export const SYMBOL = 'symbol';
5353
export const NUMERIC = 'numeric';
5454
export const NUMERAL = 'numeral';
55+
export const SOLFEGE = 'solfege';
5556

5657
export const ROMAN_NUMERALS = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII'];
5758

@@ -62,7 +63,7 @@ export const NO_MODIFIER = 'NM';
6263
export type NoModifier = 'NM';
6364
export type ModifierMaybe = Modifier | NoModifier;
6465

65-
export type ChordType = 'symbol' | 'numeric' | 'numeral';
66+
export type ChordType = 'symbol' | 'solfege' | 'numeric' | 'numeral';
6667

6768
export const MINOR = 'm';
6869
export const MAJOR = 'M';

src/helpers.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ function changeChordType(
4242
switch (type) {
4343
case 'symbol':
4444
return chord.toChordSymbol(referenceKey);
45+
case 'solfege':
46+
return chord.toChordSolfege(referenceKey);
4547
case 'numeral':
4648
return chord.toNumeral(referenceKey);
4749
case 'number':
@@ -91,7 +93,9 @@ export function renderChord(
9193
* values are the effective key for that capo.
9294
*/
9395
export function getCapos(key: Key | string): Record<string, string> {
94-
return capos[Key.toString(key)];
96+
const keyObj = Key.wrapOrFail(key);
97+
const chordType = keyObj.type === 'solfege' ? 'solfege' : 'symbol';
98+
return capos[chordType][Key.toString(key)];
9599
}
96100

97101
/**
@@ -101,5 +105,6 @@ export function getCapos(key: Key | string): Record<string, string> {
101105
*/
102106
export function getKeys(key: Key | string): string[] {
103107
const keyObj = Key.wrapOrFail(key);
104-
return keyObj.isMinor() ? minorKeys : majorKeys;
108+
const chordType = keyObj.type === 'solfege' ? 'solfege' : 'symbol';
109+
return keyObj.isMinor() ? minorKeys[chordType] : majorKeys[chordType];
105110
}

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export {
5858
INDETERMINATE,
5959
NONE,
6060
NUMERIC,
61+
SOLFEGE,
6162
SYMBOL,
6263
TAB,
6364
VERSE,

0 commit comments

Comments
 (0)