abcjs 6.2.1 → 6.2.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.
- package/README.md +3 -0
- package/RELEASE.md +54 -0
- package/abc2xml_239/abc2xml.html +769 -0
- package/abc2xml_239/abc2xml.py +2248 -0
- package/abc2xml_239/abc2xml_changelog.html +124 -0
- package/abc2xml_239/lazy-river.abc +26 -0
- package/abc2xml_239/lazy-river.xml +3698 -0
- package/abc2xml_239/mean-to-me.abc +22 -0
- package/abc2xml_239/mean-to-me.xml +2954 -0
- package/abc2xml_239/pyparsing.py +3672 -0
- package/abc2xml_239/pyparsing.pyc +0 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +205 -91
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/package.json +1 -1
- package/src/api/abc_tablatures.js +5 -0
- package/src/api/abc_tunebook_svg.js +5 -3
- package/src/parse/abc_parse_music.js +18 -53
- package/src/parse/abc_parse_settings.js +165 -0
- package/src/synth/create-synth.js +4 -0
- package/src/synth/place-note.js +6 -0
- package/src/synth/play-event.js +7 -5
- package/src/tablatures/tab-absolute-elements.js +3 -2
- package/src/tablatures/tab-renderer.js +3 -1
- package/src/test/abc_parser_lint.js +12 -12
- package/src/write/creation/abstract-engraver.js +6 -0
- package/src/write/creation/decoration.js +2 -0
- package/src/write/creation/glyphs.js +1 -1
- package/src/write/draw/glissando.js +1 -0
- package/src/write/draw/print-line.js +16 -7
- package/src/write/draw/print-stem.js +16 -8
- package/src/write/draw/set-paper-size.js +1 -1
- package/src/write/draw/tie.js +9 -1
- package/src/write/engraver-controller.js +12 -4
- package/src/write/interactive/selection.js +6 -0
- package/src/write/layout/layout.js +33 -3
- package/src/write/svg.js +10 -0
- package/types/index.d.ts +29 -21
- package/version.js +1 -1
package/dist/abcjs-basic.js
CHANGED
|
@@ -211,6 +211,8 @@ var GuitarTablature = __webpack_require__(/*! ../tablatures/instruments/guitar/t
|
|
|
211
211
|
// Existing tab classes
|
|
212
212
|
var pluginTab = {
|
|
213
213
|
'violin': 'ViolinTab',
|
|
214
|
+
'fiddle': 'ViolinTab',
|
|
215
|
+
'mandolin': 'ViolinTab',
|
|
214
216
|
'guitar': 'GuitarTab'
|
|
215
217
|
};
|
|
216
218
|
var abcTablatures = {
|
|
@@ -274,6 +276,9 @@ var abcTablatures = {
|
|
|
274
276
|
// plugin.init(tune, tuneNumber, args, ii);
|
|
275
277
|
returned.push(pluginInstance);
|
|
276
278
|
nbPlugins++;
|
|
279
|
+
} else if (instrument === '') {
|
|
280
|
+
// create a placeholder - there is no tab for this staff
|
|
281
|
+
returned.push(null);
|
|
277
282
|
} else {
|
|
278
283
|
// unknown tab plugin
|
|
279
284
|
//this.emit_error('Undefined tablature plugin: ' + tabName)
|
|
@@ -995,11 +1000,11 @@ var renderAbc = function renderAbc(output, abc, parserParams, engraverParams, re
|
|
|
995
1000
|
div.setAttribute("style", "visibility: hidden;");
|
|
996
1001
|
document.body.appendChild(div);
|
|
997
1002
|
}
|
|
998
|
-
if (params.afterParsing) params.afterParsing(tune, tuneNumber, abcString);
|
|
999
1003
|
if (!removeDiv && params.wrap && params.staffwidth) {
|
|
1000
1004
|
tune = doLineWrapping(div, tune, tuneNumber, abcString, params);
|
|
1001
1005
|
return tune;
|
|
1002
1006
|
}
|
|
1007
|
+
if (params.afterParsing) params.afterParsing(tune, tuneNumber, abcString);
|
|
1003
1008
|
renderOne(div, tune, params, tuneNumber, 0);
|
|
1004
1009
|
if (removeDiv) div.parentNode.removeChild(div);
|
|
1005
1010
|
return null;
|
|
@@ -1017,6 +1022,7 @@ function doLineWrapping(div, tune, tuneNumber, abcString, params) {
|
|
|
1017
1022
|
var warnings = abcParser.getWarnings();
|
|
1018
1023
|
if (warnings) tune.warnings = warnings;
|
|
1019
1024
|
}
|
|
1025
|
+
if (params.afterParsing) params.afterParsing(tune, tuneNumber, abcString);
|
|
1020
1026
|
renderOne(div, tune, ret.revisedParams, tuneNumber, 0);
|
|
1021
1027
|
tune.explanation = ret.explanation;
|
|
1022
1028
|
return tune;
|
|
@@ -6339,6 +6345,18 @@ var multilineVars;
|
|
|
6339
6345
|
var tune;
|
|
6340
6346
|
var tuneBuilder;
|
|
6341
6347
|
var header;
|
|
6348
|
+
var _require = __webpack_require__(/*! ./abc_parse_settings */ "./src/parse/abc_parse_settings.js"),
|
|
6349
|
+
legalAccents = _require.legalAccents,
|
|
6350
|
+
volumeDecorations = _require.volumeDecorations,
|
|
6351
|
+
dynamicDecorations = _require.dynamicDecorations,
|
|
6352
|
+
accentPseudonyms = _require.accentPseudonyms,
|
|
6353
|
+
accentDynamicPseudonyms = _require.accentDynamicPseudonyms,
|
|
6354
|
+
nonDecorations = _require.nonDecorations,
|
|
6355
|
+
durations = _require.durations,
|
|
6356
|
+
pitches = _require.pitches,
|
|
6357
|
+
rests = _require.rests,
|
|
6358
|
+
accMap = _require.accMap,
|
|
6359
|
+
tripletQ = _require.tripletQ;
|
|
6342
6360
|
var MusicParser = function MusicParser(_tokenizer, _warn, _multilineVars, _tune, _tuneBuilder, _header) {
|
|
6343
6361
|
tokenizer = _tokenizer;
|
|
6344
6362
|
warn = _warn;
|
|
@@ -6406,7 +6424,6 @@ var MusicParser = function MusicParser(_tokenizer, _warn, _multilineVars, _tune,
|
|
|
6406
6424
|
// double-quote: chord symbol
|
|
6407
6425
|
// less-than, greater-than, slash: duration
|
|
6408
6426
|
// back-tick, space, tab: space
|
|
6409
|
-
var nonDecorations = "ABCDEFGabcdefgxyzZ[]|^_{"; // use this to prescreen so we don't have to look for a decoration at every note.
|
|
6410
6427
|
|
|
6411
6428
|
var isInTie = function isInTie(multilineVars, overlayLevel, el) {
|
|
6412
6429
|
if (multilineVars.inTie[overlayLevel] === undefined) return false;
|
|
@@ -6815,7 +6832,7 @@ MusicParser.prototype.parseMusic = function (line) {
|
|
|
6815
6832
|
// Create a warning if this is not a displayable duration.
|
|
6816
6833
|
// The first item on a line is a regular note value, each item after that represents a dot placed after the previous note.
|
|
6817
6834
|
// Only durations less than a whole note are tested because whole note durations have some tricky rules.
|
|
6818
|
-
|
|
6835
|
+
|
|
6819
6836
|
if (el.duration < 1 && durations.indexOf(el.duration) === -1 && el.duration !== 0) {
|
|
6820
6837
|
if (!el.rest || el.rest.type !== 'spacer') warn("Duration not representable: " + line.substring(startI, i), line, i);
|
|
6821
6838
|
}
|
|
@@ -6963,11 +6980,6 @@ function durationOfMeasure(multilineVars) {
|
|
|
6963
6980
|
if (!meter.value || meter.value.length === 0) return 1;
|
|
6964
6981
|
return parseInt(meter.value[0].num, 10) / parseInt(meter.value[0].den, 10);
|
|
6965
6982
|
}
|
|
6966
|
-
var legalAccents = ["trill", "lowermordent", "uppermordent", "mordent", "pralltriller", "accent", "fermata", "invertedfermata", "tenuto", "0", "1", "2", "3", "4", "5", "+", "wedge", "open", "thumb", "snap", "turn", "roll", "breath", "shortphrase", "mediumphrase", "longphrase", "segno", "coda", "D.S.", "D.C.", "fine", "beambr1", "beambr2", "slide", "marcato", "upbow", "downbow", "/", "//", "///", "////", "trem1", "trem2", "trem3", "trem4", "turnx", "invertedturn", "invertedturnx", "trill(", "trill)", "arpeggio", "xstem", "mark", "umarcato", "style=normal", "style=harmonic", "style=rhythm", "style=x", "style=triangle", "D.C.alcoda", "D.C.alfine", "D.S.alcoda", "D.S.alfine", "editorial", "courtesy"];
|
|
6967
|
-
var volumeDecorations = ["p", "pp", "f", "ff", "mf", "mp", "ppp", "pppp", "fff", "ffff", "sfz"];
|
|
6968
|
-
var dynamicDecorations = ["crescendo(", "crescendo)", "diminuendo(", "diminuendo)", "glissando(", "glissando)"];
|
|
6969
|
-
var accentPseudonyms = [["<", "accent"], [">", "accent"], ["tr", "trill"], ["plus", "+"], ["emphasis", "accent"], ["^", "umarcato"], ["marcato", "umarcato"]];
|
|
6970
|
-
var accentDynamicPseudonyms = [["<(", "crescendo("], ["<)", "crescendo)"], [">(", "diminuendo("], [">)", "diminuendo)"]];
|
|
6971
6983
|
var letter_to_accent = function letter_to_accent(line, i) {
|
|
6972
6984
|
var macro = multilineVars.macros[line[i]];
|
|
6973
6985
|
if (macro !== undefined) {
|
|
@@ -7094,19 +7106,6 @@ var letter_to_bar = function letter_to_bar(line, curr_pos) {
|
|
|
7094
7106
|
if (retRep.len === 0 || retRep.token[0] === '-') return [orig_bar_len, ret.token];
|
|
7095
7107
|
return [ret.len + retRep.len, ret.token, retRep.token];
|
|
7096
7108
|
};
|
|
7097
|
-
var tripletQ = {
|
|
7098
|
-
2: 3,
|
|
7099
|
-
3: 2,
|
|
7100
|
-
4: 3,
|
|
7101
|
-
5: 2,
|
|
7102
|
-
// TODO-PER: not handling 6/8 rhythm yet
|
|
7103
|
-
6: 2,
|
|
7104
|
-
7: 2,
|
|
7105
|
-
// TODO-PER: not handling 6/8 rhythm yet
|
|
7106
|
-
8: 3,
|
|
7107
|
-
9: 2 // TODO-PER: not handling 6/8 rhythm yet
|
|
7108
|
-
};
|
|
7109
|
-
|
|
7110
7109
|
var letter_to_open_slurs_and_triplets = function letter_to_open_slurs_and_triplets(line, i) {
|
|
7111
7110
|
// consume spaces, and look for all the open parens. If there is a number after the open paren,
|
|
7112
7111
|
// that is a triplet. Otherwise that is a slur. Collect all the slurs and the first triplet.
|
|
@@ -7240,38 +7239,6 @@ var addEndBeam = function addEndBeam(el) {
|
|
|
7240
7239
|
if (el.duration !== undefined && el.duration < 0.25) el.end_beam = true;
|
|
7241
7240
|
return el;
|
|
7242
7241
|
};
|
|
7243
|
-
var pitches = {
|
|
7244
|
-
A: 5,
|
|
7245
|
-
B: 6,
|
|
7246
|
-
C: 0,
|
|
7247
|
-
D: 1,
|
|
7248
|
-
E: 2,
|
|
7249
|
-
F: 3,
|
|
7250
|
-
G: 4,
|
|
7251
|
-
a: 12,
|
|
7252
|
-
b: 13,
|
|
7253
|
-
c: 7,
|
|
7254
|
-
d: 8,
|
|
7255
|
-
e: 9,
|
|
7256
|
-
f: 10,
|
|
7257
|
-
g: 11
|
|
7258
|
-
};
|
|
7259
|
-
var rests = {
|
|
7260
|
-
x: 'invisible',
|
|
7261
|
-
X: 'invisible-multimeasure',
|
|
7262
|
-
y: 'spacer',
|
|
7263
|
-
z: 'rest',
|
|
7264
|
-
Z: 'multimeasure'
|
|
7265
|
-
};
|
|
7266
|
-
var accMap = {
|
|
7267
|
-
'dblflat': '__',
|
|
7268
|
-
'flat': '_',
|
|
7269
|
-
'natural': '=',
|
|
7270
|
-
'sharp': '^',
|
|
7271
|
-
'dblsharp': '^^',
|
|
7272
|
-
'quarterflat': '_/',
|
|
7273
|
-
'quartersharp': '^/'
|
|
7274
|
-
};
|
|
7275
7242
|
var getCoreNote = function getCoreNote(line, index, el, canHaveBrokenRhythm) {
|
|
7276
7243
|
//var el = { startChar: index };
|
|
7277
7244
|
var isComplete = function isComplete(state) {
|
|
@@ -7559,6 +7526,67 @@ module.exports = MusicParser;
|
|
|
7559
7526
|
|
|
7560
7527
|
/***/ }),
|
|
7561
7528
|
|
|
7529
|
+
/***/ "./src/parse/abc_parse_settings.js":
|
|
7530
|
+
/*!*****************************************!*\
|
|
7531
|
+
!*** ./src/parse/abc_parse_settings.js ***!
|
|
7532
|
+
\*****************************************/
|
|
7533
|
+
/***/ (function(module) {
|
|
7534
|
+
|
|
7535
|
+
module.exports.legalAccents = ['trill', 'lowermordent', 'uppermordent', 'mordent', 'pralltriller', 'accent', 'fermata', 'invertedfermata', 'tenuto', '0', '1', '2', '3', '4', '5', '+', 'wedge', 'open', 'thumb', 'snap', 'turn', 'roll', 'breath', 'shortphrase', 'mediumphrase', 'longphrase', 'segno', 'coda', 'D.S.', 'D.C.', 'fine', 'beambr1', 'beambr2', 'slide', 'marcato', 'upbow', 'downbow', '/', '//', '///', '////', 'trem1', 'trem2', 'trem3', 'trem4', 'turnx', 'invertedturn', 'invertedturnx', 'trill(', 'trill)', 'arpeggio', 'xstem', 'mark', 'umarcato', 'style=normal', 'style=harmonic', 'style=rhythm', 'style=x', 'style=triangle', 'D.C.alcoda', 'D.C.alfine', 'D.S.alcoda', 'D.S.alfine', 'editorial', 'courtesy'];
|
|
7536
|
+
module.exports.volumeDecorations = ['p', 'pp', 'f', 'ff', 'mf', 'mp', 'ppp', 'pppp', 'fff', 'ffff', 'sfz'];
|
|
7537
|
+
module.exports.dynamicDecorations = ['crescendo(', 'crescendo)', 'diminuendo(', 'diminuendo)', 'glissando(', 'glissando)', '~(', '~)'];
|
|
7538
|
+
module.exports.accentPseudonyms = [['<', 'accent'], ['>', 'accent'], ['tr', 'trill'], ['plus', '+'], ['emphasis', 'accent'], ['^', 'umarcato'], ['marcato', 'umarcato']];
|
|
7539
|
+
module.exports.accentDynamicPseudonyms = [['<(', 'crescendo('], ['<)', 'crescendo)'], ['>(', 'diminuendo('], ['>)', 'diminuendo)']];
|
|
7540
|
+
module.exports.nonDecorations = 'ABCDEFGabcdefgxyzZ[]|^_{'; // use this to prescreen so we don't have to look for a decoration at every note.
|
|
7541
|
+
|
|
7542
|
+
module.exports.durations = [0.5, 0.75, 0.875, 0.9375, 0.96875, 0.984375, 0.25, 0.375, 0.4375, 0.46875, 0.484375, 0.4921875, 0.125, 0.1875, 0.21875, 0.234375, 0.2421875, 0.24609375, 0.0625, 0.09375, 0.109375, 0.1171875, 0.12109375, 0.123046875, 0.03125, 0.046875, 0.0546875, 0.05859375, 0.060546875, 0.0615234375, 0.015625, 0.0234375, 0.02734375, 0.029296875, 0.0302734375, 0.03076171875];
|
|
7543
|
+
module.exports.pitches = {
|
|
7544
|
+
A: 5,
|
|
7545
|
+
B: 6,
|
|
7546
|
+
C: 0,
|
|
7547
|
+
D: 1,
|
|
7548
|
+
E: 2,
|
|
7549
|
+
F: 3,
|
|
7550
|
+
G: 4,
|
|
7551
|
+
a: 12,
|
|
7552
|
+
b: 13,
|
|
7553
|
+
c: 7,
|
|
7554
|
+
d: 8,
|
|
7555
|
+
e: 9,
|
|
7556
|
+
f: 10,
|
|
7557
|
+
g: 11
|
|
7558
|
+
};
|
|
7559
|
+
module.exports.rests = {
|
|
7560
|
+
x: 'invisible',
|
|
7561
|
+
X: 'invisible-multimeasure',
|
|
7562
|
+
y: 'spacer',
|
|
7563
|
+
z: 'rest',
|
|
7564
|
+
Z: 'multimeasure'
|
|
7565
|
+
};
|
|
7566
|
+
module.exports.accMap = {
|
|
7567
|
+
dblflat: '__',
|
|
7568
|
+
flat: '_',
|
|
7569
|
+
natural: '=',
|
|
7570
|
+
sharp: '^',
|
|
7571
|
+
dblsharp: '^^',
|
|
7572
|
+
quarterflat: '_/',
|
|
7573
|
+
quartersharp: '^/'
|
|
7574
|
+
};
|
|
7575
|
+
module.exports.tripletQ = {
|
|
7576
|
+
2: 3,
|
|
7577
|
+
3: 2,
|
|
7578
|
+
4: 3,
|
|
7579
|
+
5: 2,
|
|
7580
|
+
// TODO-PER: not handling 6/8 rhythm yet
|
|
7581
|
+
6: 2,
|
|
7582
|
+
7: 2,
|
|
7583
|
+
// TODO-PER: not handling 6/8 rhythm yet
|
|
7584
|
+
8: 3,
|
|
7585
|
+
9: 2 // TODO-PER: not handling 6/8 rhythm yet
|
|
7586
|
+
};
|
|
7587
|
+
|
|
7588
|
+
/***/ }),
|
|
7589
|
+
|
|
7562
7590
|
/***/ "./src/parse/abc_tokenizer.js":
|
|
7563
7591
|
/*!************************************!*\
|
|
7564
7592
|
!*** ./src/parse/abc_tokenizer.js ***!
|
|
@@ -14186,6 +14214,9 @@ function CreateSynth() {
|
|
|
14186
14214
|
self.getAudioBuffer = function () {
|
|
14187
14215
|
return self.audioBuffers[0];
|
|
14188
14216
|
};
|
|
14217
|
+
self.getIsRunning = function () {
|
|
14218
|
+
return self.isRunning;
|
|
14219
|
+
};
|
|
14189
14220
|
|
|
14190
14221
|
/////////////// Private functions //////////////
|
|
14191
14222
|
|
|
@@ -14782,6 +14813,11 @@ function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMulti
|
|
|
14782
14813
|
if (len < 0) len = 0.005; // Have some small audible length no matter how short the note is.
|
|
14783
14814
|
var offlineCtx = new OfflineAC(2, Math.floor((len + fadeTimeSec) * sampleRate), sampleRate);
|
|
14784
14815
|
var noteName = pitchToNoteName[sound.pitch];
|
|
14816
|
+
if (!soundsCache[sound.instrument]) {
|
|
14817
|
+
// It shouldn't happen that the entire instrument cache wasn't created, but this has been seen in practice, so guard against it.
|
|
14818
|
+
if (debugCallback) debugCallback('placeNote skipped (instrument empty): ' + sound.instrument + ':' + noteName);
|
|
14819
|
+
return Promise.resolve();
|
|
14820
|
+
}
|
|
14785
14821
|
var noteBufferPromise = soundsCache[sound.instrument][noteName];
|
|
14786
14822
|
if (!noteBufferPromise) {
|
|
14787
14823
|
// if the note isn't present then just skip it - it will leave a blank spot in the audio.
|
|
@@ -14877,7 +14913,7 @@ module.exports = placeNote;
|
|
|
14877
14913
|
var SynthSequence = __webpack_require__(/*! ./synth-sequence */ "./src/synth/synth-sequence.js");
|
|
14878
14914
|
var CreateSynth = __webpack_require__(/*! ./create-synth */ "./src/synth/create-synth.js");
|
|
14879
14915
|
var activeAudioContext = __webpack_require__(/*! ./active-audio-context */ "./src/synth/active-audio-context.js");
|
|
14880
|
-
function playEvent(midiPitches, midiGracePitches, millisecondsPerMeasure) {
|
|
14916
|
+
function playEvent(midiPitches, midiGracePitches, millisecondsPerMeasure, soundFontUrl, debugCallback) {
|
|
14881
14917
|
var sequence = new SynthSequence();
|
|
14882
14918
|
for (var i = 0; i < midiPitches.length; i++) {
|
|
14883
14919
|
var note = midiPitches[i];
|
|
@@ -14894,17 +14930,21 @@ function playEvent(midiPitches, midiGracePitches, millisecondsPerMeasure) {
|
|
|
14894
14930
|
var ac = activeAudioContext();
|
|
14895
14931
|
if (ac.state === "suspended") {
|
|
14896
14932
|
return ac.resume().then(function () {
|
|
14897
|
-
return doPlay(sequence, millisecondsPerMeasure);
|
|
14933
|
+
return doPlay(sequence, millisecondsPerMeasure, soundFontUrl, debugCallback);
|
|
14898
14934
|
});
|
|
14899
14935
|
} else {
|
|
14900
|
-
return doPlay(sequence, millisecondsPerMeasure);
|
|
14936
|
+
return doPlay(sequence, millisecondsPerMeasure, soundFontUrl, debugCallback);
|
|
14901
14937
|
}
|
|
14902
14938
|
}
|
|
14903
|
-
function doPlay(sequence, millisecondsPerMeasure) {
|
|
14939
|
+
function doPlay(sequence, millisecondsPerMeasure, soundFontUrl, debugCallback) {
|
|
14904
14940
|
var buffer = new CreateSynth();
|
|
14905
14941
|
return buffer.init({
|
|
14906
14942
|
sequence: sequence,
|
|
14907
|
-
millisecondsPerMeasure: millisecondsPerMeasure
|
|
14943
|
+
millisecondsPerMeasure: millisecondsPerMeasure,
|
|
14944
|
+
options: {
|
|
14945
|
+
soundFontUrl: soundFontUrl
|
|
14946
|
+
},
|
|
14947
|
+
debugCallback: debugCallback
|
|
14908
14948
|
}).then(function () {
|
|
14909
14949
|
return buffer.prime();
|
|
14910
14950
|
}).then(function () {
|
|
@@ -16250,10 +16290,10 @@ function buildGraceRelativesForRest(plugin, abs, absChild, graceNotes, tabVoice)
|
|
|
16250
16290
|
* Build tab absolutes by scanning current staff line absolute array
|
|
16251
16291
|
* @param {*} staffAbsolute
|
|
16252
16292
|
*/
|
|
16253
|
-
TabAbsoluteElements.prototype.build = function (plugin, staffAbsolute, tabVoice, voiceIndex, staffIndex, keySig) {
|
|
16293
|
+
TabAbsoluteElements.prototype.build = function (plugin, staffAbsolute, tabVoice, voiceIndex, staffIndex, keySig, tabVoiceIndex) {
|
|
16254
16294
|
var staffSize = getInitialStaffSize(staffAbsolute);
|
|
16255
16295
|
var source = staffAbsolute[staffIndex + voiceIndex];
|
|
16256
|
-
var dest = staffAbsolute[
|
|
16296
|
+
var dest = staffAbsolute[tabVoiceIndex];
|
|
16257
16297
|
var tabPos = null;
|
|
16258
16298
|
var defNote = null;
|
|
16259
16299
|
if (source.children[0].abcelem.el_type != 'clef') {
|
|
@@ -16632,15 +16672,17 @@ TabRenderer.prototype.doLayout = function () {
|
|
|
16632
16672
|
this.tabStaff.voices = [];
|
|
16633
16673
|
for (var ii = 0; ii < nbVoices; ii++) {
|
|
16634
16674
|
var tabVoice = new VoiceElement(0, 0);
|
|
16675
|
+
if (ii > 0) tabVoice.duplicate = true;
|
|
16635
16676
|
var nameHeight = buildTabName(this, tabVoice) / spacing.STEP;
|
|
16636
16677
|
nameHeight = Math.max(nameHeight, 1); // If there is no label for the tab line, then there needs to be a little padding
|
|
16637
16678
|
staffGroup.staffs[this.staffIndex].top += nameHeight;
|
|
16638
16679
|
staffGroup.height += nameHeight * spacing.STEP;
|
|
16639
16680
|
tabVoice.staff = staffGroupInfos;
|
|
16681
|
+
var tabVoiceIndex = voices.length;
|
|
16640
16682
|
voices.splice(voices.length, 0, tabVoice);
|
|
16641
16683
|
var keySig = checkVoiceKeySig(voices, ii + this.staffIndex);
|
|
16642
16684
|
this.tabStaff.voices[ii] = [];
|
|
16643
|
-
this.absolutes.build(this.plugin, voices, this.tabStaff.voices[ii], ii, this.staffIndex, keySig);
|
|
16685
|
+
this.absolutes.build(this.plugin, voices, this.tabStaff.voices[ii], ii, this.staffIndex, keySig, tabVoiceIndex);
|
|
16644
16686
|
}
|
|
16645
16687
|
linkStaffAndTabs(staffGroup.staffs); // crossreference tabs and staff
|
|
16646
16688
|
};
|
|
@@ -17484,6 +17526,9 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
|
|
|
17484
17526
|
if (noteHead && noteHead.c === 'noteheads.slash.quarter') {
|
|
17485
17527
|
if (dir === 'down') p2 -= 1;else p1 += 1;
|
|
17486
17528
|
}
|
|
17529
|
+
if (noteHead && noteHead.c === 'noteheads.triangle.quarter') {
|
|
17530
|
+
if (dir === 'down') p2 -= 0.7;else p1 -= 1.2;
|
|
17531
|
+
}
|
|
17487
17532
|
abselem.addRight(new RelativeElement(null, dx, 0, p1, {
|
|
17488
17533
|
"type": "stem",
|
|
17489
17534
|
"pitch2": p2,
|
|
@@ -18696,10 +18741,12 @@ Decoration.prototype.dynamicDecoration = function (voice, decoration, abselem, p
|
|
|
18696
18741
|
};
|
|
18697
18742
|
this.startCrescendoX = undefined;
|
|
18698
18743
|
break;
|
|
18744
|
+
case '~(':
|
|
18699
18745
|
case "glissando(":
|
|
18700
18746
|
this.startGlissandoX = abselem;
|
|
18701
18747
|
glissando = undefined;
|
|
18702
18748
|
break;
|
|
18749
|
+
case '~)':
|
|
18703
18750
|
case "glissando)":
|
|
18704
18751
|
glissando = {
|
|
18705
18752
|
start: this.startGlissandoX,
|
|
@@ -20692,7 +20739,7 @@ glyphs['noteheads.harmonic.quarter'] = {
|
|
|
20692
20739
|
h: 8.165
|
|
20693
20740
|
};
|
|
20694
20741
|
glyphs['noteheads.triangle.quarter'] = {
|
|
20695
|
-
d: [['M', 0,
|
|
20742
|
+
d: [['M', 0, 4], ['l', 9, 0], ['l', -4.5, -9], ['z']],
|
|
20696
20743
|
w: 9,
|
|
20697
20744
|
h: 9
|
|
20698
20745
|
};
|
|
@@ -21565,14 +21612,20 @@ function printLine(renderer, x1, x2, y, klass, name, dy) {
|
|
|
21565
21612
|
x2 = roundNumber(x2);
|
|
21566
21613
|
var y1 = roundNumber(y - dy);
|
|
21567
21614
|
var y2 = roundNumber(y + dy);
|
|
21568
|
-
// TODO-PER: This fixes a firefox bug where
|
|
21569
|
-
if (renderer.firefox112
|
|
21570
|
-
|
|
21571
|
-
var
|
|
21572
|
-
|
|
21573
|
-
|
|
21574
|
-
|
|
21575
|
-
|
|
21615
|
+
// TODO-PER: This fixes a firefox bug where it isn't displayed
|
|
21616
|
+
if (renderer.firefox112) {
|
|
21617
|
+
y += dy / 2; // Because the y coordinate is the edge of where the line goes but the width widens from the middle.
|
|
21618
|
+
var attr = {
|
|
21619
|
+
x1: x1,
|
|
21620
|
+
x2: x2,
|
|
21621
|
+
y1: y,
|
|
21622
|
+
y2: y,
|
|
21623
|
+
stroke: renderer.foregroundColor,
|
|
21624
|
+
'stroke-width': Math.abs(dy * 2)
|
|
21625
|
+
};
|
|
21626
|
+
if (klass) attr['class'] = klass;
|
|
21627
|
+
if (name) attr['data-name'] = name;
|
|
21628
|
+
return renderer.paper.lineToBack(attr);
|
|
21576
21629
|
}
|
|
21577
21630
|
var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y1, x2, y1, x2, y2, x1, y2);
|
|
21578
21631
|
var options = {
|
|
@@ -21623,15 +21676,20 @@ function printStem(renderer, x, dx, y1, y2, klass, name) {
|
|
|
21623
21676
|
}
|
|
21624
21677
|
x = roundNumber(x);
|
|
21625
21678
|
var x2 = roundNumber(x + dx);
|
|
21626
|
-
// TODO-PER: This fixes a firefox bug where
|
|
21627
|
-
if (renderer.firefox112
|
|
21628
|
-
|
|
21629
|
-
var
|
|
21630
|
-
|
|
21631
|
-
|
|
21632
|
-
|
|
21633
|
-
|
|
21634
|
-
|
|
21679
|
+
// TODO-PER: This fixes a firefox bug where it isn't displayed
|
|
21680
|
+
if (renderer.firefox112) {
|
|
21681
|
+
x += dx / 2; // Because the x coordinate is the edge of where the line goes but the width widens from the middle.
|
|
21682
|
+
var attr = {
|
|
21683
|
+
x1: x,
|
|
21684
|
+
x2: x,
|
|
21685
|
+
y1: y1,
|
|
21686
|
+
y2: y2,
|
|
21687
|
+
stroke: renderer.foregroundColor,
|
|
21688
|
+
'stroke-width': Math.abs(dx)
|
|
21689
|
+
};
|
|
21690
|
+
if (klass) attr['class'] = klass;
|
|
21691
|
+
if (name) attr['data-name'] = name;
|
|
21692
|
+
return renderer.paper.lineToBack(attr);
|
|
21635
21693
|
}
|
|
21636
21694
|
var pathArray = [["M", x, y1], ["L", x, y2], ["L", x2, y2], ["L", x2, y1], ["z"]];
|
|
21637
21695
|
var attr = {
|
|
@@ -22025,7 +22083,7 @@ module.exports = drawSeparator;
|
|
|
22025
22083
|
/***/ (function(module) {
|
|
22026
22084
|
|
|
22027
22085
|
function setPaperSize(renderer, maxwidth, scale, responsive) {
|
|
22028
|
-
var w = (maxwidth + renderer.padding.right) * scale;
|
|
22086
|
+
var w = (maxwidth + renderer.padding.left + renderer.padding.right) * scale;
|
|
22029
22087
|
var h = (renderer.y + renderer.padding.bottom) * scale;
|
|
22030
22088
|
if (renderer.isPrint) h = Math.max(h, 1056); // 11in x 72pt/in x 1.33px/pt
|
|
22031
22089
|
// TODO-PER: We are letting the page get as long as it needs now, but eventually that should go to a second page.
|
|
@@ -22638,10 +22696,15 @@ function drawTie(renderer, params, linestartx, lineendx, selectables) {
|
|
|
22638
22696
|
if (params.hint) klass = "abcjs-hint";
|
|
22639
22697
|
var fudgeY = params.fixedY ? 1.5 : 0; // TODO-PER: This just compensates for drawArc, which contains too much knowledge of ties and slurs.
|
|
22640
22698
|
var el = drawArc(renderer, params.startX, params.endX, params.startY + fudgeY, params.endY + fudgeY, params.above, klass, params.isTie, params.dotted);
|
|
22699
|
+
var startChar = -1;
|
|
22700
|
+
// This gets the start and end points of the contents of the slur. We assume that the parenthesis are just to the outside of that.
|
|
22701
|
+
if (params.anchor1 && !params.isTie) startChar = params.anchor1.parent.abcelem.startChar - 1;
|
|
22702
|
+
var endChar = -1;
|
|
22703
|
+
if (params.anchor2 && !params.isTie) endChar = params.anchor2.parent.abcelem.endChar + 1;
|
|
22641
22704
|
selectables.wrapSvgEl({
|
|
22642
22705
|
el_type: "slur",
|
|
22643
|
-
startChar:
|
|
22644
|
-
endChar:
|
|
22706
|
+
startChar: startChar,
|
|
22707
|
+
endChar: endChar
|
|
22645
22708
|
}, el);
|
|
22646
22709
|
return [el];
|
|
22647
22710
|
}
|
|
@@ -22951,6 +23014,7 @@ var EngraverController = function EngraverController(paper, params) {
|
|
|
22951
23014
|
this.responsive = params.responsive;
|
|
22952
23015
|
this.space = 3 * spacing.SPACE;
|
|
22953
23016
|
this.initialClef = params.initialClef;
|
|
23017
|
+
this.expandToWidest = !!params.expandToWidest;
|
|
22954
23018
|
this.scale = params.scale ? parseFloat(params.scale) : 0;
|
|
22955
23019
|
this.classes = new Classes({
|
|
22956
23020
|
shouldAddClasses: params.add_classes
|
|
@@ -23134,7 +23198,12 @@ EngraverController.prototype.engraveTune = function (abcTune, tuneNumber, lineOf
|
|
|
23134
23198
|
this.constructTuneElements(abcTune);
|
|
23135
23199
|
|
|
23136
23200
|
// Do all the positioning, both horizontally and vertically
|
|
23137
|
-
var maxWidth = layout(this.renderer, abcTune, this.width, this.space);
|
|
23201
|
+
var maxWidth = layout(this.renderer, abcTune, this.width, this.space, this.expandToWidest);
|
|
23202
|
+
|
|
23203
|
+
//Set the top text now that we know the width
|
|
23204
|
+
if (this.expandToWidest && maxWidth > this.width + 1) {
|
|
23205
|
+
abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, maxWidth, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
|
|
23206
|
+
}
|
|
23138
23207
|
|
|
23139
23208
|
// Deal with tablature for staff
|
|
23140
23209
|
if (abcTune.tablatures) {
|
|
@@ -23147,13 +23216,13 @@ EngraverController.prototype.engraveTune = function (abcTune, tuneNumber, lineOf
|
|
|
23147
23216
|
this.selectables = ret.selectables;
|
|
23148
23217
|
if (this.oneSvgPerLine) {
|
|
23149
23218
|
var div = this.renderer.paper.svg.parentNode;
|
|
23150
|
-
this.svgs = splitSvgIntoLines(div, abcTune.metaText.title, this.responsive);
|
|
23219
|
+
this.svgs = splitSvgIntoLines(this.renderer, div, abcTune.metaText.title, this.responsive);
|
|
23151
23220
|
} else {
|
|
23152
23221
|
this.svgs = [this.renderer.paper.svg];
|
|
23153
23222
|
}
|
|
23154
23223
|
setupSelection(this, this.svgs);
|
|
23155
23224
|
};
|
|
23156
|
-
function splitSvgIntoLines(output, title, responsive) {
|
|
23225
|
+
function splitSvgIntoLines(renderer, output, title, responsive) {
|
|
23157
23226
|
// Each line is a top level <g> in the svg. To split it into separate
|
|
23158
23227
|
// svgs iterate through each of those and put them in a new svg. Since
|
|
23159
23228
|
// they are placed absolutely, the viewBox needs to be manipulated to
|
|
@@ -23183,7 +23252,9 @@ function splitSvgIntoLines(output, title, responsive) {
|
|
|
23183
23252
|
svg.setAttribute("aria-label", fullTitle);
|
|
23184
23253
|
if (responsive !== 'resize') svg.setAttribute("height", height);
|
|
23185
23254
|
if (responsive === 'resize') svg.style.position = '';
|
|
23186
|
-
|
|
23255
|
+
// TODO-PER: Hack! Not sure why this is needed.
|
|
23256
|
+
var viewBoxHeight = renderer.firefox112 ? height + 1 : height;
|
|
23257
|
+
svg.setAttribute("viewBox", "0 " + nextTop + " " + width + " " + viewBoxHeight);
|
|
23187
23258
|
svg.appendChild(style.cloneNode(true));
|
|
23188
23259
|
var titleEl = document.createElement("title");
|
|
23189
23260
|
titleEl.innerText = fullTitle;
|
|
@@ -23635,6 +23706,7 @@ function keyboardSelection(ev) {
|
|
|
23635
23706
|
if (handled) ev.preventDefault();
|
|
23636
23707
|
}
|
|
23637
23708
|
function findElementInHistory(selectables, el) {
|
|
23709
|
+
if (!el) return -1;
|
|
23638
23710
|
for (var i = 0; i < selectables.length; i++) {
|
|
23639
23711
|
if (el.dataset.index === selectables[i].svgEl.dataset.index) return i;
|
|
23640
23712
|
}
|
|
@@ -23693,7 +23765,9 @@ function getBestMatchCoordinates(dim, ev, scale) {
|
|
|
23693
23765
|
}
|
|
23694
23766
|
function getTarget(target) {
|
|
23695
23767
|
// This searches up the dom for the first item containing the attribute "selectable", or stopping at the SVG.
|
|
23768
|
+
if (!target) return null;
|
|
23696
23769
|
if (target.tagName === "svg") return target;
|
|
23770
|
+
if (!target.getAttribute) return null;
|
|
23697
23771
|
var found = target.getAttribute("selectable");
|
|
23698
23772
|
while (!found) {
|
|
23699
23773
|
if (!target.parentElement) found = true;else {
|
|
@@ -24232,7 +24306,7 @@ var layoutVoice = __webpack_require__(/*! ./voice */ "./src/write/layout/voice.j
|
|
|
24232
24306
|
var setUpperAndLowerElements = __webpack_require__(/*! ./set-upper-and-lower-elements */ "./src/write/layout/set-upper-and-lower-elements.js");
|
|
24233
24307
|
var layoutStaffGroup = __webpack_require__(/*! ./staff-group */ "./src/write/layout/staff-group.js");
|
|
24234
24308
|
var getLeftEdgeOfStaff = __webpack_require__(/*! ./get-left-edge-of-staff */ "./src/write/layout/get-left-edge-of-staff.js");
|
|
24235
|
-
var layout = function layout(renderer, abctune, width, space) {
|
|
24309
|
+
var layout = function layout(renderer, abctune, width, space, expandToWidest) {
|
|
24236
24310
|
var i;
|
|
24237
24311
|
var abcLine;
|
|
24238
24312
|
// Adjust the x-coordinates to their absolute positions
|
|
@@ -24240,8 +24314,14 @@ var layout = function layout(renderer, abctune, width, space) {
|
|
|
24240
24314
|
for (i = 0; i < abctune.lines.length; i++) {
|
|
24241
24315
|
abcLine = abctune.lines[i];
|
|
24242
24316
|
if (abcLine.staff) {
|
|
24243
|
-
|
|
24244
|
-
|
|
24317
|
+
// console.log("=== line", i)
|
|
24318
|
+
var thisWidth = setXSpacing(renderer, maxWidth, space, abcLine.staffGroup, abctune.formatting, i === abctune.lines.length - 1, false);
|
|
24319
|
+
// console.log(thisWidth, maxWidth)
|
|
24320
|
+
if (Math.round(thisWidth) > Math.round(maxWidth)) {
|
|
24321
|
+
// to take care of floating point weirdness
|
|
24322
|
+
maxWidth = thisWidth;
|
|
24323
|
+
if (expandToWidest) i = -1; // do the calculations over with the new width
|
|
24324
|
+
}
|
|
24245
24325
|
}
|
|
24246
24326
|
}
|
|
24247
24327
|
|
|
@@ -24272,13 +24352,38 @@ var setXSpacing = function setXSpacing(renderer, width, space, staffGroup, forma
|
|
|
24272
24352
|
var newspace = space;
|
|
24273
24353
|
for (var it = 0; it < 8; it++) {
|
|
24274
24354
|
// TODO-PER: shouldn't need multiple passes, but each pass gets it closer to the right spacing. (Only affects long lines: normal lines break out of this loop quickly.)
|
|
24355
|
+
// console.log("iteration", it)
|
|
24356
|
+
// dumpGroup("before", staffGroup)
|
|
24275
24357
|
var ret = layoutStaffGroup(newspace, renderer, debug, staffGroup, leftEdge);
|
|
24358
|
+
// dumpGroup("after",staffGroup)
|
|
24276
24359
|
newspace = calcHorizontalSpacing(isLastLine, formatting.stretchlast, width + renderer.padding.left, staffGroup.w, newspace, ret.spacingUnits, ret.minSpace, renderer.padding.left + renderer.padding.right);
|
|
24277
24360
|
if (debug) console.log("setXSpace", it, staffGroup.w, newspace, staffGroup.minspace);
|
|
24278
24361
|
if (newspace === null) break;
|
|
24279
24362
|
}
|
|
24280
24363
|
centerWholeRests(staffGroup.voices);
|
|
24281
|
-
|
|
24364
|
+
return staffGroup.w - leftEdge;
|
|
24365
|
+
};
|
|
24366
|
+
|
|
24367
|
+
// function dumpGroup(label, staffGroup) {
|
|
24368
|
+
// var output = {
|
|
24369
|
+
// line: staffGroup.line,
|
|
24370
|
+
// w: staffGroup.w,
|
|
24371
|
+
// voice: {
|
|
24372
|
+
// i: staffGroup.voices[0].i,
|
|
24373
|
+
// minx: staffGroup.voices[0].minx,
|
|
24374
|
+
// nextx: staffGroup.voices[0].nextx,
|
|
24375
|
+
// spacingduration: staffGroup.voices[0].spacingduration,
|
|
24376
|
+
// w: staffGroup.voices[0].w,
|
|
24377
|
+
// children: [],
|
|
24378
|
+
// }
|
|
24379
|
+
// }
|
|
24380
|
+
// for (var i = 0; i < staffGroup.voices[0].children.length; i++) {
|
|
24381
|
+
// var child = staffGroup.voices[0].children[i]
|
|
24382
|
+
// output.voice.children.push({ fixedW: child.fixed.w, w: child.w, x: child.x, type: child.type })
|
|
24383
|
+
// }
|
|
24384
|
+
// console.log(label,output)
|
|
24385
|
+
// }
|
|
24386
|
+
|
|
24282
24387
|
function calcHorizontalSpacing(isLastLine, stretchLast, targetWidth, lineWidth, spacing, spacingUnits, minSpace, padding) {
|
|
24283
24388
|
if (isLastLine) {
|
|
24284
24389
|
if (stretchLast === undefined) {
|
|
@@ -25486,6 +25591,15 @@ Svg.prototype.pathToBack = function (attr) {
|
|
|
25486
25591
|
this.prepend(el);
|
|
25487
25592
|
return el;
|
|
25488
25593
|
};
|
|
25594
|
+
Svg.prototype.lineToBack = function (attr) {
|
|
25595
|
+
var el = document.createElementNS(svgNS, 'line');
|
|
25596
|
+
var keys = Object.keys(attr);
|
|
25597
|
+
for (var i = 0; i < keys.length; i++) {
|
|
25598
|
+
el.setAttribute(keys[i], attr[keys[i]]);
|
|
25599
|
+
}
|
|
25600
|
+
this.prepend(el);
|
|
25601
|
+
return el;
|
|
25602
|
+
};
|
|
25489
25603
|
Svg.prototype.append = function (el) {
|
|
25490
25604
|
if (this.currentGroup.length > 0) this.currentGroup[0].appendChild(el);else this.svg.appendChild(el);
|
|
25491
25605
|
};
|
|
@@ -25521,7 +25635,7 @@ module.exports = Svg;
|
|
|
25521
25635
|
\********************/
|
|
25522
25636
|
/***/ (function(module) {
|
|
25523
25637
|
|
|
25524
|
-
var version = '6.2.
|
|
25638
|
+
var version = '6.2.3';
|
|
25525
25639
|
module.exports = version;
|
|
25526
25640
|
|
|
25527
25641
|
/***/ })
|