chordsheetjs 5.1.2 → 6.0.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.
Files changed (34) hide show
  1. package/d7b54993c4ea66c07a35bd36690482ab620f836e.patch +105 -0
  2. package/lib/chord.js +155 -43
  3. package/lib/chord_sheet/chord_lyrics_pair.js +1 -1
  4. package/lib/chord_sheet/chord_pro/composite.js +1 -1
  5. package/lib/chord_sheet/chord_pro/evaluation_error.js +7 -3
  6. package/lib/chord_sheet/chord_pro/literal.js +1 -1
  7. package/lib/chord_sheet/chord_pro/ternary.js +1 -1
  8. package/lib/chord_sheet/comment.js +1 -1
  9. package/lib/chord_sheet/line.js +1 -1
  10. package/lib/chord_sheet/metadata.js +1 -1
  11. package/lib/chord_sheet/paragraph.js +1 -1
  12. package/lib/chord_sheet/song.js +2 -2
  13. package/lib/chord_sheet/tag.js +1 -1
  14. package/lib/chord_sheet_serializer.js +1 -1
  15. package/lib/constants.js +6 -2
  16. package/lib/formatter/chord_pro_formatter.js +1 -1
  17. package/lib/formatter/html_div_formatter.js +4 -4
  18. package/lib/formatter/html_formatter.js +1 -1
  19. package/lib/formatter/html_table_formatter.js +4 -4
  20. package/lib/formatter/text_formatter.js +4 -2
  21. package/lib/index.js +1 -1
  22. package/lib/key.js +101 -26
  23. package/lib/normalize_mappings/enharmonic-normalize.js +124 -0
  24. package/lib/normalize_mappings/generate-suffix-normalize-mapping.js +36 -0
  25. package/lib/normalize_mappings/suffix-normalize-mapping.js +914 -0
  26. package/lib/note.js +161 -29
  27. package/lib/parser/chord_pro_parser.js +1 -1
  28. package/lib/parser/chord_pro_peg_parser.js +22 -13
  29. package/lib/parser/chord_sheet_parser.js +1 -1
  30. package/lib/parser/parser_warning.js +1 -1
  31. package/lib/parser/ultimate_guitar_parser.js +3 -3
  32. package/lib/{handlebars_helpers.js → template_helpers.js} +16 -1
  33. package/lib/utilities.js +2 -16
  34. package/package.json +11 -8
@@ -0,0 +1,105 @@
1
+ commit d7b54993c4ea66c07a35bd36690482ab620f836e
2
+ Author: Martijn Versluis <martijnversluis@users.noreply.github.com>
3
+ Date: Sun Jan 30 16:35:24 2022 +0100
4
+
5
+ Do not rely on contructor name
6
+
7
+ Due to build tools scrambling constructor names, we can not rely on those
8
+ for type checking. Thus we have to use `instanceof`. This change removes
9
+ usages of `constructor.name` and solves the cyclic dependency by moving around
10
+ some functions.
11
+
12
+ Resolves #421
13
+
14
+ diff --git a/src/formatter/html_div_formatter.js b/src/formatter/html_div_formatter.js
15
+ index f92f532..b1de230 100644
16
+ --- a/src/formatter/html_div_formatter.js
17
+ +++ b/src/formatter/html_div_formatter.js
18
+ @@ -1,6 +1,6 @@
19
+ import Handlebars from 'handlebars';
20
+
21
+ -import '../handlebars_helpers';
22
+ +import '../template_helpers';
23
+ import HtmlFormatter from './html_formatter';
24
+ import './templates/html_div_formatter';
25
+ import { scopeCss } from '../utilities';
26
+ diff --git a/src/formatter/html_table_formatter.js b/src/formatter/html_table_formatter.js
27
+ index 4883fef..7d7e8ea 100644
28
+ --- a/src/formatter/html_table_formatter.js
29
+ +++ b/src/formatter/html_table_formatter.js
30
+ @@ -1,6 +1,6 @@
31
+ import Handlebars from 'handlebars';
32
+
33
+ -import '../handlebars_helpers';
34
+ +import '../template_helpers';
35
+ import HtmlFormatter from './html_formatter';
36
+ import './templates/html_table_formatter';
37
+ import { scopeCss } from '../utilities';
38
+ diff --git a/src/formatter/text_formatter.js b/src/formatter/text_formatter.js
39
+ index 61385f1..81fe226 100644
40
+ --- a/src/formatter/text_formatter.js
41
+ +++ b/src/formatter/text_formatter.js
42
+ @@ -1,10 +1,10 @@
43
+ import ChordLyricsPair from '../chord_sheet/chord_lyrics_pair';
44
+ import Tag from '../chord_sheet/tag';
45
+ import { renderChord } from '../helpers';
46
+ +import { hasTextContents } from '../template_helpers';
47
+
48
+ import {
49
+ hasChordContents,
50
+ - hasTextContents,
51
+ padLeft,
52
+ } from '../utilities';
53
+
54
+ diff --git a/src/handlebars_helpers.js b/src/template_helpers.js
55
+ similarity index 87%
56
+ rename from src/handlebars_helpers.js
57
+ rename to src/template_helpers.js
58
+ index 0e5ff98..b330f87 100644
59
+ --- a/src/handlebars_helpers.js
60
+ +++ b/src/template_helpers.js
61
+ @@ -7,12 +7,20 @@ import { renderChord } from './helpers';
62
+
63
+ import {
64
+ hasChordContents,
65
+ - hasTextContents,
66
+ isEvaluatable,
67
+ } from './utilities';
68
+
69
+ const lineHasContents = (line) => line.items.some((item) => item.isRenderable());
70
+
71
+ +/* eslint import/prefer-default-export: 0 */
72
+ +export const hasTextContents = (line) => (
73
+ + line.items.some((item) => (
74
+ + (item instanceof ChordLyricsPair && item.lyrics)
75
+ + || (item instanceof Tag && item.isRenderable())
76
+ + || isEvaluatable(item)
77
+ + ))
78
+ +);
79
+ +
80
+ HandleBars.registerHelper('isChordLyricsPair', (item) => item instanceof ChordLyricsPair);
81
+
82
+ HandleBars.registerHelper('isTag', (item) => item instanceof Tag);
83
+ diff --git a/src/utilities.js b/src/utilities.js
84
+ index 03c69cc..503c811 100644
85
+ --- a/src/utilities.js
86
+ +++ b/src/utilities.js
87
+ @@ -8,18 +8,6 @@ export const hasChordContents = (line) => line.items.some((item) => !!item.chord
88
+
89
+ export const isEvaluatable = (item) => typeof item.evaluate === 'function';
90
+
91
+ -function isInstanceOf(object, constructorName) {
92
+ - return object?.constructor?.name === constructorName;
93
+ -}
94
+ -
95
+ -export const hasTextContents = (line) => (
96
+ - line.items.some((item) => (
97
+ - (isInstanceOf(item, 'ChordLyricsPair') && item.lyrics)
98
+ - || (isInstanceOf(item, 'Tag') && item.isRenderable())
99
+ - || isEvaluatable(item)
100
+ - ))
101
+ -);
102
+ -
103
+ export const padLeft = (str, length) => {
104
+ let paddedString = str;
105
+ for (let l = str.length; l < length; l += 1, paddedString += ' ');
package/lib/chord.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
4
 
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
@@ -12,13 +12,15 @@ 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 }; }
18
20
 
19
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
21
+ 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; }
20
22
 
21
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
23
+ 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; }
22
24
 
23
25
  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; }
24
26
 
@@ -26,7 +28,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
26
28
 
27
29
  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); } }
28
30
 
29
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
31
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
30
32
 
31
33
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
32
34
 
@@ -36,35 +38,30 @@ 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); }
41
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
40
42
 
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); }
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."); }
42
44
 
43
- function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
45
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
44
46
 
45
- function _wrapRegExp() { _wrapRegExp = function _wrapRegExp(re, groups) { return new BabelRegExp(re, undefined, groups); }; var _super = RegExp.prototype; var _groups = new WeakMap(); function BabelRegExp(re, flags, groups) { var _this = new RegExp(re, flags); _groups.set(_this, groups || _groups.get(re)); return _setPrototypeOf(_this, BabelRegExp.prototype); } _inherits(BabelRegExp, RegExp); BabelRegExp.prototype.exec = function (str) { var result = _super.exec.call(this, str); if (result) result.groups = buildGroups(result, this); return result; }; BabelRegExp.prototype[Symbol.replace] = function (str, substitution) { if (typeof substitution === "string") { var groups = _groups.get(this); return _super[Symbol.replace].call(this, str, substitution.replace(/\$<([^>]+)>/g, function (_, name) { return "$" + groups[name]; })); } else if (typeof substitution === "function") { var _this = this; return _super[Symbol.replace].call(this, str, function () { var args = arguments; if (_typeof(args[args.length - 1]) !== "object") { args = [].slice.call(args); args.push(buildGroups(args, _this)); } return substitution.apply(this, args); }); } else { return _super[Symbol.replace].call(this, str, substitution); } }; function buildGroups(result, re) { var g = _groups.get(re); return Object.keys(g).reduce(function (groups, name) { groups[name] = result[g[name]]; return groups; }, Object.create(null)); } return _wrapRegExp.apply(this, arguments); }
47
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
46
48
 
47
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
49
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
48
50
 
49
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
51
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
50
52
 
51
- var MAJOR_SCALE = [null, 'M', 'm', 'm', 'M', 'M', 'm', 'dim'];
53
+ function _wrapRegExp() { _wrapRegExp = function _wrapRegExp(re, groups) { return new BabelRegExp(re, void 0, groups); }; var _super = RegExp.prototype, _groups = new WeakMap(); function BabelRegExp(re, flags, groups) { var _this = new RegExp(re, flags); return _groups.set(_this, groups || _groups.get(re)), _setPrototypeOf(_this, BabelRegExp.prototype); } function buildGroups(result, re) { var g = _groups.get(re); return Object.keys(g).reduce(function (groups, name) { return groups[name] = result[g[name]], groups; }, Object.create(null)); } return _inherits(BabelRegExp, RegExp), BabelRegExp.prototype.exec = function (str) { var result = _super.exec.call(this, str); return result && (result.groups = buildGroups(result, this)), result; }, BabelRegExp.prototype[Symbol.replace] = function (str, substitution) { if ("string" == typeof substitution) { var groups = _groups.get(this); return _super[Symbol.replace].call(this, str, substitution.replace(/\$<([^>]+)>/g, function (_, name) { return "$" + groups[name]; })); } if ("function" == typeof substitution) { var _this = this; return _super[Symbol.replace].call(this, str, function () { var args = arguments; return "object" != _typeof(args[args.length - 1]) && (args = [].slice.call(args)).push(buildGroups(args, _this)), substitution.apply(this, args); }); } return _super[Symbol.replace].call(this, str, substitution); }, _wrapRegExp.apply(this, arguments); }
52
54
 
53
- function normalizeSuffix(suffix) {
54
- if (suffix === 'M') {
55
- return '';
56
- }
55
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
57
56
 
58
- return suffix;
59
- }
57
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
60
58
 
61
- function chordSuffix(noteNumber, suffix) {
62
- if ((0, _utilities.isEmptyString)(suffix)) {
63
- var defaultSuffix = MAJOR_SCALE[noteNumber];
64
- return normalizeSuffix(defaultSuffix);
59
+ function normalizeSuffix(suffix) {
60
+ if (_suffixNormalizeMapping["default"][suffix] === '[blank]') {
61
+ return null;
65
62
  }
66
63
 
67
- return normalizeSuffix(suffix);
64
+ return _suffixNormalizeMapping["default"][suffix] || suffix;
68
65
  }
69
66
 
70
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, {
@@ -83,7 +80,16 @@ var numericChordRegex = /*#__PURE__*/_wrapRegExp(/^(#|b)?([1-7])((?:(?![\t-\r \/
83
80
  bassBase: 6
84
81
  });
85
82
 
86
- var regexes = [numericChordRegex, chordRegex];
83
+ var sortedNumerals = _toConsumableArray(_constants.ROMAN_NUMERALS).sort(function (numeralA, numeralB) {
84
+ return numeralB.length - numeralA.length;
85
+ });
86
+
87
+ var numerals = [].concat(_toConsumableArray(sortedNumerals), _toConsumableArray(sortedNumerals.map(function (numeral) {
88
+ return numeral.toLowerCase();
89
+ }))).join('|');
90
+ var numeralChordRegex = // eslint-disable-next-line max-len
91
+ new RegExp("^(?<modifier>#|b)?(?<base>".concat(numerals, ")(?<suffix>[^/\\s]*)(\\/(?<bassModifier>#|b)?(?<bassBase>").concat(numerals, "))?$"));
92
+ var regexes = [numericChordRegex, numeralChordRegex, chordRegex];
87
93
  /**
88
94
  * Represents a Chord, consisting of a root, suffix (quality) and bass
89
95
  */
@@ -122,15 +128,24 @@ var Chord = /*#__PURE__*/function () {
122
128
  set: void 0
123
129
  });
124
130
 
131
+ this.suffix = (0, _utilities.presence)(suffix);
125
132
  this.root = root || new _key["default"]({
126
133
  note: base,
127
- modifier: modifier
134
+ modifier: modifier,
135
+ minor: suffix === 'm'
128
136
  });
129
- this.suffix = (0, _utilities.presence)(suffix);
130
- this.bass = bass || (bassBase ? new _key["default"]({
131
- note: bassBase,
132
- modifier: bassModifier
133
- }) : null);
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
+ }
134
149
  }
135
150
 
136
151
  _createClass(Chord, [{
@@ -162,11 +177,18 @@ var Chord = /*#__PURE__*/function () {
162
177
 
163
178
  var keyObj = _key["default"].wrap(key);
164
179
 
165
- return new Chord({
166
- suffix: chordSuffix(_classPrivateFieldGet(this, _rootNote), this.suffix),
167
- root: this.root.toChordSymbol(keyObj),
168
- bass: (_this$bass = this.bass) === null || _this$bass === void 0 ? void 0 : _this$bass.toChordSymbol(keyObj)
180
+ var rootKey = this.root.toChordSymbol(keyObj).normalizeEnharmonics(keyObj);
181
+ var chordSymbolChord = new Chord({
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)
169
185
  });
186
+
187
+ if (this.root.isMinor()) {
188
+ chordSymbolChord = chordSymbolChord.makeMinor();
189
+ }
190
+
191
+ return chordSymbolChord;
170
192
  }
171
193
  /**
172
194
  * Converts the chord to a chord symbol string, using the supplied key as a reference.
@@ -193,7 +215,7 @@ var Chord = /*#__PURE__*/function () {
193
215
  return _classPrivateMethodGet(this, _is, _is2).call(this, _constants.SYMBOL);
194
216
  }
195
217
  /**
196
- * Converts the chord to a numeric chord, using the supplied kye as a reference.
218
+ * Converts the chord to a numeric chord, using the supplied key as a reference.
197
219
  * For example, a chord symbol A# with reference key E will return the numeric chord #4.
198
220
  * @param {Key|string} key the reference key
199
221
  * @returns {Chord} the numeric chord
@@ -202,20 +224,77 @@ var Chord = /*#__PURE__*/function () {
202
224
  }, {
203
225
  key: "toNumeric",
204
226
  value: function toNumeric(key) {
205
- var _this$bass2;
227
+ var _this$bass3;
206
228
 
207
229
  if (this.isNumeric()) {
208
230
  return this.clone();
209
231
  }
210
232
 
233
+ if (this.isNumeral()) {
234
+ var _this$bass2;
235
+
236
+ return this.set({
237
+ root: this.root.toNumeric(),
238
+ bass: (_this$bass2 = this.bass) === null || _this$bass2 === void 0 ? void 0 : _this$bass2.toNumeric()
239
+ });
240
+ }
241
+
211
242
  var keyObj = _key["default"].wrap(key);
212
243
 
213
244
  return new Chord({
214
- suffix: chordSuffix(_classPrivateFieldGet(this, _rootNote), this.suffix),
245
+ suffix: normalizeSuffix(this.suffix),
215
246
  root: this.root.toNumeric(keyObj),
216
- bass: (_this$bass2 = this.bass) === null || _this$bass2 === void 0 ? void 0 : _this$bass2.toNumeric(keyObj)
247
+ bass: (_this$bass3 = this.bass) === null || _this$bass3 === void 0 ? void 0 : _this$bass3.toNumeric(keyObj)
217
248
  });
218
249
  }
250
+ /**
251
+ * Converts the chord to a numeral chord, using the supplied key as a reference.
252
+ * For example, a chord symbol A# with reference key E will return the numeral chord #IV.
253
+ * @param {Key|string|null} key the reference key. The key is required when converting a chord symbol
254
+ * @returns {Chord} the numeral chord
255
+ */
256
+
257
+ }, {
258
+ key: "toNumeral",
259
+ value: function toNumeral() {
260
+ var _this$bass5;
261
+
262
+ var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
263
+
264
+ if (this.isNumeral()) {
265
+ return this.clone();
266
+ }
267
+
268
+ if (this.isNumeric()) {
269
+ var _this$bass4;
270
+
271
+ return this.set({
272
+ root: this.root.toNumeral(),
273
+ bass: (_this$bass4 = this.bass) === null || _this$bass4 === void 0 ? void 0 : _this$bass4.toNumeral()
274
+ });
275
+ }
276
+
277
+ var keyObj = _key["default"].wrap(key);
278
+
279
+ return new Chord({
280
+ suffix: normalizeSuffix(this.suffix),
281
+ root: this.root.toNumeral(keyObj),
282
+ bass: (_this$bass5 = this.bass) === null || _this$bass5 === void 0 ? void 0 : _this$bass5.toNumeral(keyObj)
283
+ });
284
+ }
285
+ /**
286
+ * Converts the chord to a numeral chord string, using the supplied kye as a reference.
287
+ * For example, a chord symbol A# with reference key E will return the numeral chord #4.
288
+ * @param {Key|string} key the reference key
289
+ * @returns {string} the numeral chord string
290
+ * @see {toNumeral}
291
+ */
292
+
293
+ }, {
294
+ key: "toNumeralString",
295
+ value: function toNumeralString(key) {
296
+ return this.toNumeral(key).toString();
297
+ }
219
298
  /**
220
299
  * Determines whether the chord is numeric
221
300
  * @returns {boolean}
@@ -239,6 +318,16 @@ var Chord = /*#__PURE__*/function () {
239
318
  value: function toNumericString(key) {
240
319
  return this.toNumeric(key).toString();
241
320
  }
321
+ /**
322
+ * Determines whether the chord is a numeral
323
+ * @returns {boolean}
324
+ */
325
+
326
+ }, {
327
+ key: "isNumeral",
328
+ value: function isNumeral() {
329
+ return _classPrivateMethodGet(this, _is, _is2).call(this, _constants.NUMERAL);
330
+ }
242
331
  /**
243
332
  * Converts the chord to a string, eg `Esus4/G#` or `1sus4/#3`
244
333
  * @returns {string} the chord string
@@ -256,7 +345,7 @@ var Chord = /*#__PURE__*/function () {
256
345
  return chordString;
257
346
  }
258
347
  /**
259
- * Normalizes the chord:
348
+ * Normalizes the chord root and bass notes:
260
349
  * - Fb becomes E
261
350
  * - Cb becomes B
262
351
  * - B# becomes C
@@ -266,14 +355,26 @@ var Chord = /*#__PURE__*/function () {
266
355
  * - 7# becomes 1
267
356
  * - 3# becomes 4
268
357
  *
269
- * If the chord is already normalized, this will return a copy.
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
+ *
270
361
  * @returns {Chord} the normalized chord
271
362
  */
272
363
 
273
364
  }, {
274
365
  key: "normalize",
275
- value: function normalize() {
276
- return _classPrivateMethodGet(this, _process, _process2).call(this, 'normalize');
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
+ });
277
378
  }
278
379
  /**
279
380
  * Switches to the specified modifier
@@ -317,15 +418,26 @@ var Chord = /*#__PURE__*/function () {
317
418
  value: function transpose(delta) {
318
419
  return _classPrivateMethodGet(this, _process, _process2).call(this, 'transpose', delta);
319
420
  }
421
+ }, {
422
+ key: "makeMinor",
423
+ value: function makeMinor() {
424
+ if (!this.suffix || this.suffix[0] !== 'm') {
425
+ return this.set({
426
+ suffix: "m".concat(this.suffix || '')
427
+ });
428
+ }
429
+
430
+ return this.clone();
431
+ }
320
432
  }, {
321
433
  key: "set",
322
434
  value: function set(properties) {
323
- var _this$bass3;
435
+ var _this$bass6;
324
436
 
325
437
  return new this.constructor(_objectSpread({
326
438
  root: this.root.clone(),
327
439
  suffix: this.suffix,
328
- bass: (_this$bass3 = this.bass) === null || _this$bass3 === void 0 ? void 0 : _this$bass3.clone()
440
+ bass: (_this$bass6 = this.bass) === null || _this$bass6 === void 0 ? void 0 : _this$bass6.clone()
329
441
  }, properties));
330
442
  }
331
443
  }], [{
@@ -9,7 +9,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
9
9
 
10
10
  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); } }
11
11
 
12
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
13
 
14
14
  /**
15
15
  * Represents a chord with the corresponding (partial) lyrics
@@ -9,7 +9,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
9
9
 
10
10
  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); } }
11
11
 
12
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
13
 
14
14
  var Composite = /*#__PURE__*/function () {
15
15
  function Composite(expressions) {
@@ -1,15 +1,19 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
4
 
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports["default"] = void 0;
9
9
 
10
+ 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); } }
11
+
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
+
10
14
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
11
15
 
12
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
16
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
13
17
 
14
18
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
15
19
 
@@ -47,7 +51,7 @@ var EvaluationError = /*#__PURE__*/function (_Error) {
47
51
  return _this;
48
52
  }
49
53
 
50
- return EvaluationError;
54
+ return _createClass(EvaluationError);
51
55
  }( /*#__PURE__*/_wrapNativeSuper(Error));
52
56
 
53
57
  var _default = EvaluationError;
@@ -9,7 +9,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
9
9
 
10
10
  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); } }
11
11
 
12
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
13
 
14
14
  var Literal = /*#__PURE__*/function () {
15
15
  function Literal(expression) {
@@ -17,7 +17,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
17
17
 
18
18
  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); } }
19
19
 
20
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
20
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
21
21
 
22
22
  var Ternary = /*#__PURE__*/function () {
23
23
  function Ternary() {
@@ -9,7 +9,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
9
9
 
10
10
  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); } }
11
11
 
12
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
13
 
14
14
  /**
15
15
  * Represents a comment. See https://www.chordpro.org/chordpro/chordpro-file-format-specification/#overview
@@ -19,7 +19,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
19
19
 
20
20
  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); } }
21
21
 
22
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
22
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
23
23
 
24
24
  /**
25
25
  * Represents a line in a chord sheet, consisting of items of type ChordLyricsPair or Tag
@@ -35,7 +35,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
35
35
 
36
36
  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); } }
37
37
 
38
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
38
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
39
39
 
40
40
  function appendValue(array, key, value) {
41
41
  if (!array.includes(value)) {
@@ -23,7 +23,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
23
23
 
24
24
  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); } }
25
25
 
26
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
26
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
27
27
 
28
28
  /**
29
29
  * Represents a paragraph of lines in a chord sheet
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
4
 
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
@@ -43,7 +43,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
43
43
 
44
44
  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); } }
45
45
 
46
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
46
+ 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
47
 
48
48
  /**
49
49
  * Represents a song in a chord sheet. Currently a chord sheet can only have one song.
@@ -12,7 +12,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
12
12
 
13
13
  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); } }
14
14
 
15
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
15
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
16
16
 
17
17
  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; }
18
18
 
@@ -25,7 +25,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
25
25
 
26
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); } }
27
27
 
28
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
28
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
29
29
 
30
30
  var CHORD_SHEET = 'chordSheet';
31
31
  var CHORD_LYRICS_PAIR = 'chordLyricsPair';
package/lib/constants.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.VERSE = exports.TAB = exports.SYMBOL = exports.NUMERIC = exports.NONE = exports.INDETERMINATE = exports.CHORUS = void 0;
6
+ exports.VERSE = exports.TAB = exports.SYMBOL = exports.ROMAN_NUMERALS = exports.NUMERIC = exports.NUMERAL = exports.NONE = exports.INDETERMINATE = exports.CHORUS = void 0;
7
7
 
8
8
  /**
9
9
  * Used to mark a paragraph as verse
@@ -47,4 +47,8 @@ exports.TAB = TAB;
47
47
  var SYMBOL = 'symbol';
48
48
  exports.SYMBOL = SYMBOL;
49
49
  var NUMERIC = 'numeric';
50
- exports.NUMERIC = NUMERIC;
50
+ exports.NUMERIC = NUMERIC;
51
+ var NUMERAL = 'numeral';
52
+ exports.NUMERAL = NUMERAL;
53
+ var ROMAN_NUMERALS = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII'];
54
+ exports.ROMAN_NUMERALS = ROMAN_NUMERALS;
@@ -19,7 +19,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
19
19
 
20
20
  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); } }
21
21
 
22
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
22
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
23
23
 
24
24
  var NEW_LINE = '\n';
25
25
  /**