musicxml-io 0.2.12 → 0.3.1
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/dist/{index-DkvcsWdo.d.ts → index-C1gu_fLF.d.ts} +1 -1
- package/dist/{index-DPW0wqXK.d.mts → index-Dy4LmZRQ.d.mts} +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +552 -263
- package/dist/index.mjs +552 -263
- package/dist/operations/index.d.mts +2 -2
- package/dist/operations/index.d.ts +2 -2
- package/dist/operations/index.js +7 -4
- package/dist/operations/index.mjs +7 -4
- package/dist/query/index.d.mts +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +7 -6
- package/dist/query/index.mjs +7 -6
- package/dist/{types-JohtsbUB.d.mts → types-D0G3_ykl.d.mts} +63 -9
- package/dist/{types-JohtsbUB.d.ts → types-D0G3_ykl.d.ts} +63 -9
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -19,11 +19,22 @@ var xmlParser = new XMLParser({
|
|
|
19
19
|
});
|
|
20
20
|
function parse(xmlString) {
|
|
21
21
|
const parsed = xmlParser.parse(xmlString);
|
|
22
|
-
|
|
22
|
+
let scorePartwiseVersion;
|
|
23
|
+
let scorePartwise;
|
|
24
|
+
for (const el of parsed) {
|
|
25
|
+
if (el["score-partwise"]) {
|
|
26
|
+
scorePartwise = el["score-partwise"];
|
|
27
|
+
const attrs = getAttributes(el);
|
|
28
|
+
if (attrs["version"]) scorePartwiseVersion = attrs["version"];
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
if (!scorePartwise) {
|
|
24
33
|
throw new Error("Unsupported MusicXML format: only score-partwise is supported");
|
|
25
34
|
}
|
|
26
|
-
|
|
35
|
+
const score = parseScorePartwise(scorePartwise);
|
|
36
|
+
if (scorePartwiseVersion) score.version = scorePartwiseVersion;
|
|
37
|
+
return score;
|
|
27
38
|
}
|
|
28
39
|
function findElement(elements, tagName) {
|
|
29
40
|
for (const el of elements) {
|
|
@@ -241,9 +252,11 @@ function parseDefaults(elements) {
|
|
|
241
252
|
const lineWidths = collectElements(appContent, "line-width", (c, a) => ({ type: a["type"] || "", value: parseFloat(extractText(c)) || 0 }));
|
|
242
253
|
const noteSizes = collectElements(appContent, "note-size", (c, a) => ({ type: a["type"] || "", value: parseFloat(extractText(c)) || 0 }));
|
|
243
254
|
const distances = collectElements(appContent, "distance", (c, a) => ({ type: a["type"] || "", value: parseFloat(extractText(c)) || 0 }));
|
|
255
|
+
const glyphs = collectElements(appContent, "glyph", (c, a) => ({ type: a["type"] || "", value: extractText(c) }));
|
|
244
256
|
if (lineWidths.length > 0) appearance["line-widths"] = lineWidths;
|
|
245
257
|
if (noteSizes.length > 0) appearance["note-sizes"] = noteSizes;
|
|
246
258
|
if (distances.length > 0) appearance["distances"] = distances;
|
|
259
|
+
if (glyphs.length > 0) appearance["glyphs"] = glyphs;
|
|
247
260
|
return Object.keys(appearance).length > 0 ? appearance : void 0;
|
|
248
261
|
});
|
|
249
262
|
if (appResult) defaults.appearance = appResult;
|
|
@@ -265,13 +278,25 @@ function parsePageLayout(elements) {
|
|
|
265
278
|
m.type = attrs["type"];
|
|
266
279
|
}
|
|
267
280
|
const left = getElementText(content, "left-margin");
|
|
268
|
-
if (left)
|
|
281
|
+
if (left) {
|
|
282
|
+
m.leftMargin = parseFloat(left);
|
|
283
|
+
m.leftMarginRaw = left;
|
|
284
|
+
}
|
|
269
285
|
const right = getElementText(content, "right-margin");
|
|
270
|
-
if (right)
|
|
286
|
+
if (right) {
|
|
287
|
+
m.rightMargin = parseFloat(right);
|
|
288
|
+
m.rightMarginRaw = right;
|
|
289
|
+
}
|
|
271
290
|
const top = getElementText(content, "top-margin");
|
|
272
|
-
if (top)
|
|
291
|
+
if (top) {
|
|
292
|
+
m.topMargin = parseFloat(top);
|
|
293
|
+
m.topMarginRaw = top;
|
|
294
|
+
}
|
|
273
295
|
const bottom = getElementText(content, "bottom-margin");
|
|
274
|
-
if (bottom)
|
|
296
|
+
if (bottom) {
|
|
297
|
+
m.bottomMargin = parseFloat(bottom);
|
|
298
|
+
m.bottomMarginRaw = bottom;
|
|
299
|
+
}
|
|
275
300
|
margins.push(m);
|
|
276
301
|
}
|
|
277
302
|
}
|
|
@@ -284,14 +309,48 @@ function parseSystemLayout(elements) {
|
|
|
284
309
|
if (margins) {
|
|
285
310
|
layout.systemMargins = {};
|
|
286
311
|
const left = getElementText(margins, "left-margin");
|
|
287
|
-
if (left)
|
|
312
|
+
if (left) {
|
|
313
|
+
layout.systemMargins.leftMargin = parseFloat(left);
|
|
314
|
+
layout.systemMargins.leftMarginRaw = left;
|
|
315
|
+
}
|
|
288
316
|
const right = getElementText(margins, "right-margin");
|
|
289
|
-
if (right)
|
|
317
|
+
if (right) {
|
|
318
|
+
layout.systemMargins.rightMargin = parseFloat(right);
|
|
319
|
+
layout.systemMargins.rightMarginRaw = right;
|
|
320
|
+
}
|
|
290
321
|
}
|
|
291
322
|
const dist = getElementText(elements, "system-distance");
|
|
292
|
-
if (dist)
|
|
323
|
+
if (dist) {
|
|
324
|
+
layout.systemDistance = parseFloat(dist);
|
|
325
|
+
layout.systemDistanceRaw = dist;
|
|
326
|
+
}
|
|
293
327
|
const topDist = getElementText(elements, "top-system-distance");
|
|
294
|
-
if (topDist)
|
|
328
|
+
if (topDist) {
|
|
329
|
+
layout.topSystemDistance = parseFloat(topDist);
|
|
330
|
+
layout.topSystemDistanceRaw = topDist;
|
|
331
|
+
}
|
|
332
|
+
const dividers = getElementContent(elements, "system-dividers");
|
|
333
|
+
if (dividers) {
|
|
334
|
+
layout.systemDividers = {};
|
|
335
|
+
for (const el of dividers) {
|
|
336
|
+
if (el["left-divider"]) {
|
|
337
|
+
const attrs = getAttributes(el);
|
|
338
|
+
layout.systemDividers.leftDivider = {
|
|
339
|
+
printObject: attrs["print-object"] === "yes" ? true : attrs["print-object"] === "no" ? false : void 0,
|
|
340
|
+
halign: attrs["halign"],
|
|
341
|
+
valign: attrs["valign"]
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
if (el["right-divider"]) {
|
|
345
|
+
const attrs = getAttributes(el);
|
|
346
|
+
layout.systemDividers.rightDivider = {
|
|
347
|
+
printObject: attrs["print-object"] === "yes" ? true : attrs["print-object"] === "no" ? false : void 0,
|
|
348
|
+
halign: attrs["halign"],
|
|
349
|
+
valign: attrs["valign"]
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
295
354
|
return layout;
|
|
296
355
|
}
|
|
297
356
|
function parseCredits(elements) {
|
|
@@ -303,6 +362,7 @@ function parseCredits(elements) {
|
|
|
303
362
|
const cw = { text: extractText(c) };
|
|
304
363
|
if (a["default-x"]) cw.defaultX = parseFloat(a["default-x"]);
|
|
305
364
|
if (a["default-y"]) cw.defaultY = parseFloat(a["default-y"]);
|
|
365
|
+
if (a["font-family"]) cw.fontFamily = a["font-family"];
|
|
306
366
|
if (a["font-size"]) cw.fontSize = a["font-size"];
|
|
307
367
|
if (a["font-weight"]) cw.fontWeight = a["font-weight"];
|
|
308
368
|
if (a["font-style"]) cw.fontStyle = a["font-style"];
|
|
@@ -526,6 +586,15 @@ function parseMeasure(elements, attrs) {
|
|
|
526
586
|
measure.entries.push(parseFiguredBass(el["figured-bass"], getAttributes(el)));
|
|
527
587
|
} else if (el["sound"]) {
|
|
528
588
|
measure.entries.push(parseSound(el["sound"], getAttributes(el)));
|
|
589
|
+
} else if (el["grouping"] !== void 0) {
|
|
590
|
+
const grpAttrs = getAttributes(el);
|
|
591
|
+
const grouping = {
|
|
592
|
+
_id: generateId(),
|
|
593
|
+
type: "grouping",
|
|
594
|
+
groupingType: grpAttrs["type"] || "start"
|
|
595
|
+
};
|
|
596
|
+
if (grpAttrs["number"]) grouping.number = grpAttrs["number"];
|
|
597
|
+
measure.entries.push(grouping);
|
|
529
598
|
}
|
|
530
599
|
}
|
|
531
600
|
if (barlines.length > 0) measure.barlines = barlines;
|
|
@@ -592,6 +661,7 @@ function parseAttributes(elements) {
|
|
|
592
661
|
const key = parseKeySignature(keyContent);
|
|
593
662
|
if (keyAttrs["number"]) key.number = parseInt(keyAttrs["number"], 10);
|
|
594
663
|
if (keyAttrs["print-object"] === "no") key.printObject = false;
|
|
664
|
+
else if (keyAttrs["print-object"] === "yes") key.printObject = true;
|
|
595
665
|
keys.push(key);
|
|
596
666
|
}
|
|
597
667
|
}
|
|
@@ -643,14 +713,15 @@ function parseTimeSignature(elements, parentElements) {
|
|
|
643
713
|
return time2;
|
|
644
714
|
}
|
|
645
715
|
}
|
|
646
|
-
const
|
|
716
|
+
const beatsStrList = collectElements(elements, "beats", (c) => extractText(c));
|
|
647
717
|
const beatTypeList = collectElements(elements, "beat-type", (c) => parseInt(extractText(c), 10));
|
|
648
718
|
const time = {
|
|
649
|
-
beats:
|
|
719
|
+
beats: beatsStrList.length > 0 ? beatsStrList[0] : "4",
|
|
650
720
|
beatType: beatTypeList.length > 0 ? beatTypeList[0] : 4
|
|
651
721
|
};
|
|
652
|
-
if (
|
|
653
|
-
time.beatsList =
|
|
722
|
+
if (beatsStrList.length > 1 || beatTypeList.length > 1) {
|
|
723
|
+
time.beatsList = beatsStrList.map((b) => parseInt(b, 10));
|
|
724
|
+
time.beatsStrList = beatsStrList;
|
|
654
725
|
time.beatTypeList = beatTypeList;
|
|
655
726
|
}
|
|
656
727
|
for (const el of parentElements) {
|
|
@@ -689,6 +760,7 @@ function parseKeySignature(elements) {
|
|
|
689
760
|
const keyOctaves = collectElements(elements, "key-octave", (c, a) => {
|
|
690
761
|
const ko = { number: parseInt(a["number"] || "1", 10), octave: parseInt(extractText(c), 10) };
|
|
691
762
|
if (a["cancel"] === "yes") ko.cancel = true;
|
|
763
|
+
else if (a["cancel"] === "no") ko.cancel = false;
|
|
692
764
|
return ko;
|
|
693
765
|
});
|
|
694
766
|
if (keySteps.length > 0) key.keySteps = keySteps;
|
|
@@ -698,8 +770,11 @@ function parseKeySignature(elements) {
|
|
|
698
770
|
}
|
|
699
771
|
function parseClef(elements, attrs) {
|
|
700
772
|
const sign = getElementText(elements, "sign") || "G";
|
|
701
|
-
const
|
|
702
|
-
const clef = { sign
|
|
773
|
+
const lineText = getElementText(elements, "line");
|
|
774
|
+
const clef = { sign };
|
|
775
|
+
if (lineText) {
|
|
776
|
+
clef.line = parseInt(lineText, 10);
|
|
777
|
+
}
|
|
703
778
|
if (attrs["number"]) {
|
|
704
779
|
clef.staff = parseInt(attrs["number"], 10);
|
|
705
780
|
}
|
|
@@ -709,6 +784,8 @@ function parseClef(elements, attrs) {
|
|
|
709
784
|
}
|
|
710
785
|
if (attrs["print-object"] === "no") {
|
|
711
786
|
clef.printObject = false;
|
|
787
|
+
} else if (attrs["print-object"] === "yes") {
|
|
788
|
+
clef.printObject = true;
|
|
712
789
|
}
|
|
713
790
|
if (attrs["after-barline"] === "yes") {
|
|
714
791
|
clef.afterBarline = true;
|
|
@@ -730,15 +807,20 @@ function parseNote(elements, attrs) {
|
|
|
730
807
|
const note = {
|
|
731
808
|
_id: generateId(),
|
|
732
809
|
type: "note",
|
|
733
|
-
duration: getElementTextAsInt(elements, "duration", 0)
|
|
734
|
-
voice: getElementTextAsInt(elements, "voice", 1)
|
|
810
|
+
duration: getElementTextAsInt(elements, "duration", 0)
|
|
735
811
|
};
|
|
812
|
+
const voiceValue = getElementTextAsInt(elements, "voice");
|
|
813
|
+
if (voiceValue !== void 0) {
|
|
814
|
+
note.voice = voiceValue;
|
|
815
|
+
}
|
|
736
816
|
if (attrs["default-x"]) note.defaultX = parseFloat(attrs["default-x"]);
|
|
737
817
|
if (attrs["default-y"]) note.defaultY = parseFloat(attrs["default-y"]);
|
|
738
818
|
if (attrs["relative-x"]) note.relativeX = parseFloat(attrs["relative-x"]);
|
|
739
819
|
if (attrs["relative-y"]) note.relativeY = parseFloat(attrs["relative-y"]);
|
|
740
820
|
if (attrs["dynamics"]) note.dynamics = parseFloat(attrs["dynamics"]);
|
|
741
821
|
if (attrs["print-object"] === "no") note.printObject = false;
|
|
822
|
+
if (attrs["print-dot"] === "no") note.printDot = false;
|
|
823
|
+
if (attrs["print-dot"] === "yes") note.printDot = true;
|
|
742
824
|
if (attrs["print-spacing"] === "yes") note.printSpacing = true;
|
|
743
825
|
if (attrs["print-spacing"] === "no") note.printSpacing = false;
|
|
744
826
|
if (hasElement(elements, "cue")) {
|
|
@@ -851,6 +933,7 @@ function parseNote(elements, attrs) {
|
|
|
851
933
|
const graceAttrs = getAttributes(el);
|
|
852
934
|
note.grace = {};
|
|
853
935
|
if (graceAttrs["slash"] === "yes") note.grace.slash = true;
|
|
936
|
+
else if (graceAttrs["slash"] === "no") note.grace.slash = false;
|
|
854
937
|
if (graceAttrs["steal-time-previous"]) {
|
|
855
938
|
note.grace.stealTimePrevious = parseFloat(graceAttrs["steal-time-previous"]);
|
|
856
939
|
}
|
|
@@ -1096,6 +1179,14 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1096
1179
|
notations.push(tremNotation);
|
|
1097
1180
|
}
|
|
1098
1181
|
}
|
|
1182
|
+
const ornamentNotationsAdded = notations.filter((n) => n.type === "ornament" && n.notationsIndex === notationsIndex);
|
|
1183
|
+
if (ornamentNotationsAdded.length === 0) {
|
|
1184
|
+
notations.push({
|
|
1185
|
+
type: "ornament",
|
|
1186
|
+
ornament: "empty",
|
|
1187
|
+
notationsIndex
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1099
1190
|
} else if (el["technical"]) {
|
|
1100
1191
|
const techContent = el["technical"];
|
|
1101
1192
|
const technicalWithText = ["hammer-on", "pull-off", "tap", "pluck", "fingering", "other-technical"];
|
|
@@ -1145,8 +1236,7 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1145
1236
|
if (bendAlter) techNotation.bendAlter = parseFloat(bendAlter);
|
|
1146
1237
|
if (hasElement(bendContent, "pre-bend")) techNotation.preBend = true;
|
|
1147
1238
|
if (hasElement(bendContent, "release")) techNotation.release = true;
|
|
1148
|
-
|
|
1149
|
-
if (withBar) techNotation.withBar = parseFloat(withBar);
|
|
1239
|
+
if (hasElement(bendContent, "with-bar")) techNotation.withBar = true;
|
|
1150
1240
|
notations.push(techNotation);
|
|
1151
1241
|
}
|
|
1152
1242
|
for (const techType of technicalTypes) {
|
|
@@ -1183,6 +1273,7 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1183
1273
|
if (typeAttr === "start" || typeAttr === "stop") {
|
|
1184
1274
|
notation.startStop = typeAttr;
|
|
1185
1275
|
}
|
|
1276
|
+
if (techAttrs["number"]) notation.number = parseInt(techAttrs["number"], 10);
|
|
1186
1277
|
}
|
|
1187
1278
|
if (techType === "fingering") {
|
|
1188
1279
|
if (techAttrs["substitution"] === "yes") notation.fingeringSubstitution = true;
|
|
@@ -1265,11 +1356,33 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1265
1356
|
notations.push(fermataNotation);
|
|
1266
1357
|
} else if (el["arpeggiate"] !== void 0) {
|
|
1267
1358
|
const arpAttrs = getAttributes(el);
|
|
1268
|
-
|
|
1359
|
+
const arpNotation = {
|
|
1269
1360
|
type: "arpeggiate",
|
|
1270
1361
|
direction: arpAttrs["direction"],
|
|
1271
1362
|
number: arpAttrs["number"] ? parseInt(arpAttrs["number"], 10) : void 0,
|
|
1272
1363
|
notationsIndex
|
|
1364
|
+
};
|
|
1365
|
+
if (arpAttrs["default-x"]) arpNotation.defaultX = parseFloat(arpAttrs["default-x"]);
|
|
1366
|
+
if (arpAttrs["default-y"]) arpNotation.defaultY = parseFloat(arpAttrs["default-y"]);
|
|
1367
|
+
notations.push(arpNotation);
|
|
1368
|
+
} else if (el["non-arpeggiate"] !== void 0) {
|
|
1369
|
+
const nonArpAttrs = getAttributes(el);
|
|
1370
|
+
notations.push({
|
|
1371
|
+
type: "non-arpeggiate",
|
|
1372
|
+
nonArpeggiateType: nonArpAttrs["type"],
|
|
1373
|
+
number: nonArpAttrs["number"] ? parseInt(nonArpAttrs["number"], 10) : void 0,
|
|
1374
|
+
placement: nonArpAttrs["placement"],
|
|
1375
|
+
notationsIndex
|
|
1376
|
+
});
|
|
1377
|
+
} else if (el["accidental-mark"]) {
|
|
1378
|
+
const amAttrs = getAttributes(el);
|
|
1379
|
+
const amContent = el["accidental-mark"];
|
|
1380
|
+
const value = extractText(amContent);
|
|
1381
|
+
notations.push({
|
|
1382
|
+
type: "accidental-mark",
|
|
1383
|
+
value,
|
|
1384
|
+
placement: amAttrs["placement"],
|
|
1385
|
+
notationsIndex
|
|
1273
1386
|
});
|
|
1274
1387
|
} else if (el["glissando"]) {
|
|
1275
1388
|
const glissAttrs = getAttributes(el);
|
|
@@ -1291,13 +1404,17 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1291
1404
|
});
|
|
1292
1405
|
} else if (el["slide"]) {
|
|
1293
1406
|
const slideAttrs = getAttributes(el);
|
|
1294
|
-
|
|
1407
|
+
const slideContent = el["slide"];
|
|
1408
|
+
const slideText = extractText(slideContent);
|
|
1409
|
+
const slideNotation = {
|
|
1295
1410
|
type: "slide",
|
|
1296
1411
|
slideType: slideAttrs["type"] === "stop" ? "stop" : "start",
|
|
1297
1412
|
number: slideAttrs["number"] ? parseInt(slideAttrs["number"], 10) : void 0,
|
|
1298
1413
|
lineType: slideAttrs["line-type"],
|
|
1299
1414
|
notationsIndex
|
|
1300
|
-
}
|
|
1415
|
+
};
|
|
1416
|
+
if (slideText) slideNotation.text = slideText;
|
|
1417
|
+
notations.push(slideNotation);
|
|
1301
1418
|
}
|
|
1302
1419
|
}
|
|
1303
1420
|
return notations;
|
|
@@ -1318,8 +1435,9 @@ function parseLyric(elements, attrs) {
|
|
|
1318
1435
|
break;
|
|
1319
1436
|
}
|
|
1320
1437
|
}
|
|
1321
|
-
} else if (el["text"]) {
|
|
1438
|
+
} else if (el["text"] !== void 0) {
|
|
1322
1439
|
const content = el["text"];
|
|
1440
|
+
let foundText = false;
|
|
1323
1441
|
for (const item of content) {
|
|
1324
1442
|
if (item["#text"] !== void 0) {
|
|
1325
1443
|
textElements.push({
|
|
@@ -1327,9 +1445,17 @@ function parseLyric(elements, attrs) {
|
|
|
1327
1445
|
syllabic: currentSyllabic
|
|
1328
1446
|
});
|
|
1329
1447
|
currentSyllabic = void 0;
|
|
1448
|
+
foundText = true;
|
|
1330
1449
|
break;
|
|
1331
1450
|
}
|
|
1332
1451
|
}
|
|
1452
|
+
if (!foundText) {
|
|
1453
|
+
textElements.push({
|
|
1454
|
+
text: "",
|
|
1455
|
+
syllabic: currentSyllabic
|
|
1456
|
+
});
|
|
1457
|
+
currentSyllabic = void 0;
|
|
1458
|
+
}
|
|
1333
1459
|
} else if (el["elision"] !== void 0) {
|
|
1334
1460
|
hasElision = true;
|
|
1335
1461
|
}
|
|
@@ -1498,6 +1624,7 @@ function parseDirectionTypes(elements) {
|
|
|
1498
1624
|
"pf"
|
|
1499
1625
|
];
|
|
1500
1626
|
for (const dyn of dynContent) {
|
|
1627
|
+
let foundStandard = false;
|
|
1501
1628
|
for (const dv of dynamicsValues) {
|
|
1502
1629
|
if (dyn[dv] !== void 0) {
|
|
1503
1630
|
const result = { kind: "dynamics", value: dv };
|
|
@@ -1506,9 +1633,22 @@ function parseDirectionTypes(elements) {
|
|
|
1506
1633
|
if (dynAttrs["relative-x"]) result.relativeX = parseFloat(dynAttrs["relative-x"]);
|
|
1507
1634
|
if (dynAttrs["halign"]) result.halign = dynAttrs["halign"];
|
|
1508
1635
|
results.push(result);
|
|
1636
|
+
foundStandard = true;
|
|
1509
1637
|
break;
|
|
1510
1638
|
}
|
|
1511
1639
|
}
|
|
1640
|
+
if (!foundStandard && dyn["other-dynamics"] !== void 0) {
|
|
1641
|
+
const otherDynContent = dyn["other-dynamics"];
|
|
1642
|
+
const otherDynText = extractText(otherDynContent);
|
|
1643
|
+
if (otherDynText) {
|
|
1644
|
+
const result = { kind: "dynamics", otherDynamics: otherDynText };
|
|
1645
|
+
if (dynAttrs["default-x"]) result.defaultX = parseFloat(dynAttrs["default-x"]);
|
|
1646
|
+
if (dynAttrs["default-y"]) result.defaultY = parseFloat(dynAttrs["default-y"]);
|
|
1647
|
+
if (dynAttrs["relative-x"]) result.relativeX = parseFloat(dynAttrs["relative-x"]);
|
|
1648
|
+
if (dynAttrs["halign"]) result.halign = dynAttrs["halign"];
|
|
1649
|
+
results.push(result);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1512
1652
|
}
|
|
1513
1653
|
continue;
|
|
1514
1654
|
}
|
|
@@ -1633,11 +1773,14 @@ function parseDirectionTypes(elements) {
|
|
|
1633
1773
|
for (const acc of accContent) {
|
|
1634
1774
|
if (acc["accordion-high"] !== void 0) {
|
|
1635
1775
|
result.high = true;
|
|
1636
|
-
} else if (acc["accordion-middle"]) {
|
|
1776
|
+
} else if (acc["accordion-middle"] !== void 0) {
|
|
1777
|
+
result.middlePresent = true;
|
|
1637
1778
|
const midContent = acc["accordion-middle"];
|
|
1638
1779
|
for (const item of midContent) {
|
|
1639
1780
|
if (item["#text"] !== void 0) {
|
|
1640
|
-
|
|
1781
|
+
const textValue = String(item["#text"]);
|
|
1782
|
+
const numValue = parseInt(textValue, 10);
|
|
1783
|
+
result.middle = !isNaN(numValue) ? numValue : textValue;
|
|
1641
1784
|
break;
|
|
1642
1785
|
}
|
|
1643
1786
|
}
|
|
@@ -1814,6 +1957,9 @@ function parseBarline(elements, attrs) {
|
|
|
1814
1957
|
if (repeatAttrs["times"]) {
|
|
1815
1958
|
barline.repeat.times = parseInt(repeatAttrs["times"], 10);
|
|
1816
1959
|
}
|
|
1960
|
+
if (repeatAttrs["winged"]) {
|
|
1961
|
+
barline.repeat.winged = repeatAttrs["winged"];
|
|
1962
|
+
}
|
|
1817
1963
|
}
|
|
1818
1964
|
} else if (el["ending"]) {
|
|
1819
1965
|
const endingAttrs = getAttributes(el);
|
|
@@ -1821,6 +1967,11 @@ function parseBarline(elements, attrs) {
|
|
|
1821
1967
|
const type = endingAttrs["type"];
|
|
1822
1968
|
if (number && (type === "start" || type === "stop" || type === "discontinue")) {
|
|
1823
1969
|
barline.ending = { number, type };
|
|
1970
|
+
const endingContent = el["ending"];
|
|
1971
|
+
const endingText = extractText(endingContent);
|
|
1972
|
+
if (endingText) barline.ending.text = endingText;
|
|
1973
|
+
if (endingAttrs["default-y"]) barline.ending.defaultY = parseFloat(endingAttrs["default-y"]);
|
|
1974
|
+
if (endingAttrs["end-length"]) barline.ending.endLength = parseFloat(endingAttrs["end-length"]);
|
|
1824
1975
|
}
|
|
1825
1976
|
}
|
|
1826
1977
|
}
|
|
@@ -1946,6 +2097,8 @@ function parseStaffDetails(elements, attrs) {
|
|
|
1946
2097
|
if (attrs["number"]) sd.number = parseInt(attrs["number"], 10);
|
|
1947
2098
|
if (attrs["print-object"] === "no") sd.printObject = false;
|
|
1948
2099
|
else if (attrs["print-object"] === "yes") sd.printObject = true;
|
|
2100
|
+
if (attrs["print-spacing"] === "yes") sd.printSpacing = true;
|
|
2101
|
+
else if (attrs["print-spacing"] === "no") sd.printSpacing = false;
|
|
1949
2102
|
const staffType = getElementText(elements, "staff-type");
|
|
1950
2103
|
if (staffType && ["ossia", "cue", "editorial", "regular", "alternate"].includes(staffType)) {
|
|
1951
2104
|
sd.staffType = staffType;
|
|
@@ -2009,7 +2162,9 @@ function parseMeasureStyle(elements, attrs) {
|
|
|
2009
2162
|
const slAttrs = getAttributes(el);
|
|
2010
2163
|
ms.slash = { type: slAttrs["type"] === "stop" ? "stop" : "start" };
|
|
2011
2164
|
if (slAttrs["use-dots"] === "yes") ms.slash.useDots = true;
|
|
2165
|
+
else if (slAttrs["use-dots"] === "no") ms.slash.useDots = false;
|
|
2012
2166
|
if (slAttrs["use-stems"] === "yes") ms.slash.useStems = true;
|
|
2167
|
+
else if (slAttrs["use-stems"] === "no") ms.slash.useStems = false;
|
|
2013
2168
|
}
|
|
2014
2169
|
}
|
|
2015
2170
|
return ms;
|
|
@@ -2049,19 +2204,29 @@ function parseHarmony(elements, attrs) {
|
|
|
2049
2204
|
break;
|
|
2050
2205
|
}
|
|
2051
2206
|
}
|
|
2052
|
-
if (kindAttrs["text"]) harmony.kindText = kindAttrs["text"];
|
|
2207
|
+
if (kindAttrs["text"] !== void 0) harmony.kindText = kindAttrs["text"];
|
|
2208
|
+
if (kindAttrs["halign"]) harmony.kindHalign = kindAttrs["halign"];
|
|
2053
2209
|
break;
|
|
2054
2210
|
}
|
|
2055
2211
|
}
|
|
2056
|
-
const
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2212
|
+
for (const el of elements) {
|
|
2213
|
+
if (el["bass"]) {
|
|
2214
|
+
const bassAttrs = getAttributes(el);
|
|
2215
|
+
const bassContent = el["bass"];
|
|
2216
|
+
const bassStep = getElementText(bassContent, "bass-step");
|
|
2217
|
+
if (bassStep) {
|
|
2218
|
+
harmony.bass = { bassStep };
|
|
2219
|
+
const bassAlter = getElementText(bassContent, "bass-alter");
|
|
2220
|
+
if (bassAlter) harmony.bass.bassAlter = parseFloat(bassAlter);
|
|
2221
|
+
if (bassAttrs["arrangement"]) harmony.bass.arrangement = bassAttrs["arrangement"];
|
|
2222
|
+
}
|
|
2223
|
+
break;
|
|
2063
2224
|
}
|
|
2064
2225
|
}
|
|
2226
|
+
const inversionText = getElementText(elements, "inversion");
|
|
2227
|
+
if (inversionText) {
|
|
2228
|
+
harmony.inversion = parseInt(inversionText, 10);
|
|
2229
|
+
}
|
|
2065
2230
|
const degrees = [];
|
|
2066
2231
|
for (const el of elements) {
|
|
2067
2232
|
if (el["degree"]) {
|
|
@@ -2828,7 +2993,7 @@ function validateVoiceStaff(measure, staves, location) {
|
|
|
2828
2993
|
for (let entryIndex = 0; entryIndex < measure.entries.length; entryIndex++) {
|
|
2829
2994
|
const entry = measure.entries[entryIndex];
|
|
2830
2995
|
if (entry.type !== "note") continue;
|
|
2831
|
-
if (entry.voice <= 0) {
|
|
2996
|
+
if (entry.voice !== void 0 && entry.voice <= 0) {
|
|
2832
2997
|
errors.push({
|
|
2833
2998
|
code: "INVALID_VOICE_NUMBER",
|
|
2834
2999
|
level: "error",
|
|
@@ -3324,7 +3489,7 @@ function validateSlursAcrossMeasures(part) {
|
|
|
3324
3489
|
|
|
3325
3490
|
// src/exporters/musicxml.ts
|
|
3326
3491
|
function serialize(score, options = {}) {
|
|
3327
|
-
const version = options.version || "4.0";
|
|
3492
|
+
const version = options.version || score.version || "4.0";
|
|
3328
3493
|
const indent = options.indent ?? " ";
|
|
3329
3494
|
if (options.validate) {
|
|
3330
3495
|
const result = validate(score, options.validateOptions);
|
|
@@ -3339,11 +3504,7 @@ ${errorMessages}`);
|
|
|
3339
3504
|
}
|
|
3340
3505
|
const lines = [];
|
|
3341
3506
|
lines.push('<?xml version="1.0" encoding="UTF-8"?>');
|
|
3342
|
-
|
|
3343
|
-
lines.push('<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 4.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">');
|
|
3344
|
-
} else {
|
|
3345
|
-
lines.push('<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">');
|
|
3346
|
-
}
|
|
3507
|
+
lines.push(`<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML ${version} Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">`);
|
|
3347
3508
|
lines.push(`<score-partwise version="${version}">`);
|
|
3348
3509
|
lines.push(...serializeMetadata(score.metadata, indent));
|
|
3349
3510
|
if (score.defaults) {
|
|
@@ -3477,6 +3638,11 @@ function serializeDefaults(defaults, indent) {
|
|
|
3477
3638
|
lines.push(`${indent}${indent}${indent}<distance type="${escapeXml(d.type)}">${d.value}</distance>`);
|
|
3478
3639
|
}
|
|
3479
3640
|
}
|
|
3641
|
+
if (app["glyphs"]) {
|
|
3642
|
+
for (const g of app["glyphs"]) {
|
|
3643
|
+
lines.push(`${indent}${indent}${indent}<glyph type="${escapeXml(g.type)}">${escapeXml(g.value)}</glyph>`);
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3480
3646
|
lines.push(`${indent}${indent}</appearance>`);
|
|
3481
3647
|
}
|
|
3482
3648
|
if (defaults.musicFont) {
|
|
@@ -3533,16 +3699,16 @@ function serializePageLayout(layout, indent) {
|
|
|
3533
3699
|
const typeAttr = m.type ? ` type="${m.type}"` : "";
|
|
3534
3700
|
lines.push(`${indent} <page-margins${typeAttr}>`);
|
|
3535
3701
|
if (m.leftMargin !== void 0) {
|
|
3536
|
-
lines.push(`${indent} <left-margin>${m.leftMargin}</left-margin>`);
|
|
3702
|
+
lines.push(`${indent} <left-margin>${m.leftMarginRaw ?? m.leftMargin}</left-margin>`);
|
|
3537
3703
|
}
|
|
3538
3704
|
if (m.rightMargin !== void 0) {
|
|
3539
|
-
lines.push(`${indent} <right-margin>${m.rightMargin}</right-margin>`);
|
|
3705
|
+
lines.push(`${indent} <right-margin>${m.rightMarginRaw ?? m.rightMargin}</right-margin>`);
|
|
3540
3706
|
}
|
|
3541
3707
|
if (m.topMargin !== void 0) {
|
|
3542
|
-
lines.push(`${indent} <top-margin>${m.topMargin}</top-margin>`);
|
|
3708
|
+
lines.push(`${indent} <top-margin>${m.topMarginRaw ?? m.topMargin}</top-margin>`);
|
|
3543
3709
|
}
|
|
3544
3710
|
if (m.bottomMargin !== void 0) {
|
|
3545
|
-
lines.push(`${indent} <bottom-margin>${m.bottomMargin}</bottom-margin>`);
|
|
3711
|
+
lines.push(`${indent} <bottom-margin>${m.bottomMarginRaw ?? m.bottomMargin}</bottom-margin>`);
|
|
3546
3712
|
}
|
|
3547
3713
|
lines.push(`${indent} </page-margins>`);
|
|
3548
3714
|
}
|
|
@@ -3556,18 +3722,48 @@ function serializeSystemLayout(layout, indent) {
|
|
|
3556
3722
|
if (layout.systemMargins) {
|
|
3557
3723
|
lines.push(`${indent} <system-margins>`);
|
|
3558
3724
|
if (layout.systemMargins.leftMargin !== void 0) {
|
|
3559
|
-
lines.push(`${indent} <left-margin>${layout.systemMargins.leftMargin}</left-margin>`);
|
|
3725
|
+
lines.push(`${indent} <left-margin>${layout.systemMargins.leftMarginRaw ?? layout.systemMargins.leftMargin}</left-margin>`);
|
|
3560
3726
|
}
|
|
3561
3727
|
if (layout.systemMargins.rightMargin !== void 0) {
|
|
3562
|
-
lines.push(`${indent} <right-margin>${layout.systemMargins.rightMargin}</right-margin>`);
|
|
3728
|
+
lines.push(`${indent} <right-margin>${layout.systemMargins.rightMarginRaw ?? layout.systemMargins.rightMargin}</right-margin>`);
|
|
3563
3729
|
}
|
|
3564
3730
|
lines.push(`${indent} </system-margins>`);
|
|
3565
3731
|
}
|
|
3566
3732
|
if (layout.systemDistance !== void 0) {
|
|
3567
|
-
lines.push(`${indent} <system-distance>${layout.systemDistance}</system-distance>`);
|
|
3733
|
+
lines.push(`${indent} <system-distance>${layout.systemDistanceRaw ?? layout.systemDistance}</system-distance>`);
|
|
3568
3734
|
}
|
|
3569
3735
|
if (layout.topSystemDistance !== void 0) {
|
|
3570
|
-
lines.push(`${indent} <top-system-distance>${layout.topSystemDistance}</top-system-distance>`);
|
|
3736
|
+
lines.push(`${indent} <top-system-distance>${layout.topSystemDistanceRaw ?? layout.topSystemDistance}</top-system-distance>`);
|
|
3737
|
+
}
|
|
3738
|
+
if (layout.systemDividers) {
|
|
3739
|
+
lines.push(`${indent} <system-dividers>`);
|
|
3740
|
+
if (layout.systemDividers.leftDivider) {
|
|
3741
|
+
let attrs = "";
|
|
3742
|
+
if (layout.systemDividers.leftDivider.printObject !== void 0) {
|
|
3743
|
+
attrs += ` print-object="${layout.systemDividers.leftDivider.printObject ? "yes" : "no"}"`;
|
|
3744
|
+
}
|
|
3745
|
+
if (layout.systemDividers.leftDivider.halign) {
|
|
3746
|
+
attrs += ` halign="${layout.systemDividers.leftDivider.halign}"`;
|
|
3747
|
+
}
|
|
3748
|
+
if (layout.systemDividers.leftDivider.valign) {
|
|
3749
|
+
attrs += ` valign="${layout.systemDividers.leftDivider.valign}"`;
|
|
3750
|
+
}
|
|
3751
|
+
lines.push(`${indent} <left-divider${attrs}/>`);
|
|
3752
|
+
}
|
|
3753
|
+
if (layout.systemDividers.rightDivider) {
|
|
3754
|
+
let attrs = "";
|
|
3755
|
+
if (layout.systemDividers.rightDivider.printObject !== void 0) {
|
|
3756
|
+
attrs += ` print-object="${layout.systemDividers.rightDivider.printObject ? "yes" : "no"}"`;
|
|
3757
|
+
}
|
|
3758
|
+
if (layout.systemDividers.rightDivider.halign) {
|
|
3759
|
+
attrs += ` halign="${layout.systemDividers.rightDivider.halign}"`;
|
|
3760
|
+
}
|
|
3761
|
+
if (layout.systemDividers.rightDivider.valign) {
|
|
3762
|
+
attrs += ` valign="${layout.systemDividers.rightDivider.valign}"`;
|
|
3763
|
+
}
|
|
3764
|
+
lines.push(`${indent} <right-divider${attrs}/>`);
|
|
3765
|
+
}
|
|
3766
|
+
lines.push(`${indent} </system-dividers>`);
|
|
3571
3767
|
}
|
|
3572
3768
|
lines.push(`${indent}</system-layout>`);
|
|
3573
3769
|
return lines;
|
|
@@ -3588,6 +3784,7 @@ function serializeCredit(credit, indent) {
|
|
|
3588
3784
|
let attrs2 = "";
|
|
3589
3785
|
if (cw.defaultX !== void 0) attrs2 += ` default-x="${cw.defaultX}"`;
|
|
3590
3786
|
if (cw.defaultY !== void 0) attrs2 += ` default-y="${cw.defaultY}"`;
|
|
3787
|
+
if (cw.fontFamily) attrs2 += ` font-family="${escapeXml(cw.fontFamily)}"`;
|
|
3591
3788
|
if (cw.fontSize) attrs2 += ` font-size="${escapeXml(cw.fontSize)}"`;
|
|
3592
3789
|
if (cw.fontWeight) attrs2 += ` font-weight="${escapeXml(cw.fontWeight)}"`;
|
|
3593
3790
|
if (cw.fontStyle) attrs2 += ` font-style="${escapeXml(cw.fontStyle)}"`;
|
|
@@ -3882,6 +4079,7 @@ function serializeKey(key, indent) {
|
|
|
3882
4079
|
let keyAttrs = "";
|
|
3883
4080
|
if (key.number !== void 0) keyAttrs += ` number="${key.number}"`;
|
|
3884
4081
|
if (key.printObject === false) keyAttrs += ' print-object="no"';
|
|
4082
|
+
else if (key.printObject === true) keyAttrs += ' print-object="yes"';
|
|
3885
4083
|
lines.push(`${indent}<key${keyAttrs}>`);
|
|
3886
4084
|
if (key.cancel !== void 0) {
|
|
3887
4085
|
const locationAttr = key.cancelLocation ? ` location="${key.cancelLocation}"` : "";
|
|
@@ -3929,7 +4127,8 @@ function serializeTime(time, indent) {
|
|
|
3929
4127
|
const maxLen = Math.max(time.beatsList.length, time.beatTypeList.length);
|
|
3930
4128
|
for (let i = 0; i < maxLen; i++) {
|
|
3931
4129
|
if (i < time.beatsList.length) {
|
|
3932
|
-
|
|
4130
|
+
const beatsValue = time.beatsStrList && i < time.beatsStrList.length ? time.beatsStrList[i] : time.beatsList[i];
|
|
4131
|
+
lines.push(`${indent} <beats>${beatsValue}</beats>`);
|
|
3933
4132
|
}
|
|
3934
4133
|
if (i < time.beatTypeList.length) {
|
|
3935
4134
|
lines.push(`${indent} <beat-type>${time.beatTypeList[i]}</beat-type>`);
|
|
@@ -3946,10 +4145,13 @@ function serializeClef(clef, indent) {
|
|
|
3946
4145
|
const lines = [];
|
|
3947
4146
|
let attrs = clef.staff ? ` number="${clef.staff}"` : "";
|
|
3948
4147
|
if (clef.printObject === false) attrs += ' print-object="no"';
|
|
4148
|
+
else if (clef.printObject === true) attrs += ' print-object="yes"';
|
|
3949
4149
|
if (clef.afterBarline) attrs += ' after-barline="yes"';
|
|
3950
4150
|
lines.push(`${indent}<clef${attrs}>`);
|
|
3951
4151
|
lines.push(`${indent} <sign>${clef.sign}</sign>`);
|
|
3952
|
-
|
|
4152
|
+
if (clef.line !== void 0) {
|
|
4153
|
+
lines.push(`${indent} <line>${clef.line}</line>`);
|
|
4154
|
+
}
|
|
3953
4155
|
if (clef.clefOctaveChange !== void 0) {
|
|
3954
4156
|
lines.push(`${indent} <clef-octave-change>${clef.clefOctaveChange}</clef-octave-change>`);
|
|
3955
4157
|
}
|
|
@@ -3985,6 +4187,12 @@ function serializeEntry(entry, indent) {
|
|
|
3985
4187
|
return serializeSound(entry, indent);
|
|
3986
4188
|
case "attributes":
|
|
3987
4189
|
return serializeAttributes(entry.attributes, indent, entry._id);
|
|
4190
|
+
case "grouping": {
|
|
4191
|
+
const grp = entry;
|
|
4192
|
+
let grpAttrs = ` type="${grp.groupingType}"`;
|
|
4193
|
+
if (grp.number) grpAttrs += ` number="${grp.number}"`;
|
|
4194
|
+
return [`${indent}<grouping${grpAttrs}/>`];
|
|
4195
|
+
}
|
|
3988
4196
|
default:
|
|
3989
4197
|
return [];
|
|
3990
4198
|
}
|
|
@@ -3999,12 +4207,13 @@ function serializeNote(note, indent) {
|
|
|
3999
4207
|
"relative-y": note.relativeY,
|
|
4000
4208
|
"dynamics": note.dynamics,
|
|
4001
4209
|
"print-object": note.printObject === false ? false : void 0,
|
|
4210
|
+
"print-dot": note.printDot !== void 0 ? note.printDot : void 0,
|
|
4002
4211
|
"print-spacing": note.printSpacing
|
|
4003
4212
|
});
|
|
4004
4213
|
lines.push(`${indent}<note${noteAttrs}>`);
|
|
4005
4214
|
if (note.grace) {
|
|
4006
4215
|
const graceAttrs = buildAttrs({
|
|
4007
|
-
"slash": note.grace.slash
|
|
4216
|
+
"slash": note.grace.slash !== void 0 ? note.grace.slash : void 0,
|
|
4008
4217
|
"steal-time-previous": note.grace.stealTimePrevious,
|
|
4009
4218
|
"steal-time-following": note.grace.stealTimeFollowing
|
|
4010
4219
|
});
|
|
@@ -4059,7 +4268,9 @@ function serializeNote(note, indent) {
|
|
|
4059
4268
|
} else if (note.tie) {
|
|
4060
4269
|
lines.push(`${indent} <tie type="${note.tie.type}"/>`);
|
|
4061
4270
|
}
|
|
4062
|
-
|
|
4271
|
+
if (note.voice !== void 0) {
|
|
4272
|
+
lines.push(`${indent} <voice>${note.voice}</voice>`);
|
|
4273
|
+
}
|
|
4063
4274
|
if (note.noteType) {
|
|
4064
4275
|
const typeAttrs = note.noteTypeSize ? ` size="${escapeXml(note.noteTypeSize)}"` : "";
|
|
4065
4276
|
lines.push(`${indent} <type${typeAttrs}>${note.noteType}</type>`);
|
|
@@ -4167,154 +4378,200 @@ function serializeNotations(notations, indent) {
|
|
|
4167
4378
|
function serializeNotationsGroup(notations, indent) {
|
|
4168
4379
|
const lines = [];
|
|
4169
4380
|
lines.push(`${indent}<notations>`);
|
|
4170
|
-
const
|
|
4171
|
-
const ornaments = [];
|
|
4172
|
-
const technicals = [];
|
|
4173
|
-
const others = [];
|
|
4381
|
+
const chunks = [];
|
|
4174
4382
|
for (const notation of notations) {
|
|
4175
4383
|
if (notation.type === "articulation") {
|
|
4176
4384
|
const artIdx = notation.articulationsIndex ?? 0;
|
|
4177
|
-
|
|
4178
|
-
|
|
4385
|
+
const last = chunks[chunks.length - 1];
|
|
4386
|
+
if (last && last.kind === "articulations" && last.articulationsIndex === artIdx) {
|
|
4387
|
+
last.items.push(notation);
|
|
4388
|
+
} else {
|
|
4389
|
+
chunks.push({ kind: "articulations", items: [notation], articulationsIndex: artIdx });
|
|
4179
4390
|
}
|
|
4180
|
-
articulationsGroups.get(artIdx).push(notation);
|
|
4181
4391
|
} else if (notation.type === "ornament") {
|
|
4182
|
-
|
|
4392
|
+
const last = chunks[chunks.length - 1];
|
|
4393
|
+
if (last && last.kind === "ornaments") {
|
|
4394
|
+
last.items.push(notation);
|
|
4395
|
+
} else {
|
|
4396
|
+
chunks.push({ kind: "ornaments", items: [notation] });
|
|
4397
|
+
}
|
|
4183
4398
|
} else if (notation.type === "technical") {
|
|
4184
|
-
|
|
4399
|
+
const last = chunks[chunks.length - 1];
|
|
4400
|
+
if (last && last.kind === "technical") {
|
|
4401
|
+
last.items.push(notation);
|
|
4402
|
+
} else {
|
|
4403
|
+
chunks.push({ kind: "technical", items: [notation] });
|
|
4404
|
+
}
|
|
4185
4405
|
} else {
|
|
4186
|
-
|
|
4406
|
+
chunks.push({ kind: "standalone", notation });
|
|
4187
4407
|
}
|
|
4188
4408
|
}
|
|
4189
|
-
for (const
|
|
4190
|
-
if (
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
}
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4409
|
+
for (const chunk of chunks) {
|
|
4410
|
+
if (chunk.kind === "standalone") {
|
|
4411
|
+
lines.push(...serializeStandaloneNotation(chunk.notation, indent));
|
|
4412
|
+
} else if (chunk.kind === "articulations") {
|
|
4413
|
+
lines.push(...serializeArticulationsGroup(chunk.items, indent));
|
|
4414
|
+
} else if (chunk.kind === "ornaments") {
|
|
4415
|
+
lines.push(...serializeOrnamentsGroup(chunk.items, indent));
|
|
4416
|
+
} else if (chunk.kind === "technical") {
|
|
4417
|
+
lines.push(...serializeTechnicalGroup(chunk.items, indent));
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
lines.push(`${indent}</notations>`);
|
|
4421
|
+
return lines;
|
|
4422
|
+
}
|
|
4423
|
+
function serializeStandaloneNotation(notation, indent) {
|
|
4424
|
+
const lines = [];
|
|
4425
|
+
if (notation.type === "tied") {
|
|
4426
|
+
let attrs = ` type="${notation.tiedType}"`;
|
|
4427
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4428
|
+
if (notation.orientation) attrs += ` orientation="${notation.orientation}"`;
|
|
4429
|
+
lines.push(`${indent} <tied${attrs}/>`);
|
|
4430
|
+
} else if (notation.type === "slur") {
|
|
4431
|
+
let attrs = "";
|
|
4432
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4433
|
+
attrs += ` type="${notation.slurType}"`;
|
|
4434
|
+
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4435
|
+
if (notation.orientation) attrs += ` orientation="${notation.orientation}"`;
|
|
4436
|
+
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4437
|
+
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4438
|
+
if (notation.bezierX !== void 0) attrs += ` bezier-x="${notation.bezierX}"`;
|
|
4439
|
+
if (notation.bezierY !== void 0) attrs += ` bezier-y="${notation.bezierY}"`;
|
|
4440
|
+
if (notation.bezierX2 !== void 0) attrs += ` bezier-x2="${notation.bezierX2}"`;
|
|
4441
|
+
if (notation.bezierY2 !== void 0) attrs += ` bezier-y2="${notation.bezierY2}"`;
|
|
4442
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4443
|
+
lines.push(`${indent} <slur${attrs}/>`);
|
|
4444
|
+
} else if (notation.type === "tuplet") {
|
|
4445
|
+
let attrs = ` type="${notation.tupletType}"`;
|
|
4446
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4447
|
+
if (notation.bracket !== void 0) attrs += ` bracket="${notation.bracket ? "yes" : "no"}"`;
|
|
4448
|
+
if (notation.showNumber) attrs += ` show-number="${notation.showNumber}"`;
|
|
4449
|
+
if (notation.showType) attrs += ` show-type="${notation.showType}"`;
|
|
4450
|
+
if (notation.lineShape) attrs += ` line-shape="${notation.lineShape}"`;
|
|
4451
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4452
|
+
const tup = notation;
|
|
4453
|
+
if (tup.tupletActual || tup.tupletNormal) {
|
|
4454
|
+
lines.push(`${indent} <tuplet${attrs}>`);
|
|
4455
|
+
if (tup.tupletActual) {
|
|
4456
|
+
lines.push(`${indent} <tuplet-actual>`);
|
|
4457
|
+
if (tup.tupletActual.tupletNumber !== void 0) {
|
|
4458
|
+
lines.push(`${indent} <tuplet-number>${tup.tupletActual.tupletNumber}</tuplet-number>`);
|
|
4459
|
+
}
|
|
4460
|
+
if (tup.tupletActual.tupletType) {
|
|
4461
|
+
lines.push(`${indent} <tuplet-type>${tup.tupletActual.tupletType}</tuplet-type>`);
|
|
4462
|
+
}
|
|
4463
|
+
if (tup.tupletActual.tupletDots) {
|
|
4464
|
+
for (let i = 0; i < tup.tupletActual.tupletDots; i++) {
|
|
4465
|
+
lines.push(`${indent} <tuplet-dot/>`);
|
|
4232
4466
|
}
|
|
4233
|
-
lines.push(`${indent} </tuplet-actual>`);
|
|
4234
4467
|
}
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4468
|
+
lines.push(`${indent} </tuplet-actual>`);
|
|
4469
|
+
}
|
|
4470
|
+
if (tup.tupletNormal) {
|
|
4471
|
+
lines.push(`${indent} <tuplet-normal>`);
|
|
4472
|
+
if (tup.tupletNormal.tupletNumber !== void 0) {
|
|
4473
|
+
lines.push(`${indent} <tuplet-number>${tup.tupletNormal.tupletNumber}</tuplet-number>`);
|
|
4474
|
+
}
|
|
4475
|
+
if (tup.tupletNormal.tupletType) {
|
|
4476
|
+
lines.push(`${indent} <tuplet-type>${tup.tupletNormal.tupletType}</tuplet-type>`);
|
|
4477
|
+
}
|
|
4478
|
+
if (tup.tupletNormal.tupletDots) {
|
|
4479
|
+
for (let i = 0; i < tup.tupletNormal.tupletDots; i++) {
|
|
4480
|
+
lines.push(`${indent} <tuplet-dot/>`);
|
|
4247
4481
|
}
|
|
4248
|
-
lines.push(`${indent} </tuplet-normal>`);
|
|
4249
4482
|
}
|
|
4250
|
-
lines.push(`${indent}
|
|
4251
|
-
} else {
|
|
4252
|
-
lines.push(`${indent} <tuplet${attrs}/>`);
|
|
4253
|
-
}
|
|
4254
|
-
} else if (notation.type === "dynamics") {
|
|
4255
|
-
const placementAttr = notation.placement ? ` placement="${notation.placement}"` : "";
|
|
4256
|
-
lines.push(`${indent} <dynamics${placementAttr}>`);
|
|
4257
|
-
for (const dyn of notation.dynamics) {
|
|
4258
|
-
lines.push(`${indent} <${dyn}/>`);
|
|
4259
|
-
}
|
|
4260
|
-
if (notation.otherDynamics) {
|
|
4261
|
-
lines.push(`${indent} <other-dynamics>${escapeXml(notation.otherDynamics)}</other-dynamics>`);
|
|
4262
|
-
}
|
|
4263
|
-
lines.push(`${indent} </dynamics>`);
|
|
4264
|
-
} else if (notation.type === "fermata") {
|
|
4265
|
-
let attrs = "";
|
|
4266
|
-
if (notation.fermataType) attrs += ` type="${notation.fermataType}"`;
|
|
4267
|
-
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4268
|
-
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4269
|
-
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4270
|
-
if (notation.shape) {
|
|
4271
|
-
lines.push(`${indent} <fermata${attrs}>${notation.shape}</fermata>`);
|
|
4272
|
-
} else {
|
|
4273
|
-
lines.push(`${indent} <fermata${attrs}/>`);
|
|
4274
|
-
}
|
|
4275
|
-
} else if (notation.type === "arpeggiate") {
|
|
4276
|
-
let attrs = "";
|
|
4277
|
-
if (notation.direction) attrs += ` direction="${notation.direction}"`;
|
|
4278
|
-
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4279
|
-
lines.push(`${indent} <arpeggiate${attrs}/>`);
|
|
4280
|
-
} else if (notation.type === "glissando") {
|
|
4281
|
-
let attrs = ` type="${notation.glissandoType}"`;
|
|
4282
|
-
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4283
|
-
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4284
|
-
if (notation.text) {
|
|
4285
|
-
lines.push(`${indent} <glissando${attrs}>${escapeXml(notation.text)}</glissando>`);
|
|
4286
|
-
} else {
|
|
4287
|
-
lines.push(`${indent} <glissando${attrs}/>`);
|
|
4483
|
+
lines.push(`${indent} </tuplet-normal>`);
|
|
4288
4484
|
}
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4485
|
+
lines.push(`${indent} </tuplet>`);
|
|
4486
|
+
} else {
|
|
4487
|
+
lines.push(`${indent} <tuplet${attrs}/>`);
|
|
4488
|
+
}
|
|
4489
|
+
} else if (notation.type === "dynamics") {
|
|
4490
|
+
const placementAttr = notation.placement ? ` placement="${notation.placement}"` : "";
|
|
4491
|
+
lines.push(`${indent} <dynamics${placementAttr}>`);
|
|
4492
|
+
for (const dyn of notation.dynamics) {
|
|
4493
|
+
lines.push(`${indent} <${dyn}/>`);
|
|
4494
|
+
}
|
|
4495
|
+
if (notation.otherDynamics) {
|
|
4496
|
+
lines.push(`${indent} <other-dynamics>${escapeXml(notation.otherDynamics)}</other-dynamics>`);
|
|
4497
|
+
}
|
|
4498
|
+
lines.push(`${indent} </dynamics>`);
|
|
4499
|
+
} else if (notation.type === "fermata") {
|
|
4500
|
+
let attrs = "";
|
|
4501
|
+
if (notation.fermataType) attrs += ` type="${notation.fermataType}"`;
|
|
4502
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4503
|
+
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4504
|
+
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4505
|
+
if (notation.shape) {
|
|
4506
|
+
lines.push(`${indent} <fermata${attrs}>${notation.shape}</fermata>`);
|
|
4507
|
+
} else {
|
|
4508
|
+
lines.push(`${indent} <fermata${attrs}/>`);
|
|
4509
|
+
}
|
|
4510
|
+
} else if (notation.type === "arpeggiate") {
|
|
4511
|
+
let attrs = "";
|
|
4512
|
+
if (notation.direction) attrs += ` direction="${notation.direction}"`;
|
|
4513
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4514
|
+
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4515
|
+
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4516
|
+
lines.push(`${indent} <arpeggiate${attrs}/>`);
|
|
4517
|
+
} else if (notation.type === "non-arpeggiate") {
|
|
4518
|
+
let attrs = ` type="${notation.nonArpeggiateType}"`;
|
|
4519
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4520
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4521
|
+
lines.push(`${indent} <non-arpeggiate${attrs}/>`);
|
|
4522
|
+
} else if (notation.type === "accidental-mark") {
|
|
4523
|
+
let attrs = "";
|
|
4524
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4525
|
+
lines.push(`${indent} <accidental-mark${attrs}>${escapeXml(notation.value)}</accidental-mark>`);
|
|
4526
|
+
} else if (notation.type === "glissando") {
|
|
4527
|
+
let attrs = ` type="${notation.glissandoType}"`;
|
|
4528
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4529
|
+
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4530
|
+
if (notation.text) {
|
|
4531
|
+
lines.push(`${indent} <glissando${attrs}>${escapeXml(notation.text)}</glissando>`);
|
|
4532
|
+
} else {
|
|
4533
|
+
lines.push(`${indent} <glissando${attrs}/>`);
|
|
4534
|
+
}
|
|
4535
|
+
} else if (notation.type === "slide") {
|
|
4536
|
+
let attrs = ` type="${notation.slideType}"`;
|
|
4537
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4538
|
+
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4539
|
+
if (notation.text) {
|
|
4540
|
+
lines.push(`${indent} <slide${attrs}>${escapeXml(notation.text)}</slide>`);
|
|
4541
|
+
} else {
|
|
4293
4542
|
lines.push(`${indent} <slide${attrs}/>`);
|
|
4294
4543
|
}
|
|
4295
4544
|
}
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
}
|
|
4306
|
-
if (art.defaultX !== void 0) artAttrs += ` default-x="${art.defaultX}"`;
|
|
4307
|
-
if (art.defaultY !== void 0) artAttrs += ` default-y="${art.defaultY}"`;
|
|
4308
|
-
lines.push(`${indent} <${art.articulation}${artAttrs}/>`);
|
|
4545
|
+
return lines;
|
|
4546
|
+
}
|
|
4547
|
+
function serializeArticulationsGroup(artGroup, indent) {
|
|
4548
|
+
const lines = [];
|
|
4549
|
+
lines.push(`${indent} <articulations>`);
|
|
4550
|
+
for (const art of artGroup) {
|
|
4551
|
+
if (art.type === "articulation") {
|
|
4552
|
+
let artAttrs = art.placement ? ` placement="${art.placement}"` : "";
|
|
4553
|
+
if (art.articulation === "strong-accent" && art.strongAccentType) {
|
|
4554
|
+
artAttrs += ` type="${art.strongAccentType}"`;
|
|
4309
4555
|
}
|
|
4556
|
+
if (art.defaultX !== void 0) artAttrs += ` default-x="${art.defaultX}"`;
|
|
4557
|
+
if (art.defaultY !== void 0) artAttrs += ` default-y="${art.defaultY}"`;
|
|
4558
|
+
lines.push(`${indent} <${art.articulation}${artAttrs}/>`);
|
|
4310
4559
|
}
|
|
4311
|
-
lines.push(`${indent} </articulations>`);
|
|
4312
4560
|
}
|
|
4313
|
-
|
|
4561
|
+
lines.push(`${indent} </articulations>`);
|
|
4562
|
+
return lines;
|
|
4563
|
+
}
|
|
4564
|
+
function serializeOrnamentsGroup(ornaments, indent) {
|
|
4565
|
+
const lines = [];
|
|
4566
|
+
const hasOnlyEmptyMarker = ornaments.length === 1 && ornaments[0].type === "ornament" && ornaments[0].ornament === "empty";
|
|
4567
|
+
if (hasOnlyEmptyMarker) {
|
|
4568
|
+
lines.push(`${indent} <ornaments/>`);
|
|
4569
|
+
} else {
|
|
4314
4570
|
lines.push(`${indent} <ornaments>`);
|
|
4315
4571
|
const allAccidentalMarks = [];
|
|
4316
4572
|
for (const orn of ornaments) {
|
|
4317
4573
|
if (orn.type === "ornament") {
|
|
4574
|
+
if (orn.ornament === "empty") continue;
|
|
4318
4575
|
const placementAttr = orn.placement ? ` placement="${orn.placement}"` : "";
|
|
4319
4576
|
if (orn.ornament === "wavy-line") {
|
|
4320
4577
|
let wlAttrs = "";
|
|
@@ -4350,77 +4607,80 @@ function serializeNotationsGroup(notations, indent) {
|
|
|
4350
4607
|
}
|
|
4351
4608
|
lines.push(`${indent} </ornaments>`);
|
|
4352
4609
|
}
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
}
|
|
4389
|
-
} else if (tech.technical === "hammer-on" || tech.technical === "pull-off") {
|
|
4390
|
-
let attrs = placementAttr;
|
|
4391
|
-
if (techNotation.startStop) attrs += ` type="${techNotation.startStop}"`;
|
|
4392
|
-
if (techNotation.text !== void 0) {
|
|
4393
|
-
lines.push(`${indent} <${tech.technical}${attrs}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4394
|
-
} else {
|
|
4395
|
-
lines.push(`${indent} <${tech.technical}${attrs}/>`);
|
|
4396
|
-
}
|
|
4397
|
-
} else if (tech.technical === "string" && techNotation.string !== void 0) {
|
|
4398
|
-
lines.push(`${indent} <string${placementAttr}>${techNotation.string}</string>`);
|
|
4399
|
-
} else if (tech.technical === "fret" && techNotation.fret !== void 0) {
|
|
4400
|
-
lines.push(`${indent} <fret${placementAttr}>${techNotation.fret}</fret>`);
|
|
4401
|
-
} else if (tech.technical === "fingering") {
|
|
4402
|
-
let fAttrs = placementAttr;
|
|
4403
|
-
if (techNotation.fingeringSubstitution) fAttrs += ' substitution="yes"';
|
|
4404
|
-
if (techNotation.fingeringAlternate) fAttrs += ' alternate="yes"';
|
|
4405
|
-
if (techNotation.text !== void 0) {
|
|
4406
|
-
lines.push(`${indent} <fingering${fAttrs}>${escapeXml(techNotation.text)}</fingering>`);
|
|
4407
|
-
} else {
|
|
4408
|
-
lines.push(`${indent} <fingering${fAttrs}/>`);
|
|
4409
|
-
}
|
|
4410
|
-
} else if (tech.technical === "heel" || tech.technical === "toe") {
|
|
4411
|
-
let htAttrs = placementAttr;
|
|
4412
|
-
if (techNotation.substitution) htAttrs += ' substitution="yes"';
|
|
4413
|
-
lines.push(`${indent} <${tech.technical}${htAttrs}/>`);
|
|
4414
|
-
} else if (techNotation.text !== void 0) {
|
|
4415
|
-
lines.push(`${indent} <${tech.technical}${placementAttr}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4610
|
+
return lines;
|
|
4611
|
+
}
|
|
4612
|
+
function serializeTechnicalGroup(technicals, indent) {
|
|
4613
|
+
const lines = [];
|
|
4614
|
+
lines.push(`${indent} <technical>`);
|
|
4615
|
+
for (const tech of technicals) {
|
|
4616
|
+
if (tech.type === "technical") {
|
|
4617
|
+
let placementAttr = tech.placement ? ` placement="${tech.placement}"` : "";
|
|
4618
|
+
const techNotation = tech;
|
|
4619
|
+
if (techNotation.defaultX !== void 0) placementAttr += ` default-x="${techNotation.defaultX}"`;
|
|
4620
|
+
if (techNotation.defaultY !== void 0) placementAttr += ` default-y="${techNotation.defaultY}"`;
|
|
4621
|
+
if (tech.technical === "bend" && (techNotation.bendAlter !== void 0 || techNotation.preBend || techNotation.release)) {
|
|
4622
|
+
lines.push(`${indent} <bend${placementAttr}>`);
|
|
4623
|
+
if (techNotation.bendAlter !== void 0) {
|
|
4624
|
+
lines.push(`${indent} <bend-alter>${techNotation.bendAlter}</bend-alter>`);
|
|
4625
|
+
}
|
|
4626
|
+
if (techNotation.preBend) {
|
|
4627
|
+
lines.push(`${indent} <pre-bend/>`);
|
|
4628
|
+
}
|
|
4629
|
+
if (techNotation.release) {
|
|
4630
|
+
lines.push(`${indent} <release/>`);
|
|
4631
|
+
}
|
|
4632
|
+
if (techNotation.withBar) {
|
|
4633
|
+
lines.push(`${indent} <with-bar/>`);
|
|
4634
|
+
}
|
|
4635
|
+
lines.push(`${indent} </bend>`);
|
|
4636
|
+
} else if (tech.technical === "harmonic") {
|
|
4637
|
+
const hasChildren = techNotation.harmonicNatural || techNotation.harmonicArtificial || techNotation.basePitch || techNotation.touchingPitch || techNotation.soundingPitch;
|
|
4638
|
+
if (hasChildren) {
|
|
4639
|
+
lines.push(`${indent} <harmonic${placementAttr}>`);
|
|
4640
|
+
if (techNotation.harmonicNatural) lines.push(`${indent} <natural/>`);
|
|
4641
|
+
if (techNotation.harmonicArtificial) lines.push(`${indent} <artificial/>`);
|
|
4642
|
+
if (techNotation.basePitch) lines.push(`${indent} <base-pitch/>`);
|
|
4643
|
+
if (techNotation.touchingPitch) lines.push(`${indent} <touching-pitch/>`);
|
|
4644
|
+
if (techNotation.soundingPitch) lines.push(`${indent} <sounding-pitch/>`);
|
|
4645
|
+
lines.push(`${indent} </harmonic>`);
|
|
4416
4646
|
} else {
|
|
4417
|
-
lines.push(`${indent}
|
|
4418
|
-
}
|
|
4647
|
+
lines.push(`${indent} <harmonic${placementAttr}/>`);
|
|
4648
|
+
}
|
|
4649
|
+
} else if (tech.technical === "hammer-on" || tech.technical === "pull-off") {
|
|
4650
|
+
let attrs = "";
|
|
4651
|
+
if (techNotation.number !== void 0) attrs += ` number="${techNotation.number}"`;
|
|
4652
|
+
if (techNotation.startStop) attrs += ` type="${techNotation.startStop}"`;
|
|
4653
|
+
attrs += placementAttr;
|
|
4654
|
+
if (techNotation.text !== void 0) {
|
|
4655
|
+
lines.push(`${indent} <${tech.technical}${attrs}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4656
|
+
} else {
|
|
4657
|
+
lines.push(`${indent} <${tech.technical}${attrs}/>`);
|
|
4658
|
+
}
|
|
4659
|
+
} else if (tech.technical === "string" && techNotation.string !== void 0) {
|
|
4660
|
+
lines.push(`${indent} <string${placementAttr}>${techNotation.string}</string>`);
|
|
4661
|
+
} else if (tech.technical === "fret" && techNotation.fret !== void 0) {
|
|
4662
|
+
lines.push(`${indent} <fret${placementAttr}>${techNotation.fret}</fret>`);
|
|
4663
|
+
} else if (tech.technical === "fingering") {
|
|
4664
|
+
let fAttrs = placementAttr;
|
|
4665
|
+
if (techNotation.fingeringSubstitution) fAttrs += ' substitution="yes"';
|
|
4666
|
+
if (techNotation.fingeringAlternate) fAttrs += ' alternate="yes"';
|
|
4667
|
+
if (techNotation.text !== void 0) {
|
|
4668
|
+
lines.push(`${indent} <fingering${fAttrs}>${escapeXml(techNotation.text)}</fingering>`);
|
|
4669
|
+
} else {
|
|
4670
|
+
lines.push(`${indent} <fingering${fAttrs}/>`);
|
|
4671
|
+
}
|
|
4672
|
+
} else if (tech.technical === "heel" || tech.technical === "toe") {
|
|
4673
|
+
let htAttrs = placementAttr;
|
|
4674
|
+
if (techNotation.substitution) htAttrs += ' substitution="yes"';
|
|
4675
|
+
lines.push(`${indent} <${tech.technical}${htAttrs}/>`);
|
|
4676
|
+
} else if (techNotation.text !== void 0) {
|
|
4677
|
+
lines.push(`${indent} <${tech.technical}${placementAttr}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4678
|
+
} else {
|
|
4679
|
+
lines.push(`${indent} <${tech.technical}${placementAttr}/>`);
|
|
4419
4680
|
}
|
|
4420
4681
|
}
|
|
4421
|
-
lines.push(`${indent} </technical>`);
|
|
4422
4682
|
}
|
|
4423
|
-
lines.push(`${indent}</
|
|
4683
|
+
lines.push(`${indent} </technical>`);
|
|
4424
4684
|
return lines;
|
|
4425
4685
|
}
|
|
4426
4686
|
function serializeLyric(lyric, indent) {
|
|
@@ -4444,7 +4704,7 @@ function serializeLyric(lyric, indent) {
|
|
|
4444
4704
|
lines.push(`${indent} <elision/>`);
|
|
4445
4705
|
}
|
|
4446
4706
|
}
|
|
4447
|
-
} else {
|
|
4707
|
+
} else if (lyric.syllabic || lyric.text) {
|
|
4448
4708
|
if (lyric.syllabic) {
|
|
4449
4709
|
lines.push(`${indent} <syllabic>${lyric.syllabic}</syllabic>`);
|
|
4450
4710
|
}
|
|
@@ -4559,7 +4819,12 @@ function serializeDirectionType(dirType, indent) {
|
|
|
4559
4819
|
if (dirType.relativeX !== void 0) dynAttrs += ` relative-x="${dirType.relativeX}"`;
|
|
4560
4820
|
if (dirType.halign) dynAttrs += ` halign="${dirType.halign}"`;
|
|
4561
4821
|
lines.push(`${indent} <dynamics${dynAttrs}>`);
|
|
4562
|
-
|
|
4822
|
+
if (dirType.value) {
|
|
4823
|
+
lines.push(`${indent} <${dirType.value}/>`);
|
|
4824
|
+
}
|
|
4825
|
+
if (dirType.otherDynamics) {
|
|
4826
|
+
lines.push(`${indent} <other-dynamics>${escapeXml(dirType.otherDynamics)}</other-dynamics>`);
|
|
4827
|
+
}
|
|
4563
4828
|
lines.push(`${indent} </dynamics>`);
|
|
4564
4829
|
break;
|
|
4565
4830
|
}
|
|
@@ -4646,8 +4911,12 @@ function serializeDirectionType(dirType, indent) {
|
|
|
4646
4911
|
if (dirType.high) {
|
|
4647
4912
|
lines.push(`${indent} <accordion-high/>`);
|
|
4648
4913
|
}
|
|
4649
|
-
if (dirType.middle !== void 0) {
|
|
4650
|
-
|
|
4914
|
+
if (dirType.middlePresent || dirType.middle !== void 0) {
|
|
4915
|
+
if (dirType.middle !== void 0) {
|
|
4916
|
+
lines.push(`${indent} <accordion-middle>${dirType.middle}</accordion-middle>`);
|
|
4917
|
+
} else {
|
|
4918
|
+
lines.push(`${indent} <accordion-middle/>`);
|
|
4919
|
+
}
|
|
4651
4920
|
}
|
|
4652
4921
|
if (dirType.low) {
|
|
4653
4922
|
lines.push(`${indent} <accordion-low/>`);
|
|
@@ -4760,11 +5029,20 @@ function serializeBarline(barline, indent) {
|
|
|
4760
5029
|
lines.push(`${indent} <bar-style>${barline.barStyle}</bar-style>`);
|
|
4761
5030
|
}
|
|
4762
5031
|
if (barline.ending) {
|
|
4763
|
-
|
|
5032
|
+
let endingAttrs = ` number="${barline.ending.number}" type="${barline.ending.type}"`;
|
|
5033
|
+
if (barline.ending.defaultY !== void 0) endingAttrs += ` default-y="${barline.ending.defaultY}"`;
|
|
5034
|
+
if (barline.ending.endLength !== void 0) endingAttrs += ` end-length="${barline.ending.endLength}"`;
|
|
5035
|
+
if (barline.ending.text) {
|
|
5036
|
+
lines.push(`${indent} <ending${endingAttrs}>${escapeXml(barline.ending.text)}</ending>`);
|
|
5037
|
+
} else {
|
|
5038
|
+
lines.push(`${indent} <ending${endingAttrs}/>`);
|
|
5039
|
+
}
|
|
4764
5040
|
}
|
|
4765
5041
|
if (barline.repeat) {
|
|
4766
|
-
|
|
4767
|
-
|
|
5042
|
+
let repeatAttrs = ` direction="${barline.repeat.direction}"`;
|
|
5043
|
+
if (barline.repeat.times !== void 0) repeatAttrs += ` times="${barline.repeat.times}"`;
|
|
5044
|
+
if (barline.repeat.winged) repeatAttrs += ` winged="${barline.repeat.winged}"`;
|
|
5045
|
+
lines.push(`${indent} <repeat${repeatAttrs}/>`);
|
|
4768
5046
|
}
|
|
4769
5047
|
lines.push(`${indent}</barline>`);
|
|
4770
5048
|
return lines;
|
|
@@ -4797,7 +5075,8 @@ function serializeStaffDetails(sd, indent) {
|
|
|
4797
5075
|
const attrs = buildAttrs({
|
|
4798
5076
|
"number": sd.number,
|
|
4799
5077
|
"show-frets": sd.showFrets,
|
|
4800
|
-
"print-object": sd.printObject
|
|
5078
|
+
"print-object": sd.printObject,
|
|
5079
|
+
"print-spacing": sd.printSpacing
|
|
4801
5080
|
});
|
|
4802
5081
|
lines.push(`${indent}<staff-details${attrs}>`);
|
|
4803
5082
|
pushOptionalElement(lines, `${indent} `, "staff-type", sd.staffType);
|
|
@@ -4863,16 +5142,22 @@ function serializeHarmony(harmony, indent) {
|
|
|
4863
5142
|
}
|
|
4864
5143
|
lines.push(`${indent} </root>`);
|
|
4865
5144
|
let kindAttrs = "";
|
|
4866
|
-
if (harmony.kindText) kindAttrs += ` text="${escapeXml(harmony.kindText)}"`;
|
|
5145
|
+
if (harmony.kindText !== void 0) kindAttrs += ` text="${escapeXml(harmony.kindText)}"`;
|
|
5146
|
+
if (harmony.kindHalign) kindAttrs += ` halign="${escapeXml(harmony.kindHalign)}"`;
|
|
4867
5147
|
lines.push(`${indent} <kind${kindAttrs}>${escapeXml(harmony.kind)}</kind>`);
|
|
4868
5148
|
if (harmony.bass) {
|
|
4869
|
-
|
|
5149
|
+
let bassAttrs = "";
|
|
5150
|
+
if (harmony.bass.arrangement) bassAttrs += ` arrangement="${escapeXml(harmony.bass.arrangement)}"`;
|
|
5151
|
+
lines.push(`${indent} <bass${bassAttrs}>`);
|
|
4870
5152
|
lines.push(`${indent} <bass-step>${harmony.bass.bassStep}</bass-step>`);
|
|
4871
5153
|
if (harmony.bass.bassAlter !== void 0) {
|
|
4872
5154
|
lines.push(`${indent} <bass-alter>${harmony.bass.bassAlter}</bass-alter>`);
|
|
4873
5155
|
}
|
|
4874
5156
|
lines.push(`${indent} </bass>`);
|
|
4875
5157
|
}
|
|
5158
|
+
if (harmony.inversion !== void 0) {
|
|
5159
|
+
lines.push(`${indent} <inversion>${harmony.inversion}</inversion>`);
|
|
5160
|
+
}
|
|
4876
5161
|
if (harmony.degrees) {
|
|
4877
5162
|
for (const deg of harmony.degrees) {
|
|
4878
5163
|
lines.push(`${indent} <degree>`);
|
|
@@ -5558,7 +5843,7 @@ function groupByVoice(measure) {
|
|
|
5558
5843
|
for (const entry of measure.entries) {
|
|
5559
5844
|
if (entry.type !== "note") continue;
|
|
5560
5845
|
const staff = entry.staff ?? 1;
|
|
5561
|
-
const voice = entry.voice;
|
|
5846
|
+
const voice = entry.voice ?? 1;
|
|
5562
5847
|
const key = `${staff}-${voice}`;
|
|
5563
5848
|
if (!groups.has(key)) {
|
|
5564
5849
|
groups.set(key, { staff, voice, notes: [] });
|
|
@@ -5652,7 +5937,7 @@ function getVoices(measure) {
|
|
|
5652
5937
|
const voices = /* @__PURE__ */ new Set();
|
|
5653
5938
|
for (const entry of measure.entries) {
|
|
5654
5939
|
if (entry.type === "note") {
|
|
5655
|
-
voices.add(entry.voice);
|
|
5940
|
+
voices.add(entry.voice ?? 1);
|
|
5656
5941
|
}
|
|
5657
5942
|
}
|
|
5658
5943
|
return Array.from(voices).sort((a, b) => a - b);
|
|
@@ -5703,7 +5988,7 @@ function buildVoiceToStaffMap(measure) {
|
|
|
5703
5988
|
const map = /* @__PURE__ */ new Map();
|
|
5704
5989
|
for (const entry of measure.entries) {
|
|
5705
5990
|
if (entry.type === "note" && entry.staff !== void 0) {
|
|
5706
|
-
const voice = entry.voice;
|
|
5991
|
+
const voice = entry.voice ?? 1;
|
|
5707
5992
|
const staff = entry.staff;
|
|
5708
5993
|
if (!map.has(voice)) {
|
|
5709
5994
|
map.set(voice, staff);
|
|
@@ -5722,7 +6007,7 @@ function buildVoiceToStaffMapForPart(part) {
|
|
|
5722
6007
|
for (const measure of part.measures) {
|
|
5723
6008
|
for (const entry of measure.entries) {
|
|
5724
6009
|
if (entry.type === "note" && entry.staff !== void 0) {
|
|
5725
|
-
const voice = entry.voice;
|
|
6010
|
+
const voice = entry.voice ?? 1;
|
|
5726
6011
|
const staff = entry.staff;
|
|
5727
6012
|
if (!map.has(voice)) {
|
|
5728
6013
|
map.set(voice, staff);
|
|
@@ -5741,7 +6026,7 @@ function inferStaff(entry, voiceToStaffMap) {
|
|
|
5741
6026
|
if (entry.staff !== void 0) {
|
|
5742
6027
|
return entry.staff;
|
|
5743
6028
|
}
|
|
5744
|
-
const inferredStaff = voiceToStaffMap.get(entry.voice);
|
|
6029
|
+
const inferredStaff = voiceToStaffMap.get(entry.voice ?? 1);
|
|
5745
6030
|
if (inferredStaff !== void 0) {
|
|
5746
6031
|
return inferredStaff;
|
|
5747
6032
|
}
|
|
@@ -5784,7 +6069,7 @@ function getVoicesForStaff(measure, staff) {
|
|
|
5784
6069
|
if (entry.type === "note") {
|
|
5785
6070
|
const entryStaff = entry.staff ?? 1;
|
|
5786
6071
|
if (entryStaff === staff) {
|
|
5787
|
-
voices.add(entry.voice);
|
|
6072
|
+
voices.add(entry.voice ?? 1);
|
|
5788
6073
|
}
|
|
5789
6074
|
}
|
|
5790
6075
|
}
|
|
@@ -6120,6 +6405,7 @@ function getDynamics(score, options) {
|
|
|
6120
6405
|
if (dirType.kind === "dynamics") {
|
|
6121
6406
|
results.push({
|
|
6122
6407
|
dynamic: dirType.value,
|
|
6408
|
+
otherDynamics: dirType.otherDynamics,
|
|
6123
6409
|
direction: entry,
|
|
6124
6410
|
part,
|
|
6125
6411
|
partIndex,
|
|
@@ -7194,14 +7480,17 @@ function hasNotesInRange(voiceEntries, startPos, endPos) {
|
|
|
7194
7480
|
return { hasNotes: conflicting.length > 0, conflictingNotes: conflicting };
|
|
7195
7481
|
}
|
|
7196
7482
|
function createRest(duration, voice, staff) {
|
|
7197
|
-
|
|
7483
|
+
const note = {
|
|
7198
7484
|
_id: generateId(),
|
|
7199
7485
|
type: "note",
|
|
7200
7486
|
rest: { displayStep: void 0, displayOctave: void 0 },
|
|
7201
7487
|
duration,
|
|
7202
|
-
voice,
|
|
7203
7488
|
staff
|
|
7204
7489
|
};
|
|
7490
|
+
if (voice !== void 0) {
|
|
7491
|
+
note.voice = voice;
|
|
7492
|
+
}
|
|
7493
|
+
return note;
|
|
7205
7494
|
}
|
|
7206
7495
|
function rebuildMeasureWithVoice(measure, voice, newEntries, measureDuration, staff) {
|
|
7207
7496
|
const otherEntries = [];
|
|
@@ -8755,7 +9044,7 @@ function autoBeam(score, options) {
|
|
|
8755
9044
|
for (const entry of measure.entries) {
|
|
8756
9045
|
if (entry.type === "note") {
|
|
8757
9046
|
if (!entry.chord && !entry.rest) {
|
|
8758
|
-
const voice = entry.voice;
|
|
9047
|
+
const voice = entry.voice ?? 1;
|
|
8759
9048
|
if (options.voice === void 0 || voice === options.voice) {
|
|
8760
9049
|
if (!notesByVoice.has(voice)) {
|
|
8761
9050
|
notesByVoice.set(voice, []);
|