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 chordsheetjsLoad 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 (Songs) 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
9 months ago
9 months ago
9 months ago
11 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 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
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
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
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
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 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
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago