chordsheetjs 6.0.2 → 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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ChordSheetJS [![Build Status](https://travis-ci.org/martijnversluis/ChordSheetJS.svg?branch=master)](https://travis-ci.org/martijnversluis/ChordSheetJS) [![npm version](https://badge.fury.io/js/chordsheetjs.svg)](https://badge.fury.io/js/chordsheetjs) [![Code Climate](https://codeclimate.com/github/martijnversluis/ChordSheetJS/badges/gpa.svg)](https://codeclimate.com/github/martijnversluis/ChordSheetJS)
1
+ # ChordChartJS [![Code Climate](https://codeclimate.com/github/PraiseCharts/ChordChartJS/badges/gpa.svg)](https://codeclimate.com/github/PraiseCharts/ChordChartJS)
2
2
 
3
3
  A JavaScript library for parsing and formatting chord sheets
4
4
 
@@ -469,6 +469,9 @@ Inherits from <a href="#ChordSheetParser">ChordSheetParser</a></p>
469
469
  <dt><a href="#TRANSPOSE">TRANSPOSE</a> : <code>string</code></dt>
470
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
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>
472
475
  <dt><a href="#YEAR">YEAR</a> : <code>string</code></dt>
473
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>
474
477
  </dd>
@@ -756,6 +759,8 @@ Represents a song in a chord sheet. Currently a chord sheet can only have one so
756
759
  * [.bodyParagraphs](#Song+bodyParagraphs) ⇒ [<code>Array.&lt;Paragraph&gt;</code>](#Paragraph)
757
760
  * ~~[.metaData](#Song+metaData) ⇒~~
758
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)
759
764
 
760
765
  <a name="new_Song_new"></a>
761
766
 
@@ -818,6 +823,35 @@ Returns a deep clone of the song
818
823
 
819
824
  **Kind**: instance method of [<code>Song</code>](#Song)
820
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
+
821
855
  <a name="Tag"></a>
822
856
 
823
857
  ## Tag
@@ -1530,6 +1564,12 @@ Title meta directive. See https://www.chordpro.org/chordpro/directives-title/
1530
1564
  ## TRANSPOSE : <code>string</code>
1531
1565
  Transpose meta directive. See: https://www.chordpro.org/chordpro/directives-transpose/
1532
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
+
1533
1573
  **Kind**: global constant
1534
1574
  <a name="YEAR"></a>
1535
1575
 
@@ -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;
@@ -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
- return item.clone();
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
  *
@@ -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.key = this.currentKey;
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
- var clonedSong = new Song();
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
 
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports["default"] = exports._KEY = exports.YEAR = exports.TRANSPOSE = exports.TITLE = exports.TIME = exports.TEMPO = exports.SUBTITLE = exports.START_OF_VERSE = exports.START_OF_TAB = exports.START_OF_CHORUS = exports.READ_ONLY_TAGS = exports.META_TAGS = exports.LYRICIST = exports.KEY = exports.END_OF_VERSE = exports.END_OF_TAB = exports.END_OF_CHORUS = exports.DURATION = exports.COPYRIGHT = exports.COMPOSER = exports.COMMENT = exports.CAPO = exports.ARTIST = exports.ALBUM = void 0;
6
+ exports["default"] = exports._KEY = exports.YEAR = exports.TRANSPOSE = exports.TITLE = exports.TIME = exports.TEMPO = exports.SUBTITLE = exports.START_OF_VERSE = exports.START_OF_TAB = exports.START_OF_CHORUS = exports.READ_ONLY_TAGS = exports.NEW_KEY = exports.META_TAGS = exports.LYRICIST = exports.KEY = exports.END_OF_VERSE = exports.END_OF_TAB = exports.END_OF_CHORUS = exports.DURATION = exports.COPYRIGHT = exports.COMPOSER = exports.COMMENT = exports.CAPO = exports.ARTIST = exports.ALBUM = void 0;
7
7
  exports.isReadonlyTag = isReadonlyTag;
8
8
 
9
9
  var _ALIASES;
@@ -162,11 +162,18 @@ var TITLE = 'title';
162
162
  exports.TITLE = TITLE;
163
163
  var TRANSPOSE = 'transpose';
164
164
  /**
165
- * Year meta directive. See https://www.chordpro.org/chordpro/directives-year/
165
+ * New Key meta directive. See: https://github.com/PraiseCharts/ChordChartJS/issues/53
166
166
  * @type {string}
167
167
  */
168
168
 
169
169
  exports.TRANSPOSE = TRANSPOSE;
170
+ var NEW_KEY = 'new_key';
171
+ /**
172
+ * Year meta directive. See https://www.chordpro.org/chordpro/directives-year/
173
+ * @type {string}
174
+ */
175
+
176
+ exports.NEW_KEY = NEW_KEY;
170
177
  var YEAR = 'year';
171
178
  exports.YEAR = YEAR;
172
179
  var TITLE_SHORT = 't';
@@ -176,12 +183,13 @@ var START_OF_CHORUS_SHORT = 'soc';
176
183
  var END_OF_CHORUS_SHORT = 'eoc';
177
184
  var START_OF_TAB_SHORT = 'sot';
178
185
  var END_OF_TAB_SHORT = 'eot';
186
+ var NEW_KEY_SHORT = 'nk';
179
187
  var RENDERABLE_TAGS = [COMMENT];
180
188
  var META_TAGS = [ALBUM, ARTIST, CAPO, COMPOSER, COPYRIGHT, DURATION, KEY, LYRICIST, TEMPO, TIME, TITLE, SUBTITLE, YEAR];
181
189
  exports.META_TAGS = META_TAGS;
182
190
  var READ_ONLY_TAGS = [_KEY];
183
191
  exports.READ_ONLY_TAGS = READ_ONLY_TAGS;
184
- var ALIASES = (_ALIASES = {}, _defineProperty(_ALIASES, TITLE_SHORT, TITLE), _defineProperty(_ALIASES, SUBTITLE_SHORT, SUBTITLE), _defineProperty(_ALIASES, COMMENT_SHORT, COMMENT), _defineProperty(_ALIASES, START_OF_CHORUS_SHORT, START_OF_CHORUS), _defineProperty(_ALIASES, END_OF_CHORUS_SHORT, END_OF_CHORUS), _defineProperty(_ALIASES, START_OF_TAB_SHORT, START_OF_TAB), _defineProperty(_ALIASES, END_OF_TAB_SHORT, END_OF_TAB), _ALIASES);
192
+ var ALIASES = (_ALIASES = {}, _defineProperty(_ALIASES, TITLE_SHORT, TITLE), _defineProperty(_ALIASES, SUBTITLE_SHORT, SUBTITLE), _defineProperty(_ALIASES, COMMENT_SHORT, COMMENT), _defineProperty(_ALIASES, START_OF_CHORUS_SHORT, START_OF_CHORUS), _defineProperty(_ALIASES, END_OF_CHORUS_SHORT, END_OF_CHORUS), _defineProperty(_ALIASES, START_OF_TAB_SHORT, START_OF_TAB), _defineProperty(_ALIASES, END_OF_TAB_SHORT, END_OF_TAB), _defineProperty(_ALIASES, NEW_KEY_SHORT, NEW_KEY), _ALIASES);
185
193
  var META_TAG_REGEX = /^meta:\s*([^:\s]+)(\s*(.+))?$/;
186
194
  var TAG_REGEX = /^([^:\s]+)(:?\s*(.+))?$/;
187
195
  var CUSTOM_META_TAG_NAME_REGEX = /^x_(.+)$/;
@@ -263,7 +271,7 @@ var Tag = /*#__PURE__*/function () {
263
271
  */
264
272
  function get() {
265
273
  if (this._value) {
266
- return this._value.trim();
274
+ return "".concat(this._value).trim();
267
275
  }
268
276
 
269
277
  return this._value || null;
@@ -309,13 +317,19 @@ var Tag = /*#__PURE__*/function () {
309
317
  }, {
310
318
  key: "clone",
311
319
  value: function clone() {
312
- return new Tag(this.name, this.value);
320
+ return new Tag(this._originalName, this.value);
313
321
  }
314
322
  }, {
315
323
  key: "toString",
316
324
  value: function toString() {
317
325
  return "Tag(name=".concat(this.name, ", value=").concat(this.name, ")");
318
326
  }
327
+ }, {
328
+ key: "set",
329
+ value: function set(_ref2) {
330
+ var value = _ref2.value;
331
+ return new Tag(this._originalName, value);
332
+ }
319
333
  }], [{
320
334
  key: "parse",
321
335
  value: function parse(tag) {
@@ -379,7 +379,7 @@ templates['html_div_formatter'] = template({
379
379
  return undefined;
380
380
  };
381
381
 
382
- return "<div class=\"column\"><div class=\"chord\">" + alias3((lookupProperty(helpers, "renderChord") || depth0 && lookupProperty(depth0, "renderChord") || alias2).call(alias1, depth0 != null ? lookupProperty(depth0, "chords") : depth0, (stack1 = blockParams[3][0]) != null ? lookupProperty(stack1, "key") : stack1, (stack1 = (stack1 = data && lookupProperty(data, "root")) && lookupProperty(stack1, "song")) && lookupProperty(stack1, "key"), {
382
+ return "<div class=\"column\"><div class=\"chord\">" + alias3((lookupProperty(helpers, "renderChord") || depth0 && lookupProperty(depth0, "renderChord") || alias2).call(alias1, depth0 != null ? lookupProperty(depth0, "chords") : depth0, (stack1 = blockParams[3][0]) != null ? lookupProperty(stack1, "key") : stack1, (stack1 = blockParams[3][0]) != null ? lookupProperty(stack1, "transposeKey") : stack1, (stack1 = data && lookupProperty(data, "root")) && lookupProperty(stack1, "song"), {
383
383
  "name": "renderChord",
384
384
  "hash": {},
385
385
  "data": data,
@@ -391,7 +391,7 @@ templates['html_div_formatter'] = template({
391
391
  },
392
392
  "end": {
393
393
  "line": 18,
394
- "column": 103
394
+ "column": 117
395
395
  }
396
396
  }
397
397
  })) + "</div><div class=\"lyrics\">" + alias3((helper = (helper = lookupProperty(helpers, "lyrics") || (depth0 != null ? lookupProperty(depth0, "lyrics") : depth0)) != null ? helper : alias2, typeof helper === "function" ? helper.call(alias1, {
@@ -402,11 +402,11 @@ templates['html_div_formatter'] = template({
402
402
  "loc": {
403
403
  "start": {
404
404
  "line": 18,
405
- "column": 129
405
+ "column": 143
406
406
  },
407
407
  "end": {
408
408
  "line": 18,
409
- "column": 139
409
+ "column": 153
410
410
  }
411
411
  }
412
412
  }) : helper)) + "</div></div>";
@@ -416,7 +416,7 @@ templates['html_table_formatter'] = template({
416
416
  return undefined;
417
417
  };
418
418
 
419
- return "<td class=\"chord\">" + container.escapeExpression((lookupProperty(helpers, "renderChord") || depth0 && lookupProperty(depth0, "renderChord") || container.hooks.helperMissing).call(depth0 != null ? depth0 : container.nullContext || {}, depth0 != null ? lookupProperty(depth0, "chords") : depth0, (stack1 = blockParams[4][0]) != null ? lookupProperty(stack1, "key") : stack1, (stack1 = (stack1 = data && lookupProperty(data, "root")) && lookupProperty(stack1, "song")) && lookupProperty(stack1, "key"), {
419
+ return "<td class=\"chord\">" + container.escapeExpression((lookupProperty(helpers, "renderChord") || depth0 && lookupProperty(depth0, "renderChord") || container.hooks.helperMissing).call(depth0 != null ? depth0 : container.nullContext || {}, depth0 != null ? lookupProperty(depth0, "chords") : depth0, (stack1 = blockParams[4][0]) != null ? lookupProperty(stack1, "key") : stack1, (stack1 = blockParams[4][0]) != null ? lookupProperty(stack1, "transposeKey") : stack1, (stack1 = data && lookupProperty(data, "root")) && lookupProperty(stack1, "song"), {
420
420
  "name": "renderChord",
421
421
  "hash": {},
422
422
  "data": data,
@@ -428,7 +428,7 @@ templates['html_table_formatter'] = template({
428
428
  },
429
429
  "end": {
430
430
  "line": 21,
431
- "column": 88
431
+ "column": 102
432
432
  }
433
433
  }
434
434
  })) + "</td>";
@@ -115,7 +115,7 @@ var TextFormatter = /*#__PURE__*/function () {
115
115
  }, {
116
116
  key: "chordLyricsPairLength",
117
117
  value: function chordLyricsPairLength(chordLyricsPair, line) {
118
- var chords = (0, _helpers.renderChord)(chordLyricsPair.chords, line.key, this.song.key);
118
+ var chords = (0, _helpers.renderChord)(chordLyricsPair.chords, line.key, line.transposeKey, this.song);
119
119
  var lyrics = chordLyricsPair.lyrics;
120
120
  var chordsLength = (chords || '').length;
121
121
  var lyricsLength = (lyrics || '').length;
@@ -134,7 +134,7 @@ var TextFormatter = /*#__PURE__*/function () {
134
134
  }
135
135
 
136
136
  if (item instanceof _chord_lyrics_pair["default"]) {
137
- var chords = (0, _helpers.renderChord)(item.chords, line.key, this.song.key);
137
+ var chords = (0, _helpers.renderChord)(item.chords, line.key, line.transposeKey, this.song);
138
138
  return (0, _utilities.padLeft)(chords, this.chordLyricsPairLength(item, line));
139
139
  }
140
140
 
package/lib/helpers.js CHANGED
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.renderChord = renderChord;
7
+ exports.transposeDistance = transposeDistance;
7
8
 
8
9
  var _chord = _interopRequireDefault(require("./chord"));
9
10
 
@@ -13,20 +14,43 @@ var _key = _interopRequireDefault(require("./key"));
13
14
 
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
15
16
 
16
- function transposeDistance(lineKey, songKey) {
17
- if (/^\d+$/.test(lineKey)) {
18
- return parseInt(lineKey, 10);
17
+ function transposeDistance(transposeKey, songKey) {
18
+ if (/^\d+$/.test(transposeKey)) {
19
+ return parseInt(transposeKey, 10);
19
20
  }
20
21
 
21
- return _key["default"].distance(songKey, lineKey);
22
+ return _key["default"].distance(songKey, transposeKey);
22
23
  }
23
- /* eslint import/prefer-default-export: 0 */
24
24
 
25
+ function chordTransposeDistance(capo, transposeKey, songKey) {
26
+ var transpose = -1 * (capo || 0);
25
27
 
26
- function renderChord(chord, lineKey, songKey) {
27
- if ((0, _utilities.presence)(chord) && (0, _utilities.presence)(lineKey) && (0, _utilities.presence)(songKey)) {
28
- return _chord["default"].parse(chord).transpose(transposeDistance(lineKey, songKey)).useModifier(lineKey.modifier).toString();
28
+ if ((0, _utilities.isPresent)(transposeKey) && (0, _utilities.isPresent)(songKey)) {
29
+ transpose += transposeDistance(transposeKey, songKey);
29
30
  }
30
31
 
31
- return chord;
32
+ return transpose;
33
+ }
34
+
35
+ function renderChord(chord, lineKey, transposeKey, song) {
36
+ var chordObj = _chord["default"].parse(chord);
37
+
38
+ var capo = song.capo,
39
+ songKey = song.key;
40
+
41
+ if (!chordObj) {
42
+ return chord;
43
+ }
44
+
45
+ chordObj = chordObj.transpose(chordTransposeDistance(capo, transposeKey, songKey));
46
+
47
+ if ((0, _utilities.isPresent)(transposeKey)) {
48
+ chordObj = chordObj.useModifier(transposeKey.modifier);
49
+ }
50
+
51
+ if ((0, _utilities.isPresent)(lineKey)) {
52
+ chordObj = chordObj.normalize(lineKey);
53
+ }
54
+
55
+ return chordObj.toString();
32
56
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chordsheetjs",
3
3
  "author": "Martijn Versluis",
4
- "version": "6.0.2",
4
+ "version": "6.1.0",
5
5
  "description": "A JavaScript library for parsing and formatting chord sheets",
6
6
  "main": "lib/index.js",
7
7
  "license": "GPL-2.0-only",
@@ -27,7 +27,7 @@
27
27
  "jest": "^27.0.1",
28
28
  "jsdoc-to-markdown": "^7.1.0",
29
29
  "pegjs": "^0.10.0",
30
- "pinst": "^2.1.6",
30
+ "pinst": "^3.0.0",
31
31
  "print": "^1.2.0"
32
32
  },
33
33
  "scripts": {