Skip to content

Commit

Permalink
Introduce Song#getChords() (#1435)
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnversluis authored Nov 12, 2024
1 parent 6f9515c commit 291ed74
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ the paragraph contents as one string where lines are separated by newlines.</p>
* [.useModifier(modifier)](#Song+useModifier)[<code>Song</code>](#Song)
* [.changeMetadata(name, value)](#Song+changeMetadata)
* [.mapItems(func)](#Song+mapItems)[<code>Song</code>](#Song)
* [.getChords()](#Song+getChords) ⇒ <code>Array.&lt;string&gt;</code>
* [.mapLines(func)](#Song+mapLines)[<code>Song</code>](#Song)

<a name="new_Song_new"></a>
Expand Down Expand Up @@ -1094,6 +1095,13 @@ song.mapItems((item) => {
return item;
});
```
<a name="Song+getChords"></a>

### song.getChords() ⇒ <code>Array.&lt;string&gt;</code>
<p>Returns all unique chords used in the song</p>

**Kind**: instance method of [<code>Song</code>](#Song)
**Returns**: <code>Array.&lt;string&gt;</code> - <p>the chords</p>
<a name="Song+mapLines"></a>

### song.mapLines(func) ⇒ [<code>Song</code>](#Song)
Expand Down
30 changes: 30 additions & 0 deletions src/chord_sheet/song.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import Tag, {
} from './tag';
import SongBuilder from '../song_builder';

type EachItemCallback = (_item: Item) => void;

type MapItemsCallback = (_item: Item) => Item | null;

type MapLinesCallback = (_line: Line) => Line | null;
Expand Down Expand Up @@ -411,6 +413,34 @@ Or set the song key before changing key:
return clonedSong;
}

foreachItem(func: EachItemCallback): void {
this.lines.forEach((line) => {
line.items.forEach(func);
});
}

/**
* Returns all unique chords used in the song
* @returns {string[]} the chords
*/
getChords(): string[] {
const chords = new Set<string>();

this.foreachItem((item: Item) => {
if (!(item instanceof ChordLyricsPair)) {
return;
}

const itemChords = (item as ChordLyricsPair).chords;

if (itemChords && itemChords.length > 0) {
chords.add(itemChords);
}
});

return Array.from(chords);
}

/**
* Change the song contents inline. Return a new {@link Line} to replace it. Return `null` to remove it.
* @example
Expand Down
38 changes: 37 additions & 1 deletion test/chord_sheet/song.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChordLyricsPair, ChordSheetSerializer, Tag } from '../../src';
import { createSong } from '../utilities';
import { createChordLyricsPair, createLine, createSong } from '../utilities';

import { exampleSongSolfege, exampleSongSymbol } from '../fixtures/song';
import { serializedSongSolfege, serializedSongSymbol } from '../fixtures/serialized_song';
Expand Down Expand Up @@ -282,4 +282,40 @@ describe('Song', () => {
it('solfege can be deserialized', () => {
expect(new ChordSheetSerializer().deserialize(serializedSongSolfege)).toEqual(exampleSongSolfege);
});

describe('#getChords', () => {
it('returns the unique chords in a song', () => {
const song = createSong([
createLine([
createChordLyricsPair('CM7', 'let'),
createChordLyricsPair('', 'it'),
createChordLyricsPair('Dm7', ''),
]),
createLine([]),
createLine([
createChordLyricsPair('F#', 'be'),
createChordLyricsPair('', 'changed'),
]),
]);

expect(song.getChords()).toEqual(['CM7', 'Dm7', 'F#']);
});

it('returns an empty array if there are no chords in the song', () => {
const song = createSong([
createLine([
createChordLyricsPair('', 'let'),
createChordLyricsPair('', 'it'),
createChordLyricsPair('', ''),
]),
createLine([]),
createLine([
createChordLyricsPair('', 'be'),
createChordLyricsPair('', 'changed'),
]),
]);

expect(song.getChords()).toEqual([]);
});
});
});

0 comments on commit 291ed74

Please sign in to comment.