chordsheetjs 5.3.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +5 -0
- package/README.md +90 -4
- package/lib/chord.js +42 -35
- package/lib/chord_sheet/chord_lyrics_pair.js +5 -0
- package/lib/chord_sheet/line.js +23 -1
- package/lib/chord_sheet/metadata.js +14 -0
- package/lib/chord_sheet/song.js +189 -11
- package/lib/chord_sheet/tag.js +19 -5
- package/lib/formatter/templates/html_div_formatter.js +4 -4
- package/lib/formatter/templates/html_table_formatter.js +2 -2
- package/lib/formatter/text_formatter.js +2 -2
- package/lib/helpers.js +33 -9
- package/lib/key.js +48 -25
- package/lib/normalize_mappings/enharmonic-normalize.js +124 -0
- package/lib/normalize_mappings/generate-suffix-normalize-mapping.js +36 -0
- package/lib/normalize_mappings/suffix-normalize-mapping.js +914 -0
- package/lib/note.js +8 -3
- package/package.json +17 -9
- package/d7b54993c4ea66c07a35bd36690482ab620f836e.patch +0 -105
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ChordChartJS [](https://codeclimate.com/github/PraiseCharts/ChordChartJS)
|
|
2
2
|
|
|
3
3
|
A JavaScript library for parsing and formatting chord sheets
|
|
4
4
|
|
|
@@ -466,6 +466,12 @@ Inherits from <a href="#ChordSheetParser">ChordSheetParser</a></p>
|
|
|
466
466
|
<dt><a href="#TITLE">TITLE</a> : <code>string</code></dt>
|
|
467
467
|
<dd><p>Title meta directive. See <a href="https://www.chordpro.org/chordpro/directives-title/">https://www.chordpro.org/chordpro/directives-title/</a></p>
|
|
468
468
|
</dd>
|
|
469
|
+
<dt><a href="#TRANSPOSE">TRANSPOSE</a> : <code>string</code></dt>
|
|
470
|
+
<dd><p>Transpose meta directive. See: <a href="https://www.chordpro.org/chordpro/directives-transpose/">https://www.chordpro.org/chordpro/directives-transpose/</a></p>
|
|
471
|
+
</dd>
|
|
472
|
+
<dt><a href="#NEW_KEY">NEW_KEY</a> : <code>string</code></dt>
|
|
473
|
+
<dd><p>New Key meta directive. See: <a href="https://github.com/PraiseCharts/ChordChartJS/issues/53">https://github.com/PraiseCharts/ChordChartJS/issues/53</a></p>
|
|
474
|
+
</dd>
|
|
469
475
|
<dt><a href="#YEAR">YEAR</a> : <code>string</code></dt>
|
|
470
476
|
<dd><p>Year meta directive. See <a href="https://www.chordpro.org/chordpro/directives-year/">https://www.chordpro.org/chordpro/directives-year/</a></p>
|
|
471
477
|
</dd>
|
|
@@ -753,6 +759,8 @@ Represents a song in a chord sheet. Currently a chord sheet can only have one so
|
|
|
753
759
|
* [.bodyParagraphs](#Song+bodyParagraphs) ⇒ [<code>Array.<Paragraph></code>](#Paragraph)
|
|
754
760
|
* ~~[.metaData](#Song+metaData) ⇒~~
|
|
755
761
|
* [.clone()](#Song+clone) ⇒ [<code>Song</code>](#Song)
|
|
762
|
+
* [.setCapo(capo)](#Song+setCapo) ⇒ [<code>Song</code>](#Song)
|
|
763
|
+
* [.setKey(key)](#Song+setKey) ⇒ [<code>Song</code>](#Song)
|
|
756
764
|
|
|
757
765
|
<a name="new_Song_new"></a>
|
|
758
766
|
|
|
@@ -815,6 +823,35 @@ Returns a deep clone of the song
|
|
|
815
823
|
|
|
816
824
|
**Kind**: instance method of [<code>Song</code>](#Song)
|
|
817
825
|
**Returns**: [<code>Song</code>](#Song) - The cloned song
|
|
826
|
+
<a name="Song+setCapo"></a>
|
|
827
|
+
|
|
828
|
+
### song.setCapo(capo) ⇒ [<code>Song</code>](#Song)
|
|
829
|
+
Returns a copy of the song with the capo value set to the specified capo. It changes:
|
|
830
|
+
- the value for `capo` in the `metadata` set
|
|
831
|
+
- any existing `capo` directive)
|
|
832
|
+
|
|
833
|
+
**Kind**: instance method of [<code>Song</code>](#Song)
|
|
834
|
+
**Returns**: [<code>Song</code>](#Song) - The changed song
|
|
835
|
+
|
|
836
|
+
| Param | Type | Description |
|
|
837
|
+
| --- | --- | --- |
|
|
838
|
+
| capo | <code>number</code> \| <code>null</code> | the capo. Passing `null` will: - remove the current key from `metadata` - remove any `capo` directive |
|
|
839
|
+
|
|
840
|
+
<a name="Song+setKey"></a>
|
|
841
|
+
|
|
842
|
+
### song.setKey(key) ⇒ [<code>Song</code>](#Song)
|
|
843
|
+
Returns a copy of the song with the key set to the specified key. It changes:
|
|
844
|
+
- the value for `key` in the `metadata` set
|
|
845
|
+
- any existing `key` directive
|
|
846
|
+
- all chords, those are transposed according to the distance between the current and the new key
|
|
847
|
+
|
|
848
|
+
**Kind**: instance method of [<code>Song</code>](#Song)
|
|
849
|
+
**Returns**: [<code>Song</code>](#Song) - The changed song
|
|
850
|
+
|
|
851
|
+
| Param | Type | Description |
|
|
852
|
+
| --- | --- | --- |
|
|
853
|
+
| key | <code>string</code> | The new key. |
|
|
854
|
+
|
|
818
855
|
<a name="Tag"></a>
|
|
819
856
|
|
|
820
857
|
## Tag
|
|
@@ -1176,8 +1213,11 @@ Represents a Chord, consisting of a root, suffix (quality) and bass
|
|
|
1176
1213
|
* [.toChordSymbolString(key)](#Chord+toChordSymbolString) ⇒ <code>string</code>
|
|
1177
1214
|
* [.isChordSymbol()](#Chord+isChordSymbol) ⇒ <code>boolean</code>
|
|
1178
1215
|
* [.toNumeric(key)](#Chord+toNumeric) ⇒ [<code>Chord</code>](#Chord)
|
|
1216
|
+
* [.toNumeral(key)](#Chord+toNumeral) ⇒ [<code>Chord</code>](#Chord)
|
|
1217
|
+
* [.toNumeralString(key)](#Chord+toNumeralString) ⇒ <code>string</code>
|
|
1179
1218
|
* [.isNumeric()](#Chord+isNumeric) ⇒ <code>boolean</code>
|
|
1180
1219
|
* [.toNumericString(key)](#Chord+toNumericString) ⇒ <code>string</code>
|
|
1220
|
+
* [.isNumeral()](#Chord+isNumeral) ⇒ <code>boolean</code>
|
|
1181
1221
|
* [.toString()](#Chord+toString) ⇒ <code>string</code>
|
|
1182
1222
|
* [.normalize()](#Chord+normalize) ⇒ [<code>Chord</code>](#Chord)
|
|
1183
1223
|
* [.useModifier(newModifier)](#Chord+useModifier) ⇒ [<code>Chord</code>](#Chord)
|
|
@@ -1231,7 +1271,7 @@ Determines whether the chord is a chord symbol
|
|
|
1231
1271
|
<a name="Chord+toNumeric"></a>
|
|
1232
1272
|
|
|
1233
1273
|
### chord.toNumeric(key) ⇒ [<code>Chord</code>](#Chord)
|
|
1234
|
-
Converts the chord to a numeric chord, using the supplied
|
|
1274
|
+
Converts the chord to a numeric chord, using the supplied key as a reference.
|
|
1235
1275
|
For example, a chord symbol A# with reference key E will return the numeric chord #4.
|
|
1236
1276
|
|
|
1237
1277
|
**Kind**: instance method of [<code>Chord</code>](#Chord)
|
|
@@ -1241,6 +1281,33 @@ For example, a chord symbol A# with reference key E will return the numeric chor
|
|
|
1241
1281
|
| --- | --- | --- |
|
|
1242
1282
|
| key | <code>Key</code> \| <code>string</code> | the reference key |
|
|
1243
1283
|
|
|
1284
|
+
<a name="Chord+toNumeral"></a>
|
|
1285
|
+
|
|
1286
|
+
### chord.toNumeral(key) ⇒ [<code>Chord</code>](#Chord)
|
|
1287
|
+
Converts the chord to a numeral chord, using the supplied key as a reference.
|
|
1288
|
+
For example, a chord symbol A# with reference key E will return the numeral chord #IV.
|
|
1289
|
+
|
|
1290
|
+
**Kind**: instance method of [<code>Chord</code>](#Chord)
|
|
1291
|
+
**Returns**: [<code>Chord</code>](#Chord) - the numeral chord
|
|
1292
|
+
|
|
1293
|
+
| Param | Type | Default | Description |
|
|
1294
|
+
| --- | --- | --- | --- |
|
|
1295
|
+
| key | <code>Key</code> \| <code>string</code> \| <code>null</code> | <code></code> | the reference key. The key is required when converting a chord symbol |
|
|
1296
|
+
|
|
1297
|
+
<a name="Chord+toNumeralString"></a>
|
|
1298
|
+
|
|
1299
|
+
### chord.toNumeralString(key) ⇒ <code>string</code>
|
|
1300
|
+
Converts the chord to a numeral chord string, using the supplied kye as a reference.
|
|
1301
|
+
For example, a chord symbol A# with reference key E will return the numeral chord #4.
|
|
1302
|
+
|
|
1303
|
+
**Kind**: instance method of [<code>Chord</code>](#Chord)
|
|
1304
|
+
**Returns**: <code>string</code> - the numeral chord string
|
|
1305
|
+
**See**: {toNumeral}
|
|
1306
|
+
|
|
1307
|
+
| Param | Type | Description |
|
|
1308
|
+
| --- | --- | --- |
|
|
1309
|
+
| key | <code>Key</code> \| <code>string</code> | the reference key |
|
|
1310
|
+
|
|
1244
1311
|
<a name="Chord+isNumeric"></a>
|
|
1245
1312
|
|
|
1246
1313
|
### chord.isNumeric() ⇒ <code>boolean</code>
|
|
@@ -1261,6 +1328,12 @@ For example, a chord symbol A# with reference key E will return the numeric chor
|
|
|
1261
1328
|
| --- | --- | --- |
|
|
1262
1329
|
| key | <code>Key</code> \| <code>string</code> | the reference key |
|
|
1263
1330
|
|
|
1331
|
+
<a name="Chord+isNumeral"></a>
|
|
1332
|
+
|
|
1333
|
+
### chord.isNumeral() ⇒ <code>boolean</code>
|
|
1334
|
+
Determines whether the chord is a numeral
|
|
1335
|
+
|
|
1336
|
+
**Kind**: instance method of [<code>Chord</code>](#Chord)
|
|
1264
1337
|
<a name="Chord+toString"></a>
|
|
1265
1338
|
|
|
1266
1339
|
### chord.toString() ⇒ <code>string</code>
|
|
@@ -1271,7 +1344,7 @@ Converts the chord to a string, eg `Esus4/G#` or `1sus4/#3`
|
|
|
1271
1344
|
<a name="Chord+normalize"></a>
|
|
1272
1345
|
|
|
1273
1346
|
### chord.normalize() ⇒ [<code>Chord</code>](#Chord)
|
|
1274
|
-
Normalizes the chord:
|
|
1347
|
+
Normalizes the chord root and bass notes:
|
|
1275
1348
|
- Fb becomes E
|
|
1276
1349
|
- Cb becomes B
|
|
1277
1350
|
- B# becomes C
|
|
@@ -1281,7 +1354,8 @@ Normalizes the chord:
|
|
|
1281
1354
|
- 7# becomes 1
|
|
1282
1355
|
- 3# becomes 4
|
|
1283
1356
|
|
|
1284
|
-
|
|
1357
|
+
Besides that it normalizes the suffix. For example, `sus2` becomes `2`, `sus4` becomes `sus`.
|
|
1358
|
+
All suffix normalizations can be found in `src/normalize_mappings/suffix-mapping.txt`.
|
|
1285
1359
|
|
|
1286
1360
|
**Kind**: instance method of [<code>Chord</code>](#Chord)
|
|
1287
1361
|
**Returns**: [<code>Chord</code>](#Chord) - the normalized chord
|
|
@@ -1484,6 +1558,18 @@ Time meta directive. See https://www.chordpro.org/chordpro/directives-time/
|
|
|
1484
1558
|
## TITLE : <code>string</code>
|
|
1485
1559
|
Title meta directive. See https://www.chordpro.org/chordpro/directives-title/
|
|
1486
1560
|
|
|
1561
|
+
**Kind**: global constant
|
|
1562
|
+
<a name="TRANSPOSE"></a>
|
|
1563
|
+
|
|
1564
|
+
## TRANSPOSE : <code>string</code>
|
|
1565
|
+
Transpose meta directive. See: https://www.chordpro.org/chordpro/directives-transpose/
|
|
1566
|
+
|
|
1567
|
+
**Kind**: global constant
|
|
1568
|
+
<a name="NEW_KEY"></a>
|
|
1569
|
+
|
|
1570
|
+
## NEW\_KEY : <code>string</code>
|
|
1571
|
+
New Key meta directive. See: https://github.com/PraiseCharts/ChordChartJS/issues/53
|
|
1572
|
+
|
|
1487
1573
|
**Kind**: global constant
|
|
1488
1574
|
<a name="YEAR"></a>
|
|
1489
1575
|
|
package/lib/chord.js
CHANGED
|
@@ -12,6 +12,8 @@ var _utilities = require("./utilities");
|
|
|
12
12
|
|
|
13
13
|
var _key = _interopRequireDefault(require("./key"));
|
|
14
14
|
|
|
15
|
+
var _suffixNormalizeMapping = _interopRequireDefault(require("./normalize_mappings/suffix-normalize-mapping"));
|
|
16
|
+
|
|
15
17
|
var _constants = require("./constants");
|
|
16
18
|
|
|
17
19
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
@@ -36,12 +38,6 @@ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollect
|
|
|
36
38
|
|
|
37
39
|
function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
|
|
38
40
|
|
|
39
|
-
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
|
|
40
|
-
|
|
41
|
-
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
|
|
42
|
-
|
|
43
|
-
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
|
|
44
|
-
|
|
45
41
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
46
42
|
|
|
47
43
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
@@ -60,23 +56,12 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function"
|
|
|
60
56
|
|
|
61
57
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
62
58
|
|
|
63
|
-
var MAJOR_SCALE = [null, 'M', 'm', 'm', 'M', 'M', 'm', 'dim'];
|
|
64
|
-
|
|
65
59
|
function normalizeSuffix(suffix) {
|
|
66
|
-
if (suffix === '
|
|
67
|
-
return
|
|
60
|
+
if (_suffixNormalizeMapping["default"][suffix] === '[blank]') {
|
|
61
|
+
return null;
|
|
68
62
|
}
|
|
69
63
|
|
|
70
|
-
return suffix;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function chordSuffix(noteNumber, suffix) {
|
|
74
|
-
if ((0, _utilities.isEmptyString)(suffix)) {
|
|
75
|
-
var defaultSuffix = MAJOR_SCALE[noteNumber];
|
|
76
|
-
return normalizeSuffix(defaultSuffix);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return normalizeSuffix(suffix);
|
|
64
|
+
return _suffixNormalizeMapping["default"][suffix] || suffix;
|
|
80
65
|
}
|
|
81
66
|
|
|
82
67
|
var chordRegex = /*#__PURE__*/_wrapRegExp(/^([A-G])(#|b)?((?:(?![\t-\r \/\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])[\s\S])*)(\/([A-G])(#|b)?)?$/i, {
|
|
@@ -143,15 +128,24 @@ var Chord = /*#__PURE__*/function () {
|
|
|
143
128
|
set: void 0
|
|
144
129
|
});
|
|
145
130
|
|
|
131
|
+
this.suffix = (0, _utilities.presence)(suffix);
|
|
146
132
|
this.root = root || new _key["default"]({
|
|
147
133
|
note: base,
|
|
148
|
-
modifier: modifier
|
|
134
|
+
modifier: modifier,
|
|
135
|
+
minor: suffix === 'm'
|
|
149
136
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
137
|
+
|
|
138
|
+
if (bass) {
|
|
139
|
+
this.bass = bass;
|
|
140
|
+
} else if (bassBase) {
|
|
141
|
+
this.bass = new _key["default"]({
|
|
142
|
+
note: bassBase,
|
|
143
|
+
modifier: bassModifier,
|
|
144
|
+
minor: suffix === 'm'
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
this.bass = null;
|
|
148
|
+
}
|
|
155
149
|
}
|
|
156
150
|
|
|
157
151
|
_createClass(Chord, [{
|
|
@@ -183,10 +177,11 @@ var Chord = /*#__PURE__*/function () {
|
|
|
183
177
|
|
|
184
178
|
var keyObj = _key["default"].wrap(key);
|
|
185
179
|
|
|
180
|
+
var rootKey = this.root.toChordSymbol(keyObj).normalizeEnharmonics(keyObj);
|
|
186
181
|
var chordSymbolChord = new Chord({
|
|
187
|
-
suffix:
|
|
188
|
-
root:
|
|
189
|
-
bass: (_this$bass = this.bass) === null || _this$bass === void 0 ? void 0 : _this$bass.toChordSymbol(keyObj)
|
|
182
|
+
suffix: normalizeSuffix(this.suffix),
|
|
183
|
+
root: rootKey,
|
|
184
|
+
bass: (_this$bass = this.bass) === null || _this$bass === void 0 ? void 0 : _this$bass.toChordSymbol(keyObj).normalizeEnharmonics(rootKey)
|
|
190
185
|
});
|
|
191
186
|
|
|
192
187
|
if (this.root.isMinor()) {
|
|
@@ -247,7 +242,7 @@ var Chord = /*#__PURE__*/function () {
|
|
|
247
242
|
var keyObj = _key["default"].wrap(key);
|
|
248
243
|
|
|
249
244
|
return new Chord({
|
|
250
|
-
suffix:
|
|
245
|
+
suffix: normalizeSuffix(this.suffix),
|
|
251
246
|
root: this.root.toNumeric(keyObj),
|
|
252
247
|
bass: (_this$bass3 = this.bass) === null || _this$bass3 === void 0 ? void 0 : _this$bass3.toNumeric(keyObj)
|
|
253
248
|
});
|
|
@@ -282,7 +277,7 @@ var Chord = /*#__PURE__*/function () {
|
|
|
282
277
|
var keyObj = _key["default"].wrap(key);
|
|
283
278
|
|
|
284
279
|
return new Chord({
|
|
285
|
-
suffix:
|
|
280
|
+
suffix: normalizeSuffix(this.suffix),
|
|
286
281
|
root: this.root.toNumeral(keyObj),
|
|
287
282
|
bass: (_this$bass5 = this.bass) === null || _this$bass5 === void 0 ? void 0 : _this$bass5.toNumeral(keyObj)
|
|
288
283
|
});
|
|
@@ -350,7 +345,7 @@ var Chord = /*#__PURE__*/function () {
|
|
|
350
345
|
return chordString;
|
|
351
346
|
}
|
|
352
347
|
/**
|
|
353
|
-
* Normalizes the chord:
|
|
348
|
+
* Normalizes the chord root and bass notes:
|
|
354
349
|
* - Fb becomes E
|
|
355
350
|
* - Cb becomes B
|
|
356
351
|
* - B# becomes C
|
|
@@ -360,14 +355,26 @@ var Chord = /*#__PURE__*/function () {
|
|
|
360
355
|
* - 7# becomes 1
|
|
361
356
|
* - 3# becomes 4
|
|
362
357
|
*
|
|
363
|
-
*
|
|
358
|
+
* Besides that it normalizes the suffix. For example, `sus2` becomes `2`, `sus4` becomes `sus`.
|
|
359
|
+
* All suffix normalizations can be found in `src/normalize_mappings/suffix-mapping.txt`.
|
|
360
|
+
*
|
|
364
361
|
* @returns {Chord} the normalized chord
|
|
365
362
|
*/
|
|
366
363
|
|
|
367
364
|
}, {
|
|
368
365
|
key: "normalize",
|
|
369
|
-
value: function normalize() {
|
|
370
|
-
|
|
366
|
+
value: function normalize(key) {
|
|
367
|
+
if (!(0, _utilities.presence)(key)) {
|
|
368
|
+
return _classPrivateMethodGet(this, _process, _process2).call(this, 'normalize').set({
|
|
369
|
+
suffix: (0, _utilities.presence)(normalizeSuffix(this.suffix))
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return this.set({
|
|
374
|
+
root: this.root.normalizeEnharmonics(key),
|
|
375
|
+
suffix: (0, _utilities.presence)(normalizeSuffix(this.suffix)),
|
|
376
|
+
bass: this.bass ? this.bass.normalizeEnharmonics(this.root.toString()) : null
|
|
377
|
+
});
|
|
371
378
|
}
|
|
372
379
|
/**
|
|
373
380
|
* Switches to the specified modifier
|
|
@@ -66,6 +66,11 @@ var ChordLyricsPair = /*#__PURE__*/function () {
|
|
|
66
66
|
value: function toString() {
|
|
67
67
|
return "ChordLyricsPair(chords=".concat(this.chords, ", lyrics=").concat(this.lyrics, ")");
|
|
68
68
|
}
|
|
69
|
+
}, {
|
|
70
|
+
key: "set",
|
|
71
|
+
value: function set(properties) {
|
|
72
|
+
return new this.constructor(properties.chords || this.chords, properties.lyrics || this.lyrics);
|
|
73
|
+
}
|
|
69
74
|
}]);
|
|
70
75
|
|
|
71
76
|
return ChordLyricsPair;
|
package/lib/chord_sheet/line.js
CHANGED
|
@@ -15,6 +15,12 @@ var _constants = require("../constants");
|
|
|
15
15
|
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
17
17
|
|
|
18
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
19
|
+
|
|
20
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
21
|
+
|
|
22
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
23
|
+
|
|
18
24
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
19
25
|
|
|
20
26
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
@@ -93,9 +99,17 @@ var Line = /*#__PURE__*/function () {
|
|
|
93
99
|
}, {
|
|
94
100
|
key: "clone",
|
|
95
101
|
value: function clone() {
|
|
102
|
+
return this.mapItems(null);
|
|
103
|
+
}
|
|
104
|
+
}, {
|
|
105
|
+
key: "mapItems",
|
|
106
|
+
value: function mapItems(func) {
|
|
96
107
|
var clonedLine = new Line();
|
|
97
108
|
clonedLine.items = this.items.map(function (item) {
|
|
98
|
-
|
|
109
|
+
var clonedItem = item.clone();
|
|
110
|
+
return func ? func(clonedItem) : clonedItem;
|
|
111
|
+
}).filter(function (item) {
|
|
112
|
+
return item;
|
|
99
113
|
});
|
|
100
114
|
clonedLine.type = this.type;
|
|
101
115
|
return clonedLine;
|
|
@@ -176,6 +190,14 @@ var Line = /*#__PURE__*/function () {
|
|
|
176
190
|
this.items.push(comment);
|
|
177
191
|
return comment;
|
|
178
192
|
}
|
|
193
|
+
}, {
|
|
194
|
+
key: "set",
|
|
195
|
+
value: function set(properties) {
|
|
196
|
+
return new this.constructor(_objectSpread({
|
|
197
|
+
type: this.type,
|
|
198
|
+
items: this.items
|
|
199
|
+
}, properties));
|
|
200
|
+
}
|
|
179
201
|
}]);
|
|
180
202
|
|
|
181
203
|
return Line;
|
|
@@ -74,6 +74,11 @@ var Metadata = /*#__PURE__*/function () {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
_createClass(Metadata, [{
|
|
77
|
+
key: "contains",
|
|
78
|
+
value: function contains(key) {
|
|
79
|
+
return key in this;
|
|
80
|
+
}
|
|
81
|
+
}, {
|
|
77
82
|
key: "add",
|
|
78
83
|
value: function add(key, value) {
|
|
79
84
|
if ((0, _tag.isReadonlyTag)(key)) {
|
|
@@ -98,6 +103,15 @@ var Metadata = /*#__PURE__*/function () {
|
|
|
98
103
|
|
|
99
104
|
this[key] = [currentValue, value];
|
|
100
105
|
}
|
|
106
|
+
}, {
|
|
107
|
+
key: "set",
|
|
108
|
+
value: function set(key, value) {
|
|
109
|
+
if (value) {
|
|
110
|
+
this[key] = value;
|
|
111
|
+
} else {
|
|
112
|
+
delete this[key];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
101
115
|
/**
|
|
102
116
|
* Reads a metadata value by key. This method supports simple value lookup, as fetching single array values.
|
|
103
117
|
*
|
package/lib/chord_sheet/song.js
CHANGED
|
@@ -11,6 +11,12 @@ var _line = _interopRequireDefault(require("./line"));
|
|
|
11
11
|
|
|
12
12
|
var _paragraph = _interopRequireDefault(require("./paragraph"));
|
|
13
13
|
|
|
14
|
+
var _key = _interopRequireDefault(require("../key"));
|
|
15
|
+
|
|
16
|
+
var _chord = _interopRequireDefault(require("../chord"));
|
|
17
|
+
|
|
18
|
+
var _chord_lyrics_pair = _interopRequireDefault(require("./chord_lyrics_pair"));
|
|
19
|
+
|
|
14
20
|
var _utilities = require("../utilities");
|
|
15
21
|
|
|
16
22
|
var _metadata = _interopRequireDefault(require("./metadata"));
|
|
@@ -45,6 +51,22 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
|
|
|
45
51
|
|
|
46
52
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
47
53
|
|
|
54
|
+
function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
|
|
55
|
+
|
|
56
|
+
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
|
|
57
|
+
|
|
58
|
+
function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
|
|
59
|
+
|
|
60
|
+
var _insertDirective = /*#__PURE__*/new WeakSet();
|
|
61
|
+
|
|
62
|
+
var _mapItems = /*#__PURE__*/new WeakSet();
|
|
63
|
+
|
|
64
|
+
var _mapLines = /*#__PURE__*/new WeakSet();
|
|
65
|
+
|
|
66
|
+
var _updateItem = /*#__PURE__*/new WeakSet();
|
|
67
|
+
|
|
68
|
+
var _removeItem = /*#__PURE__*/new WeakSet();
|
|
69
|
+
|
|
48
70
|
/**
|
|
49
71
|
* Represents a song in a chord sheet. Currently a chord sheet can only have one song.
|
|
50
72
|
*/
|
|
@@ -58,16 +80,24 @@ var Song = /*#__PURE__*/function () {
|
|
|
58
80
|
|
|
59
81
|
_classCallCheck(this, Song);
|
|
60
82
|
|
|
83
|
+
_classPrivateMethodInitSpec(this, _removeItem);
|
|
84
|
+
|
|
85
|
+
_classPrivateMethodInitSpec(this, _updateItem);
|
|
86
|
+
|
|
87
|
+
_classPrivateMethodInitSpec(this, _mapLines);
|
|
88
|
+
|
|
89
|
+
_classPrivateMethodInitSpec(this, _mapItems);
|
|
90
|
+
|
|
91
|
+
_classPrivateMethodInitSpec(this, _insertDirective);
|
|
92
|
+
|
|
61
93
|
/**
|
|
62
94
|
* The {@link Line} items of which the song consists
|
|
63
|
-
* @member
|
|
64
|
-
* @type {Array<Line>}
|
|
95
|
+
* @member {Array<Line>}
|
|
65
96
|
*/
|
|
66
97
|
this.lines = [];
|
|
67
98
|
/**
|
|
68
99
|
* The {@link Paragraph} items of which the song consists
|
|
69
|
-
* @member
|
|
70
|
-
* @type {Paragraph[]}
|
|
100
|
+
* @member {Paragraph[]}
|
|
71
101
|
*/
|
|
72
102
|
|
|
73
103
|
this.paragraphs = [];
|
|
@@ -83,6 +113,7 @@ var Song = /*#__PURE__*/function () {
|
|
|
83
113
|
this.warnings = [];
|
|
84
114
|
this.sectionType = _constants.NONE;
|
|
85
115
|
this.currentKey = null;
|
|
116
|
+
this.transposeKey = null;
|
|
86
117
|
}
|
|
87
118
|
|
|
88
119
|
_createClass(Song, [{
|
|
@@ -147,11 +178,14 @@ var Song = /*#__PURE__*/function () {
|
|
|
147
178
|
}, {
|
|
148
179
|
key: "addLine",
|
|
149
180
|
value: function addLine() {
|
|
181
|
+
var _this$transposeKey;
|
|
182
|
+
|
|
150
183
|
this.ensureParagraph();
|
|
151
184
|
this.flushLine();
|
|
152
185
|
this.currentLine = (0, _utilities.pushNew)(this.lines, _line["default"]);
|
|
153
186
|
this.setCurrentLineType(this.sectionType);
|
|
154
|
-
this.currentLine.
|
|
187
|
+
this.currentLine.transposeKey = (_this$transposeKey = this.transposeKey) !== null && _this$transposeKey !== void 0 ? _this$transposeKey : this.currentKey;
|
|
188
|
+
this.currentLine.key = this.currentKey || this.key;
|
|
155
189
|
return this.currentLine;
|
|
156
190
|
}
|
|
157
191
|
}, {
|
|
@@ -211,6 +245,8 @@ var Song = /*#__PURE__*/function () {
|
|
|
211
245
|
if (tag.isMetaTag()) {
|
|
212
246
|
this.setMetaData(tag.name, tag.value);
|
|
213
247
|
} else if (tag.name === _tag.TRANSPOSE) {
|
|
248
|
+
this.transposeKey = tag.value;
|
|
249
|
+
} else if (tag.name === _tag.NEW_KEY) {
|
|
214
250
|
this.currentKey = tag.value;
|
|
215
251
|
} else {
|
|
216
252
|
this.setSectionTypeFromTag(tag);
|
|
@@ -304,12 +340,7 @@ var Song = /*#__PURE__*/function () {
|
|
|
304
340
|
}, {
|
|
305
341
|
key: "clone",
|
|
306
342
|
value: function clone() {
|
|
307
|
-
|
|
308
|
-
clonedSong.lines = this.lines.map(function (line) {
|
|
309
|
-
return line.clone();
|
|
310
|
-
});
|
|
311
|
-
clonedSong.metadata = this.metadata.clone();
|
|
312
|
-
return clonedSong;
|
|
343
|
+
return _classPrivateMethodGet(this, _mapItems, _mapItems2).call(this, null);
|
|
313
344
|
}
|
|
314
345
|
}, {
|
|
315
346
|
key: "setMetaData",
|
|
@@ -333,11 +364,158 @@ var Song = /*#__PURE__*/function () {
|
|
|
333
364
|
value: function getMetaData(name) {
|
|
334
365
|
return this.metadata[name] || null;
|
|
335
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Returns a copy of the song with the capo value set to the specified capo. It changes:
|
|
369
|
+
* - the value for `capo` in the `metadata` set
|
|
370
|
+
* - any existing `capo` directive)
|
|
371
|
+
* @param {number|null} capo the capo. Passing `null` will:
|
|
372
|
+
* - remove the current key from `metadata`
|
|
373
|
+
* - remove any `capo` directive
|
|
374
|
+
* @returns {Song} The changed song
|
|
375
|
+
*/
|
|
376
|
+
|
|
377
|
+
}, {
|
|
378
|
+
key: "setCapo",
|
|
379
|
+
value: function setCapo(capo) {
|
|
380
|
+
var updatedSong;
|
|
381
|
+
|
|
382
|
+
if (capo === null) {
|
|
383
|
+
updatedSong = _classPrivateMethodGet(this, _removeItem, _removeItem2).call(this, function (item) {
|
|
384
|
+
return item instanceof _tag["default"] && item.name === _tag.CAPO;
|
|
385
|
+
});
|
|
386
|
+
} else {
|
|
387
|
+
updatedSong = _classPrivateMethodGet(this, _updateItem, _updateItem2).call(this, function (item) {
|
|
388
|
+
return item instanceof _tag["default"] && item.name === _tag.CAPO;
|
|
389
|
+
}, function (item) {
|
|
390
|
+
return item.set({
|
|
391
|
+
value: capo
|
|
392
|
+
});
|
|
393
|
+
}, function (song) {
|
|
394
|
+
return _classPrivateMethodGet(song, _insertDirective, _insertDirective2).call(song, _tag.CAPO, capo);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
updatedSong.metadata.set('capo', capo);
|
|
399
|
+
return updatedSong;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Returns a copy of the song with the key set to the specified key. It changes:
|
|
403
|
+
* - the value for `key` in the `metadata` set
|
|
404
|
+
* - any existing `key` directive
|
|
405
|
+
* - all chords, those are transposed according to the distance between the current and the new key
|
|
406
|
+
* @param {string} key The new key.
|
|
407
|
+
* @returns {Song} The changed song
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
}, {
|
|
411
|
+
key: "setKey",
|
|
412
|
+
value: function setKey(key) {
|
|
413
|
+
var transpose = _key["default"].distance(this.key, key);
|
|
414
|
+
|
|
415
|
+
var updatedSong = _classPrivateMethodGet(this, _mapItems, _mapItems2).call(this, function (item) {
|
|
416
|
+
if (item instanceof _tag["default"] && item.name === _tag.KEY) {
|
|
417
|
+
return item.set({
|
|
418
|
+
value: key
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (item instanceof _chord_lyrics_pair["default"]) {
|
|
423
|
+
var chordObj = _chord["default"].parse(item.chords);
|
|
424
|
+
|
|
425
|
+
if (chordObj) {
|
|
426
|
+
return item.set({
|
|
427
|
+
chords: chordObj.transpose(transpose).normalize(key)
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return item;
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
updatedSong.metadata.set('key', key);
|
|
436
|
+
return updatedSong;
|
|
437
|
+
}
|
|
336
438
|
}]);
|
|
337
439
|
|
|
338
440
|
return Song;
|
|
339
441
|
}();
|
|
340
442
|
|
|
443
|
+
function _insertDirective2(name, value) {
|
|
444
|
+
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
|
|
445
|
+
_ref2$after = _ref2.after,
|
|
446
|
+
after = _ref2$after === void 0 ? null : _ref2$after;
|
|
447
|
+
|
|
448
|
+
var insertIndex = this.lines.findIndex(function (line) {
|
|
449
|
+
return line.items.some(function (item) {
|
|
450
|
+
return !(item instanceof _tag["default"]) || after && item instanceof _tag["default"] && item.name === after;
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
var newLine = new _line["default"]();
|
|
454
|
+
newLine.addTag(name, value);
|
|
455
|
+
var clonedSong = this.clone();
|
|
456
|
+
var lines = clonedSong.lines;
|
|
457
|
+
clonedSong.lines = [].concat(_toConsumableArray(lines.slice(0, insertIndex)), [newLine], _toConsumableArray(lines.slice(insertIndex)));
|
|
458
|
+
return clonedSong;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function _mapItems2(func) {
|
|
462
|
+
var clonedSong = new Song();
|
|
463
|
+
clonedSong.lines = this.lines.map(function (line) {
|
|
464
|
+
return line.mapItems(func);
|
|
465
|
+
});
|
|
466
|
+
clonedSong.metadata = this.metadata.clone();
|
|
467
|
+
return clonedSong;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function _mapLines2(func) {
|
|
471
|
+
var clonedSong = new Song();
|
|
472
|
+
clonedSong.lines = this.lines.map(function (line) {
|
|
473
|
+
return func(line.clone());
|
|
474
|
+
}).filter(function (line) {
|
|
475
|
+
return line;
|
|
476
|
+
});
|
|
477
|
+
clonedSong.metadata = this.metadata.clone();
|
|
478
|
+
return clonedSong;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function _updateItem2(findCallback, updateCallback, notFoundCallback) {
|
|
482
|
+
var found = false;
|
|
483
|
+
|
|
484
|
+
var updatedSong = _classPrivateMethodGet(this, _mapItems, _mapItems2).call(this, function (item) {
|
|
485
|
+
if (findCallback(item)) {
|
|
486
|
+
found = true;
|
|
487
|
+
return updateCallback(item);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return item;
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
if (!found) {
|
|
494
|
+
return notFoundCallback(updatedSong);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return updatedSong;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function _removeItem2(callback) {
|
|
501
|
+
return _classPrivateMethodGet(this, _mapLines, _mapLines2).call(this, function (line) {
|
|
502
|
+
var items = line.items;
|
|
503
|
+
var index = items.findIndex(callback);
|
|
504
|
+
|
|
505
|
+
if (index === -1) {
|
|
506
|
+
return line;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (items.length === 1) {
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return line.set({
|
|
514
|
+
items: [].concat(_toConsumableArray(items.slice(0, index)), _toConsumableArray(items.slice(index + 1)))
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
341
519
|
var defineProperty = Object.defineProperty;
|
|
342
520
|
var songPrototype = Song.prototype;
|
|
343
521
|
|