abcjs 6.4.2 → 6.4.3

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.
@@ -1,5 +1,5 @@
1
1
  /**!
2
- Copyright (c) 2009-2023 Paul Rosen and Gregory Dyke
2
+ Copyright (c) 2009-2024 Paul Rosen and Gregory Dyke
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
@@ -18,7 +18,7 @@ return /******/ (function() { // webpackBootstrap
18
18
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
19
19
 
20
20
  /**!
21
- Copyright (c) 2009-2023 Paul Rosen and Gregory Dyke
21
+ Copyright (c) 2009-2024 Paul Rosen and Gregory Dyke
22
22
 
23
23
  Permission is hereby granted, free of charge, to any person obtaining a copy
24
24
  of this software and associated documentation files (the "Software"), to deal
@@ -617,7 +617,6 @@ var tunebook = {};
617
617
  }
618
618
  }
619
619
  }
620
-
621
620
  return staves;
622
621
  }
623
622
  function measuresParser(staff, tune) {
@@ -1341,7 +1340,6 @@ var Tune = function Tune() {
1341
1340
  };
1342
1341
  return this.meter; // TODO-PER: is this saved value used anywhere? A get function shouldn't change state.
1343
1342
  };
1344
-
1345
1343
  this.getKeySignature = function () {
1346
1344
  for (var i = 0; i < this.lines.length; i++) {
1347
1345
  var line = this.lines[i];
@@ -1496,7 +1494,6 @@ var Tune = function Tune() {
1496
1494
  // isTiedState = voiceTimeMilliseconds;
1497
1495
  }
1498
1496
  }
1499
-
1500
1497
  return {
1501
1498
  isTiedState: isTiedState,
1502
1499
  duration: realDuration / timeDivider,
@@ -1667,6 +1664,7 @@ var Tune = function Tune() {
1667
1664
  }
1668
1665
  this.getBpm = function (tempo) {
1669
1666
  var bpm;
1667
+ if (!tempo) tempo = this.metaText ? this.metaText.tempo : null;
1670
1668
  if (tempo) {
1671
1669
  bpm = tempo.bpm;
1672
1670
  var beatLength = this.getBeatLength();
@@ -3121,7 +3119,6 @@ var Parse = function Parse() {
3121
3119
  multilineVars.lineBreaks = switches.lineBreaks;
3122
3120
  //multilineVars.continueall = true;
3123
3121
  }
3124
-
3125
3122
  header.reset(tokenizer, warn, multilineVars, tune);
3126
3123
  try {
3127
3124
  if (switches.format) {
@@ -3211,7 +3208,6 @@ var bookParser = function bookParser(book) {
3211
3208
  });
3212
3209
  pos += tune.length + 1; // We also lost a newline when splitting, so count that.
3213
3210
  });
3214
-
3215
3211
  if (tunes.length > 1 && !parseCommon.startsWith(tunes[0].abc, 'X:')) {
3216
3212
  // If there is only one tune, the X: might be missing, otherwise assume the top of the file is "intertune"
3217
3213
  // There could be file-wide directives in this, if so, we need to insert it into each tune. We can probably get away with
@@ -4784,7 +4780,6 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
4784
4780
  }
4785
4781
  return ret; // just to suppress warning
4786
4782
  };
4787
-
4788
4783
  var parseFraction = function parseFraction() {
4789
4784
  // handles this much: parseNum slash decimal
4790
4785
  var ret = parseNum();
@@ -4815,7 +4810,6 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
4815
4810
  //var tok = tokens.shift();
4816
4811
  //if (tok.token !== '+') throw "Extra characters in M: line";
4817
4812
  }
4818
-
4819
4813
  if (multilineVars.havent_set_length === true) {
4820
4814
  multilineVars.default_length = totalLength < 0.75 ? 0.0625 : 0.125;
4821
4815
  multilineVars.havent_set_length = false;
@@ -5091,7 +5085,6 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
5091
5085
  // TODO: complain about unhandled header
5092
5086
  }
5093
5087
  }
5094
-
5095
5088
  return [0];
5096
5089
  };
5097
5090
  this.letter_to_body_header = function (line, i) {
@@ -5133,7 +5126,6 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
5133
5126
  // TODO: complain about unhandled header
5134
5127
  }
5135
5128
  }
5136
-
5137
5129
  return [0];
5138
5130
  };
5139
5131
  var metaTextHeaders = {
@@ -5600,7 +5592,6 @@ var parseKeyVoice = {};
5600
5592
  str: str.substring(i)
5601
5593
  }; // We get the note in the middle of the staff. We want the note that appears as the first ledger line below the staff.
5602
5594
  };
5603
-
5604
5595
  var normalizeAccidentals = function normalizeAccidentals(accs) {
5605
5596
  for (var i = 0; i < accs.length; i++) {
5606
5597
  if (accs[i].note === 'b') accs[i].note = 'B';else if (accs[i].note === 'a') accs[i].note = 'A';else if (accs[i].note === 'F') accs[i].note = 'f';else if (accs[i].note === 'E') accs[i].note = 'e';else if (accs[i].note === 'D') accs[i].note = 'd';else if (accs[i].note === 'C') accs[i].note = 'c';else if (accs[i].note === 'G' && accs[i].acc === 'sharp') accs[i].note = 'g';else if (accs[i].note === 'g' && accs[i].acc === 'flat') accs[i].note = 'G';
@@ -6017,7 +6008,6 @@ var parseKeyVoice = {};
6017
6008
  if (multilineVars.currentVoice) {
6018
6009
  if (multilineVars.currentVoice.index === currentVoice.index && multilineVars.currentVoice.staffNum === currentVoice.staffNum) return; // there was no change so don't reset it.
6019
6010
  }
6020
-
6021
6011
  multilineVars.currentVoice = currentVoice;
6022
6012
  return tuneBuilder.setCurrentVoice(currentVoice.staffNum, currentVoice.index, id);
6023
6013
  };
@@ -6233,7 +6223,6 @@ var parseKeyVoice = {};
6233
6223
  // console.log("parse voice", token, tune.metaText.title);
6234
6224
  }
6235
6225
  }
6236
-
6237
6226
  start += tokenizer.eatWhiteSpace(line, start);
6238
6227
  }
6239
6228
 
@@ -6408,7 +6397,6 @@ MusicParser.prototype.parseMusic = function (line) {
6408
6397
  // delayStartNewLine = true;
6409
6398
  // TODO-PER: Handle inline headers
6410
6399
  }
6411
-
6412
6400
  var overlayLevel = 0;
6413
6401
  while (i < line.length) {
6414
6402
  var startI = i;
@@ -6836,15 +6824,30 @@ var letter_to_chord = function letter_to_chord(line, i) {
6836
6824
  chord[1] = chord[1].substring(1);
6837
6825
  chord[2] = 'right';
6838
6826
  } else if (chord[0] > 0 && chord[1].length > 0 && chord[1][0] === '@') {
6839
- // @-15,5.7
6827
+ // @-15,5.7
6840
6828
  chord[1] = chord[1].substring(1);
6841
6829
  var x = tokenizer.getFloat(chord[1]);
6842
- if (x.digits === 0) warn("Missing first position in absolutely positioned annotation.", line, i);
6830
+ if (x.digits === 0) {
6831
+ warn("Missing first position in absolutely positioned annotation.", line, i);
6832
+ chord[1] = chord[1].replace("@", "");
6833
+ chord[2] = 'above';
6834
+ return chord;
6835
+ }
6843
6836
  chord[1] = chord[1].substring(x.digits);
6844
- if (chord[1][0] !== ',') warn("Missing comma absolutely positioned annotation.", line, i);
6837
+ if (chord[1][0] !== ',') {
6838
+ warn("Missing comma absolutely positioned annotation.", line, i);
6839
+ chord[1] = chord[1].replace("@", "");
6840
+ chord[2] = 'above';
6841
+ return chord;
6842
+ }
6845
6843
  chord[1] = chord[1].substring(1);
6846
6844
  var y = tokenizer.getFloat(chord[1]);
6847
- if (y.digits === 0) warn("Missing second position in absolutely positioned annotation.", line, i);
6845
+ if (y.digits === 0) {
6846
+ warn("Missing second position in absolutely positioned annotation.", line, i);
6847
+ chord[1] = chord[1].replace("@", "");
6848
+ chord[2] = 'above';
6849
+ return chord;
6850
+ }
6848
6851
  chord[1] = chord[1].substring(y.digits);
6849
6852
  var ws = tokenizer.skipWhiteSpace(chord[1]);
6850
6853
  chord[1] = chord[1].substring(ws);
@@ -7574,7 +7577,6 @@ var Tokenizer = function Tokenizer(lines, multilineVars) {
7574
7577
  }
7575
7578
  return str.length; // It must have been all white space
7576
7579
  };
7577
-
7578
7580
  var finished = function finished(str, i) {
7579
7581
  return i >= str.length;
7580
7582
  };
@@ -7635,7 +7637,6 @@ var Tokenizer = function Tokenizer(lines, multilineVars) {
7635
7637
  // case 'f':return {len: i+1, token: 'F'};
7636
7638
  // case 'g':return {len: i+1, token: 'G'};
7637
7639
  }
7638
-
7639
7640
  return {
7640
7641
  len: 0
7641
7642
  };
@@ -8467,7 +8468,6 @@ var Tokenizer = function Tokenizer(lines, multilineVars) {
8467
8468
 
8468
8469
  // More chars: IJ ij Ď ď Đ đ Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š Ţ ţ Ť ť Ŧ ŧ Ŵ ŵ Ź ź Ż ż Ž
8469
8470
  };
8470
-
8471
8471
  var charMap1 = {
8472
8472
  "#": "♯",
8473
8473
  "b": "♭",
@@ -9159,7 +9159,6 @@ function transposeChordName(chord, steps, preferFlats, freeGCchord) {
9159
9159
  }
9160
9160
  } else chord += bass; // Don't know what to do so do nothing
9161
9161
  }
9162
-
9163
9162
  if (extra2) chord += extra2;
9164
9163
  return chord;
9165
9164
  }
@@ -9370,7 +9369,6 @@ var TuneBuilder = function TuneBuilder(tune) {
9370
9369
  if (hashParams.rest && hashParams.rest.type === 'invisible') {
9371
9370
  delete hashParams.decoration; // the decorations on invisible rests should be invisible, too.
9372
9371
  }
9373
-
9374
9372
  if (tune.lines.length <= tune.lineNum || tune.lines[tune.lineNum].staff.length <= tune.staffNum) {
9375
9373
  //console.log("pushNote IGNORED", tune.lines[tune.lineNum])
9376
9374
  // TODO-PER: This prevents a crash, but it drops the element. Need to figure out how to start a new line, or delay adding this.
@@ -9838,7 +9836,6 @@ function cleanUpSlursInLine(line, staffNum, voiceNum, currSlur) {
9838
9836
  obj.endSlur.push(slurNum);
9839
9837
  // lyr.syllable += '<' + slurNum; // TODO-PER: debugging
9840
9838
  }
9841
-
9842
9839
  if (currSlur[staffNum][voiceNum][chordPos].length === 0) delete currSlur[staffNum][voiceNum][chordPos];
9843
9840
  return slurNum;
9844
9841
  };
@@ -11088,7 +11085,6 @@ var strTranspose;
11088
11085
  return 0;
11089
11086
  // this should never happen
11090
11087
  }
11091
-
11092
11088
  case '_':
11093
11089
  switch (thisAccidental) {
11094
11090
  case '__':
@@ -11105,7 +11101,6 @@ var strTranspose;
11105
11101
  return 0;
11106
11102
  // this should never happen
11107
11103
  }
11108
-
11109
11104
  case '^':
11110
11105
  switch (thisAccidental) {
11111
11106
  case '__':
@@ -11123,11 +11118,9 @@ var strTranspose;
11123
11118
  // this should never happen
11124
11119
  }
11125
11120
  }
11126
-
11127
11121
  return 0; // this should never happen
11128
11122
  }
11129
11123
  })();
11130
-
11131
11124
  module.exports = strTranspose;
11132
11125
 
11133
11126
  /***/ }),
@@ -11452,7 +11445,6 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11452
11445
  // console.log(JSON.stringify(voices))
11453
11446
  }
11454
11447
  }
11455
-
11456
11448
  function getBeatFraction(meter) {
11457
11449
  switch (parseInt(meter.den, 10)) {
11458
11450
  case 2:
@@ -12228,7 +12220,6 @@ var rendererFactory;
12228
12220
  this.track += this.noteOnAndChannel;
12229
12221
  this.track += "%" + pitch.toString(16) + toHex(loudness, 2); //note
12230
12222
  };
12231
-
12232
12223
  Midi.prototype.endNote = function (pitch) {
12233
12224
  this.track += toDurationHex(this.silencelength); // only need to shift by amount of silence (if there is any)
12234
12225
  this.silencelength = 0;
@@ -12242,7 +12233,6 @@ var rendererFactory;
12242
12233
  this.track += this.noteOffAndChannel;
12243
12234
  this.track += "%" + pitch.toString(16) + "%00"; //end note
12244
12235
  };
12245
-
12246
12236
  Midi.prototype.addRest = function (length) {
12247
12237
  this.silencelength += length;
12248
12238
  if (this.silencelength < 0) this.silencelength = 0;
@@ -12279,7 +12269,6 @@ var rendererFactory;
12279
12269
  }
12280
12270
  return "%00%FF" + cmdType + toHex(nameArray.length / 3, 2) + nameArray; // Each byte is represented by three chars "%XX", so divide by 3 to get the length.
12281
12271
  }
12282
-
12283
12272
  function keySignature(key) {
12284
12273
  //00 FF 5902 03 00 - key signature
12285
12274
  if (!key || !key.accidentals) return "";
@@ -13069,7 +13058,6 @@ var parseCommon = __webpack_require__(/*! ../parse/abc_common */ "./src/parse/ab
13069
13058
  }
13070
13059
  }
13071
13060
  }
13072
-
13073
13061
  function chordVoiceOffThisBar(voices) {
13074
13062
  for (var i = 0; i < voices.length; i++) {
13075
13063
  var voice = voices[i];
@@ -13395,6 +13383,14 @@ ChordTrack.prototype.interpretChord = function (name) {
13395
13383
  }
13396
13384
  bass += chordTranspose;
13397
13385
 
13386
+ // MAE 31 Aug 2024 - For visual transpose backup range issue
13387
+ // If transposed below A or above G, bring it back in the normal backup range
13388
+ if (bass < 33) {
13389
+ bass += 12;
13390
+ } else if (bass > 44) {
13391
+ bass -= 12;
13392
+ }
13393
+
13398
13394
  // MAE 17 Jun 2024 - Supporting octave shifted bass and chords
13399
13395
  var unshiftedBass = bass;
13400
13396
  bass += this.bassOctaveShift * 12;
@@ -13533,7 +13529,6 @@ ChordTrack.prototype.resolveChords = function (startTime, endTime) {
13533
13529
  if (newBass) newBass = false;else isBoom = false; // only the first note in a chord is a bass note. This handles the case where bass and chord are played at the same time.
13534
13530
  }
13535
13531
  }
13536
-
13537
13532
  return;
13538
13533
  };
13539
13534
  ChordTrack.prototype.processChord = function (elem) {
@@ -14589,7 +14584,6 @@ function CreateSynth() {
14589
14584
  self.directSource[trackNum].buffer = audioBuffer; // tell the source which sound to play
14590
14585
  self.directSource[trackNum].connect(activeAudioContext().destination); // connect the source to the context's destination (the speakers)
14591
14586
  });
14592
-
14593
14587
  self.directSource.forEach(function (source) {
14594
14588
  source.start(0, seconds);
14595
14589
  });
@@ -16775,7 +16769,6 @@ function convertToNumber(plugin, pitches, graceNotes) {
16775
16769
  plugin.setError(tabPos.error);
16776
16770
  return tabPos; // give up on error here
16777
16771
  }
16778
-
16779
16772
  if (tabPos.graces && tabPos.notes) {
16780
16773
  // add graces to last note in notes
16781
16774
  var posNote = tabPos.notes.length - 1;
@@ -16973,7 +16966,6 @@ function getLyricHeight(voice) {
16973
16966
  }
16974
16967
  return maxLyricHeight; // add spacing
16975
16968
  }
16976
-
16977
16969
  function buildTabName(plugin, renderer, dest) {
16978
16970
  var stringSemantics = plugin.semantics;
16979
16971
  var textSize = renderer.controller.getTextSize;
@@ -17052,7 +17044,6 @@ function getNextTabPos(tabIndex, staffGroup) {
17052
17044
  if (!staffGroup[startIndex].isTabStaff) {
17053
17045
  nbVoices = staffGroup[startIndex].voices.length; // get number of staff voices
17054
17046
  }
17055
-
17056
17047
  if (staffGroup[startIndex].isTabStaff) {
17057
17048
  handledVoices++;
17058
17049
  if (islastTabInStaff(startIndex, staffGroup)) {
@@ -17165,7 +17156,6 @@ function tabRenderer(plugin, renderer, line, staffIndex) {
17165
17156
  }
17166
17157
  linkStaffAndTabs(staffGroup.staffs); // crossreference tabs and staff
17167
17158
  }
17168
-
17169
17159
  module.exports = tabRenderer;
17170
17160
 
17171
17161
  /***/ }),
@@ -17385,7 +17375,6 @@ AbstractEngraver.prototype.createABCStaff = function (staffgroup, abcstaff, temp
17385
17375
  } else {
17386
17376
  voice.duplicate = true; // bar lines and other duplicate info need not be created
17387
17377
  }
17388
-
17389
17378
  if (abcstaff.title && abcstaff.title[v]) {
17390
17379
  voice.header = abcstaff.title[v].replace(/\\n/g, "\n");
17391
17380
  voice.headerPosition = 6 + staffgroup.getTextSize.baselineToCenter(voice.header, "voicefont", 'staff-extra voice-name', v, abcstaff.voices.length) / spacing.STEP;
@@ -17399,13 +17388,11 @@ AbstractEngraver.prototype.createABCStaff = function (staffgroup, abcstaff, temp
17399
17388
  voice.addChild(clef);
17400
17389
  this.startlimitelem = clef; // limit ties here
17401
17390
  }
17402
-
17403
17391
  var keySig = createKeySignature(abcstaff.key, this.tuneNumber);
17404
17392
  if (keySig) {
17405
17393
  voice.addChild(keySig);
17406
17394
  this.startlimitelem = keySig; // limit ties here
17407
17395
  }
17408
-
17409
17396
  if (abcstaff.meter) {
17410
17397
  if (abcstaff.meter.type === 'specified') {
17411
17398
  this.measureLength = abcstaff.meter.value[0].num / abcstaff.meter.value[0].den;
@@ -17414,7 +17401,6 @@ AbstractEngraver.prototype.createABCStaff = function (staffgroup, abcstaff, temp
17414
17401
  voice.addChild(ts);
17415
17402
  this.startlimitelem = ts; // limit ties here
17416
17403
  }
17417
-
17418
17404
  if (voice.duplicate) voice.children = []; // we shouldn't reprint the above if we're reusing the same staff. We just created them to get the right spacing.
17419
17405
  var staffLines = abcstaff.clef.stafflines || abcstaff.clef.stafflines === 0 ? abcstaff.clef.stafflines : 5;
17420
17406
  staffgroup.addVoice(voice, s, staffLines);
@@ -17578,7 +17564,6 @@ AbstractEngraver.prototype.createABCElement = function (isFirstStaff, isSingleLi
17578
17564
  elemset[0] = absKey;
17579
17565
  this.startlimitelem = elemset[0]; // limit ties here
17580
17566
  }
17581
-
17582
17567
  if (voice.duplicate && elemset.length > 0) elemset[0].invisible = true;
17583
17568
  break;
17584
17569
  case "stem":
@@ -17712,7 +17697,6 @@ AbstractEngraver.prototype.addGraceNotes = function (elem, voice, abselem, noteh
17712
17697
  if (hint) gracebeam.setHint();
17713
17698
  gracebeam.mainNote = abselem; // this gives us a reference back to the note this is attached to so that the stems can be attached somewhere.
17714
17699
  }
17715
-
17716
17700
  var i;
17717
17701
  var graceoffsets = [];
17718
17702
  for (i = elem.gracenotes.length - 1; i >= 0; i--) {
@@ -17812,7 +17796,6 @@ function addRestToAbsElement(abselem, elem, duration, dot, isMultiVoice, stemdir
17812
17796
  if (duration < 0.5) restpitch = 7;else if (duration < 1) restpitch = 7; // half rest
17813
17797
  else restpitch = 5; // whole rest
17814
17798
  }
17815
-
17816
17799
  switch (elem.rest.type) {
17817
17800
  case "whole":
17818
17801
  c = chartable.rest[0];
@@ -17951,7 +17934,6 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
17951
17934
  elem.pitches[p].highestVert = elem.pitches[pp - 1].verticalPos;
17952
17935
  if (getDuration(elem) < 1 && (stemdir === "up" || dir === "up")) elem.pitches[p].highestVert += 6; // If the stem is up, then compensate for the length of the stem
17953
17936
  }
17954
-
17955
17937
  if (elem.startSlur) {
17956
17938
  if (!elem.pitches[p].startSlur) elem.pitches[p].startSlur = []; //TODO possibly redundant, provided array is not optional
17957
17939
  for (i = 0; i < elem.startSlur.length; i++) {
@@ -18121,7 +18103,6 @@ AbstractEngraver.prototype.createNote = function (elem, nostem, isSingleLineStaf
18121
18103
  flatBeams: this.flatBeams
18122
18104
  }); // above is opposite from case of slurs
18123
18105
  }
18124
-
18125
18106
  if (elem.endTriplet && this.triplet) {
18126
18107
  this.triplet.setCloseAnchor(notehead);
18127
18108
  }
@@ -18255,7 +18236,6 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
18255
18236
  abselem.addRight(new RelativeElement("dots.dot", dx, 1, 5));
18256
18237
  dx += 6; //2 hardcoded, twice;
18257
18238
  }
18258
-
18259
18239
  if (firstthin) {
18260
18240
  anchor = new RelativeElement(null, dx, 1, 2, {
18261
18241
  "type": "bar",
@@ -18304,7 +18284,6 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
18304
18284
  });
18305
18285
  abselem.addRight(anchor); // 3 is hardcoded
18306
18286
  }
18307
-
18308
18287
  if (seconddots) {
18309
18288
  dx += 3; //3 hardcoded;
18310
18289
  abselem.addRight(new RelativeElement("dots.dot", dx, 1, 7));
@@ -18638,7 +18617,6 @@ var createClef = function createClef(elem, tuneNumber) {
18638
18617
  //abselem.top += 2;
18639
18618
  }
18640
18619
  }
18641
-
18642
18620
  return abselem;
18643
18621
  };
18644
18622
  function clefOffsets(clef) {
@@ -18830,7 +18808,6 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
18830
18808
  }));
18831
18809
  extraLeft = glyphs.getSymbolWidth(symb) / 2; // TODO-PER: We need a little extra width if there is an accidental, but I'm not sure why it isn't the full width of the accidental.
18832
18810
  }
18833
-
18834
18811
  return {
18835
18812
  notehead: notehead,
18836
18813
  accidentalshiftx: accidentalshiftx,
@@ -19621,7 +19598,6 @@ BeamElem.prototype.setStemDirection = function () {
19621
19598
  var middleLine = 6; // hardcoded 6 is B
19622
19599
  this.stemsUp = this.average < middleLine; // true is up, false is down;
19623
19600
  }
19624
-
19625
19601
  delete this.count;
19626
19602
  this.total = 0;
19627
19603
  };
@@ -19635,7 +19611,6 @@ BeamElem.prototype.calcDir = function () {
19635
19611
  var middleLine = 6; // hardcoded 6 is B
19636
19612
  this.stemsUp = this.average < middleLine; // true is up, false is down;
19637
19613
  }
19638
-
19639
19614
  var dir = this.stemsUp ? 'up' : 'down';
19640
19615
  for (var i = 0; i < this.elems.length; i++) {
19641
19616
  for (var j = 0; j < this.elems[i].heads.length; j++) {
@@ -19825,7 +19800,6 @@ BraceElem.prototype.continuing = function (voice) {
19825
19800
  BraceElem.prototype.getWidth = function () {
19826
19801
  return 10; // TODO-PER: right now the drawing function doesn't vary the width at all. If it does in the future then this will change.
19827
19802
  };
19828
-
19829
19803
  BraceElem.prototype.isStartVoice = function (voice) {
19830
19804
  if (this.startVoice && this.startVoice.staff && this.startVoice.staff.voices.length > 0 && this.startVoice.staff.voices[0] === voice) return true;
19831
19805
  return false;
@@ -19850,7 +19824,6 @@ var CrescendoElem = function CrescendoElem(anchor1, anchor2, dir, positioning) {
19850
19824
  if (positioning === 'above') this.dynamicHeightAbove = 6;else this.dynamicHeightBelow = 6;
19851
19825
  this.pitch = undefined; // This will be set later
19852
19826
  };
19853
-
19854
19827
  module.exports = CrescendoElem;
19855
19828
 
19856
19829
  /***/ }),
@@ -19870,7 +19843,6 @@ var DynamicDecoration = function DynamicDecoration(anchor, dec, position) {
19870
19843
  if (position === 'below') this.volumeHeightBelow = 6;else this.volumeHeightAbove = 6;
19871
19844
  this.pitch = undefined; // This will be set later
19872
19845
  };
19873
-
19874
19846
  module.exports = DynamicDecoration;
19875
19847
 
19876
19848
  /***/ }),
@@ -19891,7 +19863,6 @@ var EndingElem = function EndingElem(text, anchor1, anchor2) {
19891
19863
  this.endingHeightAbove = 5;
19892
19864
  this.pitch = undefined; // This will be set later
19893
19865
  };
19894
-
19895
19866
  module.exports = EndingElem;
19896
19867
 
19897
19868
  /***/ }),
@@ -19997,7 +19968,6 @@ var GlissandoElem = function GlissandoElem(anchor1, anchor2) {
19997
19968
  this.anchor1 = anchor1; // must have a .x and a .parent property or be null (means starts at the "beginning" of the line - after keysig)
19998
19969
  this.anchor2 = anchor2; // must have a .x property or be null (means ends at the end of the line)
19999
19970
  };
20000
-
20001
19971
  module.exports = GlissandoElem;
20002
19972
 
20003
19973
  /***/ }),
@@ -20532,14 +20502,12 @@ TieElem.prototype.calcX = function (lineStartX, lineEndX) {
20532
20502
  if (this.anchor2) this.startX = this.anchor2.x - 20; // There is no element and no repeat mark: make a small arc
20533
20503
  else this.startX = lineStartX; // Don't have any guidance, so extend to beginning of line
20534
20504
  }
20535
-
20536
20505
  if (!this.anchor1 && this.dotted) this.startX -= 3; // The arc needs to be long enough to tell that it is dotted.
20537
20506
 
20538
20507
  if (this.anchor2) this.endX = this.anchor2.x; // The normal case where there is a starting element to attach to.
20539
20508
  else if (this.endLimitX) this.endX = this.endLimitX.x; // if there is no start element, but there is a repeat mark before the start of the line.
20540
20509
  else this.endX = lineEndX; // There is no element and no repeat mark: extend to the beginning of the line.
20541
20510
  };
20542
-
20543
20511
  TieElem.prototype.calcTieY = function () {
20544
20512
  // If the tie comes from another line, then one or both anchors will be missing.
20545
20513
  if (this.anchor1) this.startY = this.anchor1.pitch;else if (this.anchor2) this.startY = this.anchor2.pitch;else this.startY = this.above ? 14 : 0;
@@ -20602,6 +20570,30 @@ TieElem.prototype.avoidCollisionAbove = function () {
20602
20570
  if (maxInnerHeight > this.startY && maxInnerHeight > this.endY) this.startY = this.endY = maxInnerHeight - 1;
20603
20571
  }
20604
20572
  };
20573
+ TieElem.prototype.getYBounds = function () {
20574
+ var lineStartX = 10; // TODO-PER: I'm not sure where to get this number from but it probably doesn't matter much
20575
+ var lineEndX = 1000; // TODO-PER: I'm not sure where to get this number from but it probably doesn't matter much
20576
+ if (this.isTie) {
20577
+ this.calcTieDirection();
20578
+ this.calcX(lineStartX, lineEndX);
20579
+ this.calcTieY();
20580
+ } else {
20581
+ this.calcSlurDirection();
20582
+ this.calcX(lineStartX, lineEndX);
20583
+ this.calcSlurY();
20584
+ }
20585
+ var top;
20586
+ var bottom;
20587
+ // TODO-PER: It's hard to tell how far the arc is, so I'm just using 3 as the max
20588
+ if (this.above) {
20589
+ bottom = Math.min(this.startY, this.endY);
20590
+ top = bottom + 3;
20591
+ } else {
20592
+ top = Math.min(this.startY, this.endY);
20593
+ bottom = top - 3;
20594
+ }
20595
+ return [top, bottom];
20596
+ };
20605
20597
  module.exports = TieElem;
20606
20598
 
20607
20599
  /***/ }),
@@ -20652,7 +20644,6 @@ function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, padd
20652
20644
 
20653
20645
  // TopText.prototype.addTextIf = function (marginLeft, text, font, klass, marginTop, marginBottom, anchor, getTextSize, absElemType, noMove) {
20654
20646
  }
20655
-
20656
20647
  if (isPrint) this.rows.push({
20657
20648
  move: spacing.top
20658
20649
  });
@@ -21724,7 +21715,6 @@ function straightPath(renderer, xLeft, yTop, yBottom, type) {
21724
21715
  // right point
21725
21716
  -wCurve * 0.1, -hCurve * 0.3, -wCurve, -hCurve - spacing.STEP // left bottom
21726
21717
  );
21727
-
21728
21718
  return renderer.paper.path({
21729
21719
  path: pathString,
21730
21720
  stroke: renderer.foregroundColor,
@@ -23003,7 +22993,6 @@ function drawStaffGroup(renderer, params, selectables, lineNumber) {
23003
22993
  // renderer.moveY(spacing.STEP, -staff.bottom);
23004
22994
  }
23005
22995
  }
23006
-
23007
22996
  renderer.controller.classes.newMeasure();
23008
22997
 
23009
22998
  // connect all the staves together with a vertical line
@@ -23225,7 +23214,6 @@ function drawTempo(renderer, params) {
23225
23214
  // });
23226
23215
  //return [tempoGroup];
23227
23216
  }
23228
-
23229
23217
  module.exports = drawTempo;
23230
23218
 
23231
23219
  /***/ }),
@@ -23562,7 +23550,6 @@ function drawVoice(renderer, params, bartop, selectables, staffPos) {
23562
23550
  renderer.controller.classes.incrMeasure();
23563
23551
  } else drawBeam(renderer, beam, selectables); // beams must be drawn first for proper printing of triplets, slurs and ties.
23564
23552
  }
23565
-
23566
23553
  renderer.controller.classes.startMeasure();
23567
23554
  for (i = 0; i < params.otherchildren.length; i++) {
23568
23555
  child = params.otherchildren[i];
@@ -23671,7 +23658,6 @@ var EngraverController = function EngraverController(paper, params) {
23671
23658
  this.staffwidthScreen = 740; // TODO-PER: Not sure where this number comes from, but this is how it's always been.
23672
23659
  this.staffwidthPrint = 680; // The number of pixels in 8.5", after 1cm of margin has been removed.
23673
23660
  }
23674
-
23675
23661
  this.listeners = [];
23676
23662
  if (params.clickListener) this.addSelectListener(params.clickListener);
23677
23663
  this.renderer = new Renderer(paper);
@@ -24581,7 +24567,6 @@ function getMousePosition(self, ev) {
24581
24567
  clickedOn = findElementByCoord(self, x, y);
24582
24568
  //console.log("clicked near", clickedOn, x, y, printEl(ev.target));
24583
24569
  }
24584
-
24585
24570
  return {
24586
24571
  x: x,
24587
24572
  y: y,
@@ -24819,7 +24804,6 @@ function minStem(element, stemsUp, referencePitch, minStemHeight) {
24819
24804
  var elem = element.children[i];
24820
24805
  if (stemsUp && elem.top !== undefined && elem.c === "flags.ugrace") minStemHeight = Math.max(minStemHeight, elem.top - referencePitch);else if (!stemsUp && elem.bottom !== undefined && elem.c === "flags.ugrace") minStemHeight = Math.max(minStemHeight, referencePitch - elem.bottom + 7); // The extra 7 is because we are measuring the slash from the top.
24821
24806
  }
24822
-
24823
24807
  return minStemHeight;
24824
24808
  }
24825
24809
  function calcSlant(leftAveragePitch, rightAveragePitch, numStems, isFlat) {
@@ -25224,7 +25208,6 @@ function calcHorizontalSpacing(isLastLine, stretchLast, targetWidth, lineWidth,
25224
25208
  if (!stretch) return null; // don't stretch last line too much
25225
25209
  }
25226
25210
  }
25227
-
25228
25211
  if (Math.abs(targetWidth - lineWidth) < 2) return null; // if we are already near the target width, we're done.
25229
25212
  var relSpace = spacingUnits * spacing;
25230
25213
  var constSpace = lineWidth - relSpace;
@@ -25289,7 +25272,6 @@ var setUpperAndLowerElements = function setUpperAndLowerElements(renderer, staff
25289
25272
  staff.originalTop = staff.top; // This is just being stored for debugging purposes.
25290
25273
  staff.originalBottom = staff.bottom; // This is just being stored for debugging purposes.
25291
25274
  }
25292
-
25293
25275
  incTop(staff, positionY, 'lyricHeightAbove');
25294
25276
  incTop(staff, positionY, 'chordHeightAbove', staff.specialY.chordLines.above);
25295
25277
  if (staff.specialY.endingHeightAbove) {
@@ -25352,7 +25334,6 @@ var setUpperAndLowerElements = function setUpperAndLowerElements(renderer, staff
25352
25334
  }
25353
25335
  //console.log("Staff Height: ",heightInPitches,this.height);
25354
25336
  };
25355
-
25356
25337
  var margin = 1;
25357
25338
  function incTop(staff, positionY, item, count) {
25358
25339
  if (staff.specialY[item]) {
@@ -25381,6 +25362,14 @@ function setUpperAndLowerVoiceElements(positionY, voice, spacing) {
25381
25362
  case 'EndingElem':
25382
25363
  setUpperAndLowerEndingElements(positionY, abselem);
25383
25364
  break;
25365
+ case 'TieElem':
25366
+ // If a tie element is the highest or lowest thing then space might need to make room for it.
25367
+ var yBounds = abselem.getYBounds();
25368
+ voice.staff.top = Math.max(voice.staff.top, yBounds[0]);
25369
+ voice.staff.top = Math.max(voice.staff.top, yBounds[1]);
25370
+ voice.staff.bottom = Math.min(voice.staff.bottom, yBounds[0]);
25371
+ voice.staff.bottom = Math.min(voice.staff.bottom, yBounds[1]);
25372
+ break;
25384
25373
  }
25385
25374
  }
25386
25375
  }
@@ -25609,7 +25598,6 @@ function finished(voices) {
25609
25598
  function getDurationIndex(element) {
25610
25599
  return element.durationindex - (element.children[element.i] && element.children[element.i].duration > 0 ? 0 : 0.0000005); // if the ith element doesn't have a duration (is not a note), its duration index is fractionally before. This enables CLEF KEYSIG TIMESIG PART, etc. to be laid out before we get to the first note of other voices
25611
25600
  }
25612
-
25613
25601
  function isSameStaff(voice1, voice2) {
25614
25602
  if (!voice1 || !voice1.staff || !voice1.staff.voices || voice1.staff.voices.length === 0) return false;
25615
25603
  if (!voice2 || !voice2.staff || !voice2.staff.voices || voice2.staff.voices.length === 0) return false;
@@ -25707,7 +25695,6 @@ VoiceElement.beginLayout = function (startx, voice) {
25707
25695
  voice.nextx = startx; // x position where the next element of this voice should be placed assuming no other voices and no fixed width constraints
25708
25696
  voice.spacingduration = 0; // duration left to be laid out in current iteration (omitting additional spacing due to other aspects, such as bars, dots, sharps and flats)
25709
25697
  };
25710
-
25711
25698
  VoiceElement.layoutEnded = function (voice) {
25712
25699
  return voice.i >= voice.children.length;
25713
25700
  };
@@ -25773,7 +25760,6 @@ VoiceElement.layoutOneItem = function (x, spacing, voice, minPadding, firstVoice
25773
25760
 
25774
25761
  return x; // where we end up having placed the child
25775
25762
  };
25776
-
25777
25763
  VoiceElement.shiftRight = function (dx, voice) {
25778
25764
  var child = voice.children[voice.i];
25779
25765
  if (!child) return;
@@ -25936,7 +25922,6 @@ function setLane(absElems, numLanesAbove, numLanesBelow) {
25936
25922
  }
25937
25923
  }
25938
25924
  }
25939
-
25940
25925
  function yAtNote(element, beam) {
25941
25926
  beam = beam.beams[0];
25942
25927
  return getBarYAt(beam.startX, beam.startY, beam.endX, beam.endY, element.x);
@@ -26095,7 +26080,6 @@ Renderer.prototype.initVerticalSpace = function () {
26095
26080
  <float> range is 0.0 to 1.0.
26096
26081
  */
26097
26082
  };
26098
-
26099
26083
  Renderer.prototype.setVerticalSpace = function (formatting) {
26100
26084
  // conversion from pts to px 4/3
26101
26085
  if (formatting.staffsep !== undefined) this.spacing.staffSeparation = formatting.staffsep * 4 / 3;
@@ -26217,7 +26201,6 @@ Svg.prototype.insertStyles = function (styles) {
26217
26201
  this.svg.insertBefore(el, this.svg.firstChild); // prepend is not available on older browsers.
26218
26202
  // this.svg.prepend(el);
26219
26203
  };
26220
-
26221
26204
  Svg.prototype.setParentStyles = function (attr) {
26222
26205
  // This is needed to get the size right when there is scaling involved.
26223
26206
  for (var key in attr) {
@@ -26360,7 +26343,6 @@ Svg.prototype.guessWidth = function (text, attr) {
26360
26343
  height: attr['font-size'] + 2
26361
26344
  }; // Just a wild guess.
26362
26345
  }
26363
-
26364
26346
  svg.removeChild(el);
26365
26347
  return size;
26366
26348
  };
@@ -26489,7 +26471,7 @@ module.exports = Svg;
26489
26471
  \********************/
26490
26472
  /***/ (function(module) {
26491
26473
 
26492
- var version = '6.4.2';
26474
+ var version = '6.4.3';
26493
26475
  module.exports = version;
26494
26476
 
26495
26477
  /***/ })