abcjs 6.1.6 → 6.1.8
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 +2 -0
- package/RELEASE.md +41 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +1197 -4821
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/package.json +14 -10
- package/src/data/abc_tune.js +2 -0
- package/src/parse/abc_parse.js +1 -0
- package/src/parse/abc_parse_key_voice.js +10 -1
- package/src/parse/abc_parse_music.js +1 -0
- package/src/synth/pitches-to-perc.js +12 -0
- package/src/tablatures/instruments/string-patterns.js +18 -1
- package/src/tablatures/instruments/tab-note.js +12 -1
- package/src/tablatures/tab-absolute-elements.js +3 -0
- package/src/tablatures/tab-renderer.js +1 -0
- package/src/write/abc_abstract_engraver.js +5 -2
- package/src/write/classes.js +4 -0
- package/src/write/draw/absolute.js +8 -0
- package/src/write/selection.js +2 -2
- package/version.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abcjs",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.8",
|
|
4
4
|
"description": "Renderer for abc music notation",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"build:basic": "npm run webpack -- --mode development --config-name basic",
|
|
11
11
|
"build:basic-min": "npm run webpack -- --mode production --config-name basic",
|
|
12
12
|
"build:plugin": "npm run webpack -- --mode production --config-name plugin",
|
|
13
|
-
"test": "
|
|
13
|
+
"test-server": "npx http-server",
|
|
14
|
+
"test": "concurrently \"http-server\" \"npx opener http://localhost:8080/tests/all.html\"",
|
|
14
15
|
"docs:dev": "vuepress dev docs",
|
|
15
16
|
"docs:build": "vuepress build docs",
|
|
16
17
|
"build:analyze": "npm run build:basic -- --env analyze"
|
|
@@ -43,15 +44,18 @@
|
|
|
43
44
|
},
|
|
44
45
|
"homepage": "https://abcjs.net",
|
|
45
46
|
"devDependencies": {
|
|
46
|
-
"@babel/core": "7.
|
|
47
|
-
"@babel/preset-env": "7.
|
|
47
|
+
"@babel/core": "7.20.2",
|
|
48
|
+
"@babel/preset-env": "7.20.2",
|
|
48
49
|
"@tarp/require": "1.4.3",
|
|
49
|
-
"babel-loader": "
|
|
50
|
-
"chai": "4.3.
|
|
51
|
-
"
|
|
50
|
+
"babel-loader": "9.1.0",
|
|
51
|
+
"chai": "4.3.7",
|
|
52
|
+
"concurrently": "7.5.0",
|
|
53
|
+
"http-server": "14.1.1",
|
|
54
|
+
"mocha": "10.1.0",
|
|
55
|
+
"opener": "1.5.2",
|
|
52
56
|
"vuepress": "2.0.0-beta.26",
|
|
53
|
-
"vuex": "4.
|
|
54
|
-
"webpack-bundle-analyzer": "4.
|
|
55
|
-
"webpack-cli": "4.
|
|
57
|
+
"vuex": "4.1.0",
|
|
58
|
+
"webpack-bundle-analyzer": "4.7.0",
|
|
59
|
+
"webpack-cli": "4.10.0"
|
|
56
60
|
}
|
|
57
61
|
}
|
package/src/data/abc_tune.js
CHANGED
package/src/parse/abc_parse.js
CHANGED
|
@@ -408,6 +408,16 @@ var parseKeyVoice = {};
|
|
|
408
408
|
multilineVars.clef.staffscale = tokens[0].floatt;
|
|
409
409
|
tokens.shift();
|
|
410
410
|
break;
|
|
411
|
+
case "octave":
|
|
412
|
+
tokens.shift();
|
|
413
|
+
if (tokens.length === 0) { warn("Expected = after octave", str, 0); return ret; }
|
|
414
|
+
token = tokens.shift();
|
|
415
|
+
if (token.token !== "=") { warn("Expected = after octave", str, token.start); break; }
|
|
416
|
+
if (tokens.length === 0) { warn("Expected parameter after octave=", str, 0); return ret; }
|
|
417
|
+
if (tokens[0].type !== 'number') { warn("Expected number after octave", str, tokens[0].start); break; }
|
|
418
|
+
multilineVars.octave = tokens[0].intt;
|
|
419
|
+
tokens.shift();
|
|
420
|
+
break;
|
|
411
421
|
case "style":
|
|
412
422
|
tokens.shift();
|
|
413
423
|
if (tokens.length === 0) { warn("Expected = after style", str, 0); return ret; }
|
|
@@ -716,7 +726,6 @@ var parseKeyVoice = {};
|
|
|
716
726
|
addNextTokenToVoiceInfo(id, 'staffscale', 'number');
|
|
717
727
|
break;
|
|
718
728
|
case 'octave':
|
|
719
|
-
// TODO-PER: This is accepted, but not implemented, yet.
|
|
720
729
|
addNextTokenToVoiceInfo(id, 'octave', 'number');
|
|
721
730
|
break;
|
|
722
731
|
case 'volume':
|
|
@@ -1128,6 +1128,7 @@ var getCoreNote = function(line, index, el, canHaveBrokenRhythm) {
|
|
|
1128
1128
|
case 'g':
|
|
1129
1129
|
if (state === 'startSlur' || state === 'sharp2' || state === 'flat2' || state === 'pitch') {
|
|
1130
1130
|
el.pitch = pitches[line.charAt(index)];
|
|
1131
|
+
el.pitch += 7 * (multilineVars.currentVoice && multilineVars.currentVoice.octave !== undefined ? multilineVars.currentVoice.octave : multilineVars.octave);
|
|
1131
1132
|
el.name = line.charAt(index);
|
|
1132
1133
|
if (el.accidental)
|
|
1133
1134
|
el.name = accMap[el.accidental] + el.name;
|
|
@@ -55,6 +55,18 @@ var pitchMap = {
|
|
|
55
55
|
n13: "=b",
|
|
56
56
|
s13: "^b",
|
|
57
57
|
x13: "b",
|
|
58
|
+
f14: "_c'",
|
|
59
|
+
n14: "=c'",
|
|
60
|
+
s14: "^c'",
|
|
61
|
+
x14: "c'",
|
|
62
|
+
f15: "_d'",
|
|
63
|
+
n15: "=d'",
|
|
64
|
+
s15: "^d'",
|
|
65
|
+
x15: "d'",
|
|
66
|
+
f16: "_e'",
|
|
67
|
+
n16: "=e'",
|
|
68
|
+
s16: "^e'",
|
|
69
|
+
x16: "e'",
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
function pitchesToPerc(pitchObj) {
|
|
@@ -103,7 +103,7 @@ function handleChordNotes(self, notes) {
|
|
|
103
103
|
|
|
104
104
|
function noteToNumber(self, note, stringNumber, secondPosition , firstSize) {
|
|
105
105
|
var strings = self.strings;
|
|
106
|
-
note.checkKeyAccidentals(self.accidentals) ;
|
|
106
|
+
note.checkKeyAccidentals(self.accidentals, self.measureAccidentals) ;
|
|
107
107
|
if (secondPosition) {
|
|
108
108
|
strings = secondPosition;
|
|
109
109
|
}
|
|
@@ -131,6 +131,22 @@ function noteToNumber(self, note, stringNumber, secondPosition , firstSize) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
function toNumber(self, note) {
|
|
134
|
+
if (note.isAltered || note.natural) {
|
|
135
|
+
var acc;
|
|
136
|
+
if (note.isFlat) {
|
|
137
|
+
if (note.isDouble)
|
|
138
|
+
acc = "__"
|
|
139
|
+
else
|
|
140
|
+
acc = "_"
|
|
141
|
+
} else if (note.isSharp) {
|
|
142
|
+
if (note.isDouble)
|
|
143
|
+
acc = "^^"
|
|
144
|
+
else
|
|
145
|
+
acc = "^"
|
|
146
|
+
} else if (note.natural)
|
|
147
|
+
acc = "="
|
|
148
|
+
self.measureAccidentals[note.name.toUpperCase()] = acc
|
|
149
|
+
}
|
|
134
150
|
var num = null;
|
|
135
151
|
var str = 0;
|
|
136
152
|
var lowestString = self.strings[self.strings.length - 1];
|
|
@@ -254,6 +270,7 @@ function StringPatterns(plugin) {
|
|
|
254
270
|
// override default
|
|
255
271
|
this.highestNote = highestNote;
|
|
256
272
|
}
|
|
273
|
+
this.measureAccidentals = {}
|
|
257
274
|
this.capo = 0;
|
|
258
275
|
if (capo) {
|
|
259
276
|
this.capo = capo;
|
|
@@ -115,7 +115,18 @@ TabNote.prototype.isLowerThan = function (note) {
|
|
|
115
115
|
return false;
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
-
TabNote.prototype.checkKeyAccidentals = function(accidentals) {
|
|
118
|
+
TabNote.prototype.checkKeyAccidentals = function(accidentals, measureAccidentals) {
|
|
119
|
+
if (this.isAltered || this.natural)
|
|
120
|
+
return
|
|
121
|
+
if (measureAccidentals[this.name.toUpperCase()]) {
|
|
122
|
+
switch (measureAccidentals[this.name.toUpperCase()]) {
|
|
123
|
+
case "__": this.acc = -2; return;
|
|
124
|
+
case "_": this.acc = -1; return;
|
|
125
|
+
case "=": this.acc = 0; return;
|
|
126
|
+
case "^": this.acc = 1; return;
|
|
127
|
+
case "^^": this.acc = 2; return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
119
130
|
if (accidentals) {
|
|
120
131
|
var curNote = this.name;
|
|
121
132
|
for (var iii = 0; iii < accidentals.length; iii++) {
|
|
@@ -27,6 +27,8 @@ function cloneAbsolute(absSrc) {
|
|
|
27
27
|
if (returned.abcelem.el_type === "note")
|
|
28
28
|
returned.abcelem.el_type = 'tabNumber';
|
|
29
29
|
}
|
|
30
|
+
// TODO-PER: This fixes the classes because the element isn't created at the right time.
|
|
31
|
+
absSrc.cloned = returned
|
|
30
32
|
return returned;
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -226,6 +228,7 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
226
228
|
}
|
|
227
229
|
break;
|
|
228
230
|
case 'bar':
|
|
231
|
+
plugin.semantics.strings.measureAccidentals = {}
|
|
229
232
|
var lastBar = false;
|
|
230
233
|
if (ii === source.children.length-1) {
|
|
231
234
|
// used for final line bar drawing
|
|
@@ -228,6 +228,7 @@ TabRenderer.prototype.doLayout = function () {
|
|
|
228
228
|
for (var ii = 0; ii < nbVoices; ii++) {
|
|
229
229
|
var tabVoice = new VoiceElement(0, 0);
|
|
230
230
|
var nameHeight = buildTabName(this, tabVoice) / spacing.STEP;
|
|
231
|
+
nameHeight = Math.max(nameHeight, 1) // If there is no label for the tab line, then there needs to be a little padding
|
|
231
232
|
staffGroup.staffs[this.staffIndex].top += nameHeight;
|
|
232
233
|
staffGroup.height += nameHeight * spacing.STEP;
|
|
233
234
|
tabVoice.staff = staffGroupInfos;
|
|
@@ -920,8 +920,11 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
920
920
|
|
|
921
921
|
AbstractEngraver.prototype.addMeasureNumber = function (number, abselem) {
|
|
922
922
|
var measureNumDim = this.getTextSize.calc(number, "measurefont", 'bar-number');
|
|
923
|
-
var dx =
|
|
924
|
-
abselem.
|
|
923
|
+
var dx = 0;
|
|
924
|
+
if (abselem.isClef) // If this is a clef rather than bar line, then the number shouldn't be centered because it could overlap the left side. This is an easy way to let it be centered but move it over, too.
|
|
925
|
+
dx += measureNumDim.width / 2
|
|
926
|
+
var vert = measureNumDim.width > 10 && abselem.abcelem.type === "treble" ? 13 : 11
|
|
927
|
+
abselem.addFixed(new RelativeElement(number, dx, measureNumDim.width, vert+measureNumDim.height / spacing.STEP, {type:"barNumber", dim: this.getTextSize.attr("measurefont", 'bar-number')}));
|
|
925
928
|
};
|
|
926
929
|
|
|
927
930
|
AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff) {
|
package/src/write/classes.js
CHANGED
|
@@ -79,6 +79,10 @@ Classes.prototype.generate = function (c) {
|
|
|
79
79
|
return "";
|
|
80
80
|
var ret = [];
|
|
81
81
|
if (c && c.length > 0) ret.push(c);
|
|
82
|
+
if (c === "tab-number") // TODO-PER-HACK! straighten out the tablature
|
|
83
|
+
return ret.join(' ')
|
|
84
|
+
if (c === "text instrument-name")
|
|
85
|
+
return "abcjs-text abcjs-instrument-name"
|
|
82
86
|
if (this.lineNumber !== null) ret.push("l"+this.lineNumber);
|
|
83
87
|
if (this.measureNumber !== null) ret.push("m"+this.measureNumber);
|
|
84
88
|
if (this.measureNumber !== null) ret.push("mm"+this.measureTotal()); // measureNumber is null between measures so this is still the test for measureTotal
|
|
@@ -32,6 +32,14 @@ function drawAbsolute(renderer, params, bartop, selectables, staffPos) {
|
|
|
32
32
|
}
|
|
33
33
|
var g = elementGroup.endGroup(klass, params.type);
|
|
34
34
|
if (g) {
|
|
35
|
+
// TODO-PER-HACK! This corrects the classes because the tablature is not being created at the right time.
|
|
36
|
+
if (params.cloned) {
|
|
37
|
+
params.cloned.overrideClasses = g.className.baseVal
|
|
38
|
+
}
|
|
39
|
+
if (params.overrideClasses) {
|
|
40
|
+
var type = g.classList && g.classList.length > 0 ? g.classList[0] + ' ' : ''
|
|
41
|
+
g.setAttribute("class", type + params.overrideClasses)
|
|
42
|
+
}
|
|
35
43
|
if (isTempo) {
|
|
36
44
|
params.startChar = params.abcelem.startChar;
|
|
37
45
|
params.endChar = params.abcelem.endChar;
|
package/src/write/selection.js
CHANGED
|
@@ -357,10 +357,10 @@ function notifySelect(target, dragStep, dragMax, dragIndex, ev) {
|
|
|
357
357
|
if (target.staffPos)
|
|
358
358
|
analysis.staffPos = target.staffPos;
|
|
359
359
|
var closest = ev.target;
|
|
360
|
-
while (closest && !closest.dataset.name && closest.tagName.toLowerCase() !== 'svg')
|
|
360
|
+
while (closest && closest.dataset && !closest.dataset.name && closest.tagName.toLowerCase() !== 'svg')
|
|
361
361
|
closest = closest.parentNode;
|
|
362
362
|
var parent = ev.target;
|
|
363
|
-
while (parent && !parent.dataset.index && parent.tagName.toLowerCase() !== 'svg')
|
|
363
|
+
while (parent && parent.dataset && !parent.dataset.index && parent.tagName.toLowerCase() !== 'svg')
|
|
364
364
|
parent = parent.parentNode;
|
|
365
365
|
analysis.name = parent.dataset.name;
|
|
366
366
|
analysis.clickedName = closest.dataset.name;
|
package/version.js
CHANGED