abcjs 6.5.0 → 6.5.2

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/src/str/output.js CHANGED
@@ -277,6 +277,7 @@ var strTranspose;
277
277
  var regNote = /([_^=]*[A-Ga-g][,']*)(\d*\/*\d*)([\>\<\-\)\.\s\\]*)/
278
278
  var regOptionalNote = /([_^=]*[A-Ga-g][,']*)?(\d*\/*\d*)?([\>\<\-\)]*)?/
279
279
  var regSpace = /(\s*)$/
280
+ var regOptionalSpace = /(\s*)/
280
281
 
281
282
  // This the relationship of the note to the tonic and an octave. So what is returned is a distance in steps from the tonic and the amount of adjustment from
282
283
  // a normal scale. That is - in the key of D an F# is two steps from the tonic and no adjustment. A G# is three steps from the tonic and one half-step higher.
@@ -298,48 +299,60 @@ var strTranspose;
298
299
  }
299
300
 
300
301
  function replaceNote(abc, start, end, newPitch, index) {
301
- // There may be more than just the note between the start and end - there could be spaces, there could be a chord symbol, there could be a decoration.
302
- // This could also be a part of a chord. If so, then the particular note needs to be teased out.
303
- var note = abc.substring(start, end)
304
- var match = note.match(new RegExp(regNote.source + regSpace.source), '')
302
+ var note = abc.substring(start, end);
303
+ // Try single note first
304
+ var match = note.match(new RegExp(regNote.source + regSpace.source));
305
305
  if (match) {
306
- // This will match a single note
307
- var noteLen = match[1].length
308
- var trailingLen = match[2].length + match[3].length + match[4].length
309
- var leadingLen = end - start - noteLen - trailingLen
310
- start += leadingLen
311
- end -= trailingLen
306
+ var noteLen = match[1].length;
307
+ var trailingLen = match[2].length + match[3].length + match[4].length;
308
+ var leadingLen = end - start - noteLen - trailingLen;
309
+ start += leadingLen;
310
+ end -= trailingLen;
312
311
  } else {
313
- // I don't know how to capture more than one note, so I'm separating them. There is a limit of the number of notes in a chord depending on the repeats I have here, but it is unlikely to happen in real music.
314
- var regPreBracket = /([^\[]*)/
315
- var regOpenBracket = /\[/
316
- var regCloseBracket = /\-?](\d*\/*\d*)?([\>\<\-\)]*)/
317
- match = note.match(new RegExp(regPreBracket.source + regOpenBracket.source + regOptionalNote.source +
318
- regOptionalNote.source + regOptionalNote.source + regOptionalNote.source +
319
- regOptionalNote.source + regOptionalNote.source + regOptionalNote.source +
320
- regOptionalNote.source + regCloseBracket.source + regSpace.source))
321
-
312
+ // Match chord
313
+ var regPreBracket = /([^\[]*)/;
314
+ var regOpenBracket = /\[/;
315
+ var regCloseBracket = /\-?](\d*\/*\d*)?([\>\<\-\)]*)/;
316
+ var regChord = new RegExp(
317
+ regPreBracket.source +
318
+ regOpenBracket.source +
319
+ "(?:" + regOptionalNote.source + "\\s*){1,8}" +
320
+ regCloseBracket.source +
321
+ regSpace.source
322
+ );
323
+ match = note.match(regChord);
322
324
  if (match) {
323
- // This will match a chord
324
- // Get the number of chars used by the previous notes in this chord
325
- var count = 1 + match[1].length // one character for the open bracket
326
- for (var i = 0; i < index; i++) { // index is the iteration through the chord. This function gets called for each one.
327
- if (match[i * 3 + 2])
328
- count += match[i * 3 + 2].length
329
- if (match[i * 3 + 3])
330
- count += match[i * 3 + 3].length
331
- if (match[i * 3 + 4])
332
- count += match[i * 3 + 4].length
325
+ var beforeChordLen = match[1].length + 1; // text before + '['
326
+ var chordBody = note.slice(match[1].length + 1, note.lastIndexOf("]"));
327
+ // Collect notes inside chord
328
+ var chordNotes = [];
329
+ var regNoteWithSpace = new RegExp(regOptionalNote.source + "\\s*", "g");
330
+ for (const m of chordBody.matchAll(regNoteWithSpace)) {
331
+ let noteText = m[0].trim();
332
+ if (noteText !== "") {
333
+ chordNotes.push({ text: noteText, index: m.index });
334
+ }
333
335
  }
334
- start += count
335
- var endLen = match[index * 3 + 2] ? match[index * 3 + 2].length : 0
336
- // endLen += match[index * 3 + 3] ? match[index * 3 + 3].length : 0
337
- // endLen += match[index * 3 + 4] ? match[index * 3 + 4].length : 0
338
-
339
- end = start + endLen
336
+ if (index >= chordNotes.length) {
337
+ throw new Error("Chord index out of range for chord: " + note);
338
+ }
339
+ var chosen = chordNotes[index];
340
+ // Preserve duration and tie
341
+ let mDurTie = chosen.text.match(/^(.+?)(\d+\/?\d*)?(-)?$/);
342
+ let pitchPart = mDurTie ? mDurTie[1] : chosen.text;
343
+ let durationPart = mDurTie && mDurTie[2] ? mDurTie[2] : "";
344
+ let tiePart = mDurTie && mDurTie[3] ? mDurTie[3] : "";
345
+ // Replace note keeping duration and tie
346
+ newPitch = newPitch + durationPart + tiePart;
347
+ start += beforeChordLen + chosen.index;
348
+ end = start + chosen.text.length;
340
349
  }
341
350
  }
342
- return { start: start, end: end, note: newPitch }
351
+ return {
352
+ start: start,
353
+ end: end,
354
+ note: newPitch
355
+ };
343
356
  }
344
357
 
345
358
  function replaceGrace(abc, start, end, newGrace, index) {
@@ -484,7 +484,8 @@ var parseCommon = require("../parse/abc_common");
484
484
  if(Array.isArray(elem.decoration)){
485
485
  volumesPerNotePitch = [];
486
486
  elem.decoration.forEach(d=>{
487
- volumesPerNotePitch.push(volumes[d].slice(0));
487
+ if (d in volumes)
488
+ volumesPerNotePitch.push(volumes[d].slice(0));
488
489
  });
489
490
  }
490
491
  voices[voiceNumber].push({ el_type: 'beat', beats: currentVolume.slice(0), volumesPerNotePitch: volumesPerNotePitch, });
package/types/index.d.ts CHANGED
@@ -76,7 +76,7 @@ declare module 'abcjs' {
76
76
  //
77
77
  // Basic types
78
78
  //
79
- export type Selector = string | HTMLElement
79
+ export type Selector = string | Element
80
80
 
81
81
  type NumberFunction = () => number;
82
82
 
@@ -321,7 +321,7 @@ declare module 'abcjs' {
321
321
  synthControl?: SynthObjectController;
322
322
  el: Selector;
323
323
  cursorControl?: CursorControl;
324
- options?: SynthOptions;
324
+ options?: SynthOptions & SynthVisualOptions;
325
325
  }
326
326
 
327
327
  export interface EditorOptions {
@@ -331,6 +331,7 @@ declare module 'abcjs' {
331
331
  warnings_id?: Selector;
332
332
  onchange?: OnChange;
333
333
  selectionChangeCallback?: SelectionChangeCallback;
334
+ redrawCallback?: RedrawCallback;
334
335
  abcjsParams?: AbcVisualParams;
335
336
  indicate_changed?: boolean;
336
337
  synth?: EditorSynth;
@@ -1144,6 +1145,8 @@ declare module 'abcjs' {
1144
1145
 
1145
1146
  export type SelectionChangeCallback = (startChar: number, endChar: number) => void;
1146
1147
 
1148
+ export type RedrawCallback = (isBefore: boolean) => void;
1149
+
1147
1150
  // Audio
1148
1151
  export interface CursorControl {
1149
1152
  beatSubDivision?: number
@@ -1185,8 +1188,12 @@ declare module 'abcjs' {
1185
1188
  //
1186
1189
  // Editor
1187
1190
  //
1191
+ export class EditArea {
1192
+ constructor(target: Selector);
1193
+ }
1194
+
1188
1195
  export class Editor {
1189
- constructor(target: Selector, options: EditorOptions);
1196
+ constructor(target: Selector | EditArea, options: EditorOptions);
1190
1197
  paramChanged(options: AbcVisualParams): void;
1191
1198
  synthParamChanged(options: SynthOptions): void;
1192
1199
  setNotDirty(): void;
@@ -1195,6 +1202,7 @@ declare module 'abcjs' {
1195
1202
  millisecondsPerMeasure(): number;
1196
1203
  pauseMidi(shouldPause: boolean): void;
1197
1204
  fireChanged():void;
1205
+ getTunes():TuneObjectArray;
1198
1206
  }
1199
1207
 
1200
1208
  //
package/version.js CHANGED
@@ -1,3 +1,3 @@
1
- var version = '6.5.0';
1
+ var version = '6.5.2';
2
2
 
3
3
  module.exports = version;