chordsheetjs v12.1.2
ChordSheetJS

A JavaScript library for parsing and formatting chord sheets
Contents
Installation
Package managers
ChordSheetJS
is on npm, to install run:
npm install chordsheetjs
Load with import
:
import ChordSheetJS from 'chordsheetjs';
or require()
:
var ChordSheetJS = require('chordsheetjs').default;
Standalone bundle file
If you're not using a build tool, you can download and use the bundle.js
from the
latest release:
<script src="bundle.js"></script>
<script>
// ChordSheetJS is available in global namespace now
const parser = new ChordSheetJS.ChordProParser();
</script>
How to ...?
Parse chord sheet
Regular chord sheets
const chordSheet = `
Am C/G F C
Let it be, let it be, let it be, let it be
C G F C/E Dm C
Whisper words of wisdom, let it be`.substring(1);
const parser = new ChordSheetJS.ChordsOverWordsParser();
const song = parser.parse(chordSheet);
Ultimate Guitar chord sheets
const chordSheet = `
[Chorus]
Am C/G F C
Let it be, let it be, let it be, let it be
C G F C/E Dm C
Whisper words of wisdom, let it be`.substring(1);
const parser = new ChordSheetJS.UltimateGuitarParser();
const song = parser.parse(chordSheet);
Chord pro format
const chordSheet = `
{title: Let it be}
{subtitle: ChordSheetJS example version}
{start_of_chorus: Chorus}
Let it [Am]be, let it [C/G]be, let it [F]be, let it [C]be
[C]Whisper words of [G]wisdom, let it [F]be [C/E] [Dm] [C]
{end_of_chorus}`.substring(1);
const parser = new ChordSheetJS.ChordProParser();
const song = parser.parse(chordSheet);
Display a parsed sheet
Plain text format
const formatter = new ChordSheetJS.TextFormatter();
const disp = formatter.format(song);
HTML format
Table-based layout
const formatter = new ChordSheetJS.HtmlTableFormatter();
const disp = formatter.format(song);
Div-based layout
const formatter = new ChordSheetJS.HtmlDivFormatter();
const disp = formatter.format(song);
Chord pro format
const formatter = new ChordSheetJS.ChordProFormatter();
const disp = formatter.format(song);
Serialize/deserialize
Chord sheets (Song
s) can be serialized to plain JavaScript objects, which can be converted to JSON, XML etc by
third-party libraries. The serialized object can also be deserialized back into a Song
.
const serializedSong = new ChordSheetSerializer().serialize(song);
const deserialized = new ChordSheetSerializer().deserialize(serializedSong);
Add styling
The HTML formatters (HtmlTableFormatter and HtmlDivFormatter) can provide basic CSS to help with styling the output:
HtmlTableFormatter.cssString();
// .paragraph {
// margin-bottom: 1em;
// }
HtmlTableFormatter.cssString('.chordSheetViewer');
// .chordSheetViewer .paragraph {
// margin-bottom: 1em;
// }
HtmlTableFormatter.cssObject();
// '.paragraph': {
// marginBottom: '1em'
// }
Parsing and modifying chords
import { Chord } from 'chordsheetjs';
Parse
const chord = Chord.parse('Ebsus4/Bb');
Parse numeric chords (Nashville system):
const chord = Chord.parse('b1sus4/#3');
Display with #toString
Use #toString() to convert the chord to a chord string (eg Dsus/F#)
const chord = Chord.parse('Ebsus4/Bb');
chord.toString(); // --> "Ebsus4/Bb"
Clone
var chord2 = chord.clone();
Normalize
Normalizes keys B#, E#, Cb and Fb to C, F, B and E
const chord = Chord.parse('E#/B#');
normalizedChord = chord.normalize();
normalizedChord.toString(); // --> "F/C"
Switch modifier
Deprecated
Convert # to b and vice versa
const chord = parseChord('Eb/Bb');
const chord2 = chord.switchModifier();
chord2.toString(); // --> "D#/A#"
Use specific modifier
Set the chord to a specific modifier (# or b)
const chord = Chord.parse('Eb/Bb');
const chord2 = chord.useModifier('#');
chord2.toString(); // --> "D#/A#"
const chord = Chord.parse('Eb/Bb');
const chord2 = chord.useModifier('b');
chord2.toString(); // --> "Eb/Bb"
Transpose up
const chord = Chord.parse('Eb/Bb');
const chord2 = chord.transposeUp();
chord2.toString(); // -> "E/B"
Transpose down
const chord = Chord.parse('Eb/Bb');
const chord2 = chord.transposeDown();
chord2.toString(); // -> "D/A"
Transpose
const chord = Chord.parse('C/E');
const chord2 = chord.transpose(4);
chord2.toString(); // -> "E/G#"
const chord = Chord.parse('C/E');
const chord2 = chord.transpose(-4);
chord2.toString(); // -> "Ab/C"
Convert numeric chord to chord symbol
const numericChord = Chord.parse('2/4');
const chordSymbol = numericChord.toChordSymbol('E');
chordSymbol.toString(); // -> "F#/A"
Supported ChordPro directives
All directives are parsed and are added to Song.metadata
. The list below indicates whether formatters actually
use those to change the generated output.
:heavy_check_mark: = supported
:clock2: = will be supported in a future version
:heavy_multiplication_x: = currently no plans to support it in the near future
Meta-data directives
Directive | Support |
---|---|
title (short: t) | :heavy_check_mark: |
subtitle | :heavy_check_mark: |
artist | :heavy_check_mark: |
composer | :heavy_check_mark: |
lyricist | :heavy_check_mark: |
copyright | :heavy_check_mark: |
album | :heavy_check_mark: |
year | :heavy_check_mark: |
key | :heavy_check_mark: |
time | :heavy_check_mark: |
tempo | :heavy_check_mark: |
duration | :heavy_check_mark: |
capo | :heavy_check_mark: |
meta | :heavy_check_mark: |
Formatting directives
Directive | Support |
---|---|
comment (short: c) | :heavy_check_mark: |
comment_italic (short: ci) | :heavy_multiplication_x: |
comment_box (short: cb) | :heavy_multiplication_x: |
chorus | :heavy_multiplication_x: |
image | :heavy_multiplication_x: |
Environment directives
Directive | Support |
---|---|
start_of_chorus (short: soc) | :heavy_check_mark: |
end_of_chorus (short: eoc) | :heavy_check_mark: |
start_of_verse | :heavy_check_mark: |
end_of_verse | :heavy_check_mark: |
start_of_tab (short: sot) | :heavy_check_mark: |
end_of_tab (short: eot) | :heavy_check_mark: |
start_of_grid | :heavy_multiplication_x: |
end_of_grid | :heavy_multiplication_x: |
Chord diagrams
Directive | Support |
---|---|
define | :heavy_multiplication_x: |
chord | :heavy_multiplication_x: |
Fonts, sizes and colours
Directive | Support |
---|---|
textfont | :heavy_check_mark: |
textsize | :heavy_check_mark: |
textcolour | :heavy_check_mark: |
chordfont | :heavy_check_mark: |
chordsize | :heavy_check_mark: |
chordcolour | :heavy_check_mark: |
tabfont | :heavy_multiplication_x: |
tabsize | :heavy_multiplication_x: |
tabcolour | :heavy_multiplication_x: |
Output related directives
Directive | Support |
---|---|
new_page (short: np) | :heavy_multiplication_x: |
new_physical_page (short: npp) | :heavy_multiplication_x: |
column_break (short: cb) | :heavy_multiplication_x: |
grid (short: g) | :heavy_multiplication_x: |
no_grid (short: ng) | :heavy_multiplication_x: |
titles | :heavy_multiplication_x: |
columns (short: col) | :heavy_multiplication_x: |
Custom extensions
Directive | Support |
---|---|
x_ | :heavy_check_mark: |
API docs
Note: all classes, methods and constants that are documented here can be considered public API and will only be subject to breaking changes between major versions.
Classes
Constants
Functions
ChordLyricsPair
Kind: global class
- ChordLyricsPair
- new ChordLyricsPair(chords, lyrics, annotation)
- .chords : string
- .lyrics : string
- .annotation : string
- .isRenderable() ⇒ boolean
- .clone() ⇒ ChordLyricsPair
new ChordLyricsPair(chords, lyrics, annotation)
Param | Type | Default | Description |
---|---|---|---|
chords | string | The chords | |
lyrics | string | null | null | The lyrics |
annotation | string | null | null | The annotation |
chordLyricsPair.chords : string
Kind: instance property of ChordLyricsPair
chordLyricsPair.lyrics : string
Kind: instance property of ChordLyricsPair
chordLyricsPair.annotation : string
Kind: instance property of ChordLyricsPair
chordLyricsPair.isRenderable() ⇒ boolean
Kind: instance method of ChordLyricsPair
chordLyricsPair.clone() ⇒ ChordLyricsPair
Kind: instance method of ChordLyricsPair
Comment
Kind: global class
- Comment
- .isRenderable() ⇒ boolean
- .clone() ⇒ Comment
comment.isRenderable() ⇒ boolean
Kind: instance method of Comment
comment.clone() ⇒ Comment
Kind: instance method of Comment
Line
Kind: global class
- Line
- .isEmpty() ⇒ boolean
- .addItem(item)
- .hasRenderableItems() ⇒ boolean
- .clone() ⇒ Line
- .isBridge() ⇒ boolean
- .isChorus() ⇒ boolean
- .isGrid() ⇒ boolean
- .isTab() ⇒ boolean
- .isVerse() ⇒ boolean
.hasContent() ⇒ boolean
line.isEmpty() ⇒ boolean
Kind: instance method of Line
line.addItem(item)
Kind: instance method of Line
Param | Type | Description |
---|---|---|
item | ChordLyricsPair | Tag | The item to be added |
line.hasRenderableItems() ⇒ boolean
Kind: instance method of Line
line.clone() ⇒ Line
Kind: instance method of Line
line.isBridge() ⇒ boolean
Kind: instance method of Line
line.isChorus() ⇒ boolean
Kind: instance method of Line
line.isGrid() ⇒ boolean
Kind: instance method of Line
line.isTab() ⇒ boolean
Kind: instance method of Line
line.isVerse() ⇒ boolean
Kind: instance method of Line
line.hasContent() ⇒ boolean
Deprecated
Kind: instance method of Line
Metadata
Kind: global class
- Metadata
- .get(prop) ⇒ Array.<String> | String
- .clone() ⇒ Metadata
metadata.get(prop) ⇒ Array.<String> | String
Kind: instance method of Metadata
Returns: Array.<String> | String - the metadata value(s). If there is only one value, it will return a String,
else it returns an array of strings.
Param | Description |
---|---|
prop | the property name |
metadata.clone() ⇒ Metadata
Kind: instance method of Metadata
Returns: Metadata - the cloned Metadata object
Paragraph
Kind: global class
- Paragraph
- .contents ⇒ string
- .label ⇒ string | null
- .type ⇒ string
- .isLiteral() ⇒ boolean
- .hasRenderableItems() ⇒ boolean
paragraph.contents ⇒ string
Kind: instance property of Paragraph
paragraph.label ⇒ string | null
Kind: instance property of Paragraph
paragraph.type ⇒ string
Kind: instance property of Paragraph
paragraph.isLiteral() ⇒ boolean
Kind: instance method of Paragraph
See: contents
paragraph.hasRenderableItems() ⇒ boolean
Kind: instance method of Paragraph
See: Line.hasRenderableItems
Song
Kind: global class
- Song
- new Song(metadata)
- .bodyLines ⇒ Array.<Line>
- .bodyParagraphs ⇒ Array.<Paragraph>
- .paragraphs : Array.<Paragraph>
- .expandedBodyParagraphs : Array.<Paragraph>
- .clone() ⇒ Song
- .setKey(key) ⇒ Song
- .setCapo(capo) ⇒ Song
- .transpose(delta, [options]) ⇒ Song
- .transposeUp([options]) ⇒ Song
- .transposeDown([options]) ⇒ Song
- .changeKey(newKey) ⇒ Song
- .changeMetadata(name, value)
- .mapItems(func) ⇒ Song
- .mapLines(func) ⇒ Song
new Song(metadata)
Param | Type | Description |
---|---|---|
metadata | Object | Metadata | predefined metadata |
song.bodyLines ⇒ Array.<Line>
Kind: instance property of Song
Returns: Array.<Line> - The song body lines
song.bodyParagraphs ⇒ Array.<Paragraph>
Kind: instance property of Song
See: bodyLines
song.paragraphs : Array.<Paragraph>
Kind: instance property of Song
song.expandedBodyParagraphs : Array.<Paragraph>
Kind: instance property of Song
song.clone() ⇒ Song
Kind: instance method of Song
Returns: Song - The cloned song
song.setKey(key) ⇒ Song
Kind: instance method of Song
Returns: Song - The changed song
Param | Type | Description |
---|---|---|
key | number | null | the key. Passing null will: remove the current key from metadata remove any key directive |
song.setCapo(capo) ⇒ Song
Kind: instance method of Song
Returns: Song - The changed song
Param | Type | Description |
---|---|---|
capo | number | null | the capo. Passing null will: remove the current key from metadata remove any capo directive |
song.transpose(delta, options) ⇒ Song
Kind: instance method of Song
Returns: Song - The transposed song
Param | Type | Default | Description |
---|---|---|---|
delta | number | The number of semitones (positive or negative) to transpose with | |
options | Object | {} | options |
options.normalizeChordSuffix | boolean | false | whether to normalize the chord suffixes after transposing |
song.transposeUp(options) ⇒ Song
Kind: instance method of Song
Returns: Song - The transposed song
Param | Type | Default | Description |
---|---|---|---|
options | Object | {} | options |
options.normalizeChordSuffix | boolean | false | whether to normalize the chord suffixes after transposing |
song.transposeDown(options) ⇒ Song
Kind: instance method of Song
Returns: Song - The transposed song
Param | Type | Default | Description |
---|---|---|---|
options | Object | {} | options |
options.normalizeChordSuffix | boolean | false | whether to normalize the chord suffixes after transposing |
song.changeKey(newKey) ⇒ Song
Kind: instance method of Song
Returns: Song - The changed song
Param | Type | Description |
---|---|---|
newKey | string | The new key. |
song.changeMetadata(name, value)
Kind: instance method of Song
Param | Type | Description |
---|---|---|
name | string | The directive name |
value | string | null | The value to set, or null to remove the directive |
song.mapItems(func) ⇒ Song
Kind: instance method of Song
Returns: Song - the changed song
Param | Type | Description |
---|---|---|
func | MapItemsCallback | the callback function |
Example
// transpose all chords:
song.mapItems((item) => {
if (item instanceof ChordLyricsPair) {
return item.transpose(2, 'D');
}
return item;
});
song.mapLines(func) ⇒ Song
Kind: instance method of Song
Returns: Song - the changed song
Param | Type | Description |
---|---|---|
func | MapLinesCallback | the callback function |
Example
// remove lines with only Tags:
song.mapLines((line) => {
if (line.items.every(item => item instanceof Tag)) {
return null;
}
return line;
});
Tag
Kind: global class
- Tag
- .name : string
- .originalName : string
- .value : string
- .hasValue() ⇒ boolean
- .isRenderable() ⇒ boolean
- .hasRenderableLabel()
- .isMetaTag() ⇒ boolean
- .clone() ⇒ Tag
tag.name : string
Kind: instance property of Tag
tag.originalName : string
Kind: instance property of Tag
tag.value : string
Kind: instance property of Tag
tag.hasValue() ⇒ boolean
Kind: instance method of Tag
tag.isRenderable() ⇒ boolean
Kind: instance method of Tag
tag.hasRenderableLabel()
Kind: instance method of Tag
tag.isMetaTag() ⇒ boolean
Kind: instance method of Tag
tag.clone() ⇒ Tag
Kind: instance method of Tag
Returns: Tag - The cloned tag
ChordProFormatter
Kind: global class
chordProFormatter.format(song) ⇒ string
Kind: instance method of ChordProFormatter
Returns: string - The ChordPro string
Param | Type | Description |
---|---|---|
song | Song | The song to be formatted |
ChordsOverWordsFormatter
Kind: global class
chordsOverWordsFormatter.format(song) ⇒ string
Kind: instance method of ChordsOverWordsFormatter
Returns: string - the chord sheet
Param | Type | Description |
---|---|---|
song | Song | The song to be formatted |
Formatter
Kind: global class
new Formatter(configuration)
Param | Type | Default | Description |
---|---|---|---|
configuration | Object | {} | options |
configuration.evaluate | boolean | false | Whether or not to evaluate meta expressions. For more info about meta expressions, see: https://bit.ly/2SC9c2u |
configuration.metadata | object | {} | |
configuration.metadata.separator | string | "\", \"" | The separator to be used when rendering a metadata value that has multiple values. See: https://bit.ly/2SC9c2u |
configuration.key | Key | string | The key to use for rendering. The chord sheet will be transposed from the song's original key (as indicated by the {key} directive) to the specified key. Note that transposing will only work if the original song key is set. | |
configuration.expandChorusDirective | boolean | false | Whether or not to expand {chorus} directives by rendering the last defined chorus inline after the directive. |
configuration.useUnicodeModifiers | boolean | false | Whether or not to use unicode flat and sharp symbols. |
configuration.normalizeChords | boolean | true | Whether or not to automatically normalize chords |
HtmlDivFormatter
Kind: global class
HtmlFormatter
Kind: global class
- HtmlFormatter
- .cssObject ⇒ Object.<string, Object.<string, string>>
- .format(song) ⇒ string
- .cssString(scope) ⇒ string
htmlFormatter.cssObject ⇒ Object.<string, Object.<string, string>>
Kind: instance property of HtmlFormatter
Returns: Object.<string, Object.<string, string>> - the CSS object
htmlFormatter.format(song) ⇒ string
Kind: instance method of HtmlFormatter
Returns: string - The HTML string
Param | Type | Description |
---|---|---|
song | Song | The song to be formatted |
htmlFormatter.cssString(scope) ⇒ string
Kind: instance method of HtmlFormatter
Returns: string - the CSS string
Param | Description |
---|---|
scope | the CSS scope to use, for example .chordSheetViewer |
HtmlTableFormatter
Kind: global class
TextFormatter
Kind: global class
textFormatter.format(song) ⇒ string
Kind: instance method of TextFormatter
Returns: string - the chord sheet
Param | Type | Description |
---|---|---|
song | Song | The song to be formatted |
ChordProParser
Kind: global class
chordProParser.warnings : Array.<ParserWarning>
Kind: instance property of ChordProParser
chordProParser.parse(chordSheet) ⇒ Song
Kind: instance method of ChordProParser
Returns: Song - The parsed song
Param | Type | Description |
---|---|---|
chordSheet | string | the ChordPro chord sheet |
ChordSheetParser
Deprecated
Kind: global class
new ChordSheetParser(options)
Param | Type | Default | Description |
---|---|---|---|
options | Object | {} | options |
options.preserveWhitespace | boolean | true | whether to preserve trailing whitespace for chords |
chordSheetParser.parse(chordSheet, options) ⇒ Song
Kind: instance method of ChordSheetParser
Returns: Song - The parsed song
Param | Type | Default | Description |
---|---|---|---|
chordSheet | string | The ChordPro chord sheet | |
options | Object | {} | Optional parser options |
options.song | Song | The Song to store the song data in |
ChordsOverWordsParser
Kind: global class
chordsOverWordsParser.warnings : Array.<ParserWarning>
Kind: instance property of ChordsOverWordsParser
chordsOverWordsParser.parse(chordSheet, options) ⇒ Song
Kind: instance method of ChordsOverWordsParser
Returns: Song - The parsed song
See: https://peggyjs.org/documentation.html#using-the-parser
Param | Type | Description |
---|---|---|
chordSheet | string | the chords over words sheet |
options | ParseOptions | Parser options. |
ParserWarning
Kind: global class
parserWarning.toString() ⇒ string
Kind: instance method of ParserWarning
Returns: string - The string warning
UltimateGuitarParser
Kind: global class
new UltimateGuitarParser(options)
Param | Type | Default | Description |
---|---|---|---|
options | Object | {} | options |
options.preserveWhitespace | boolean | true | whether to preserve trailing whitespace for chords |
Chord
Kind: global class
- Chord
- instance
- .clone() ⇒ Chord
- .toChordSymbol([referenceKey]) ⇒ Chord
- .toChordSymbolString([referenceKey]) ⇒ string
- .isChordSymbol() ⇒ boolean
- .toChordSolfege([referenceKey]) ⇒ Chord
- .toChordSolfegeString([referenceKey]) ⇒ string
- .isChordSolfege() ⇒ boolean
- .toNumeric([referenceKey]) ⇒ Chord
- .toNumeral([referenceKey]) ⇒ Chord
- .toNumeralString([referenceKey]) ⇒ string
- .isNumeric() ⇒ boolean
- .toNumericString([referenceKey]) ⇒ string
- .isNumeral() ⇒ boolean
- .toString([configuration]) ⇒ string
- .normalize([key], [options]) ⇒ Chord
- .useModifier(newModifier) ⇒ Chord
- .transposeUp() ⇒ Chord
- .transposeDown() ⇒ Chord
- .transpose(delta) ⇒ Chord
- static
- .parse(chordString) ⇒ Chord | null
- instance
chord.clone() ⇒ Chord
Kind: instance method of Chord
chord.toChordSymbol(referenceKey) ⇒ Chord
Kind: instance method of Chord
Returns: Chord - the chord symbol
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a numeric or numeral. |
chord.toChordSymbolString(referenceKey) ⇒ string
Kind: instance method of Chord
Returns: string - the chord symbol string
See: {toChordSymbol}
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a numeric or numeral. |
chord.isChordSymbol() ⇒ boolean
Kind: instance method of Chord
chord.toChordSolfege(referenceKey) ⇒ Chord
Kind: instance method of Chord
Returns: Chord - the chord solfege
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a numeric or numeral. |
chord.toChordSolfegeString(referenceKey) ⇒ string
Kind: instance method of Chord
Returns: string - the chord solfege string
See: {toChordSolfege}
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a numeric or numeral. |
chord.isChordSolfege() ⇒ boolean
Kind: instance method of Chord
chord.toNumeric(referenceKey) ⇒ Chord
Kind: instance method of Chord
Returns: Chord - the numeric chord
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a chord symbol |
chord.toNumeral(referenceKey) ⇒ Chord
Kind: instance method of Chord
Returns: Chord - the numeral chord
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a chord symbol |
chord.toNumeralString(referenceKey) ⇒ string
Kind: instance method of Chord
Returns: string - the numeral chord string
See: {toNumeral}
Param | Type | Default | Description |
---|---|---|---|
referenceKey | Key | string | null | the reference key. The key is required when converting a chord symbol |
chord.isNumeric() ⇒ boolean
7 months ago
7 months ago
7 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
10 years ago
10 years ago