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.js
CHANGED
|
@@ -290,11 +290,22 @@ var xmlParser = new import_fast_xml_parser.XMLParser({
|
|
|
290
290
|
});
|
|
291
291
|
function parse(xmlString) {
|
|
292
292
|
const parsed = xmlParser.parse(xmlString);
|
|
293
|
-
|
|
293
|
+
let scorePartwiseVersion;
|
|
294
|
+
let scorePartwise;
|
|
295
|
+
for (const el of parsed) {
|
|
296
|
+
if (el["score-partwise"]) {
|
|
297
|
+
scorePartwise = el["score-partwise"];
|
|
298
|
+
const attrs = getAttributes(el);
|
|
299
|
+
if (attrs["version"]) scorePartwiseVersion = attrs["version"];
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
294
303
|
if (!scorePartwise) {
|
|
295
304
|
throw new Error("Unsupported MusicXML format: only score-partwise is supported");
|
|
296
305
|
}
|
|
297
|
-
|
|
306
|
+
const score = parseScorePartwise(scorePartwise);
|
|
307
|
+
if (scorePartwiseVersion) score.version = scorePartwiseVersion;
|
|
308
|
+
return score;
|
|
298
309
|
}
|
|
299
310
|
function findElement(elements, tagName) {
|
|
300
311
|
for (const el of elements) {
|
|
@@ -512,9 +523,11 @@ function parseDefaults(elements) {
|
|
|
512
523
|
const lineWidths = collectElements(appContent, "line-width", (c, a) => ({ type: a["type"] || "", value: parseFloat(extractText(c)) || 0 }));
|
|
513
524
|
const noteSizes = collectElements(appContent, "note-size", (c, a) => ({ type: a["type"] || "", value: parseFloat(extractText(c)) || 0 }));
|
|
514
525
|
const distances = collectElements(appContent, "distance", (c, a) => ({ type: a["type"] || "", value: parseFloat(extractText(c)) || 0 }));
|
|
526
|
+
const glyphs = collectElements(appContent, "glyph", (c, a) => ({ type: a["type"] || "", value: extractText(c) }));
|
|
515
527
|
if (lineWidths.length > 0) appearance["line-widths"] = lineWidths;
|
|
516
528
|
if (noteSizes.length > 0) appearance["note-sizes"] = noteSizes;
|
|
517
529
|
if (distances.length > 0) appearance["distances"] = distances;
|
|
530
|
+
if (glyphs.length > 0) appearance["glyphs"] = glyphs;
|
|
518
531
|
return Object.keys(appearance).length > 0 ? appearance : void 0;
|
|
519
532
|
});
|
|
520
533
|
if (appResult) defaults.appearance = appResult;
|
|
@@ -536,13 +549,25 @@ function parsePageLayout(elements) {
|
|
|
536
549
|
m.type = attrs["type"];
|
|
537
550
|
}
|
|
538
551
|
const left = getElementText(content, "left-margin");
|
|
539
|
-
if (left)
|
|
552
|
+
if (left) {
|
|
553
|
+
m.leftMargin = parseFloat(left);
|
|
554
|
+
m.leftMarginRaw = left;
|
|
555
|
+
}
|
|
540
556
|
const right = getElementText(content, "right-margin");
|
|
541
|
-
if (right)
|
|
557
|
+
if (right) {
|
|
558
|
+
m.rightMargin = parseFloat(right);
|
|
559
|
+
m.rightMarginRaw = right;
|
|
560
|
+
}
|
|
542
561
|
const top = getElementText(content, "top-margin");
|
|
543
|
-
if (top)
|
|
562
|
+
if (top) {
|
|
563
|
+
m.topMargin = parseFloat(top);
|
|
564
|
+
m.topMarginRaw = top;
|
|
565
|
+
}
|
|
544
566
|
const bottom = getElementText(content, "bottom-margin");
|
|
545
|
-
if (bottom)
|
|
567
|
+
if (bottom) {
|
|
568
|
+
m.bottomMargin = parseFloat(bottom);
|
|
569
|
+
m.bottomMarginRaw = bottom;
|
|
570
|
+
}
|
|
546
571
|
margins.push(m);
|
|
547
572
|
}
|
|
548
573
|
}
|
|
@@ -555,14 +580,48 @@ function parseSystemLayout(elements) {
|
|
|
555
580
|
if (margins) {
|
|
556
581
|
layout.systemMargins = {};
|
|
557
582
|
const left = getElementText(margins, "left-margin");
|
|
558
|
-
if (left)
|
|
583
|
+
if (left) {
|
|
584
|
+
layout.systemMargins.leftMargin = parseFloat(left);
|
|
585
|
+
layout.systemMargins.leftMarginRaw = left;
|
|
586
|
+
}
|
|
559
587
|
const right = getElementText(margins, "right-margin");
|
|
560
|
-
if (right)
|
|
588
|
+
if (right) {
|
|
589
|
+
layout.systemMargins.rightMargin = parseFloat(right);
|
|
590
|
+
layout.systemMargins.rightMarginRaw = right;
|
|
591
|
+
}
|
|
561
592
|
}
|
|
562
593
|
const dist = getElementText(elements, "system-distance");
|
|
563
|
-
if (dist)
|
|
594
|
+
if (dist) {
|
|
595
|
+
layout.systemDistance = parseFloat(dist);
|
|
596
|
+
layout.systemDistanceRaw = dist;
|
|
597
|
+
}
|
|
564
598
|
const topDist = getElementText(elements, "top-system-distance");
|
|
565
|
-
if (topDist)
|
|
599
|
+
if (topDist) {
|
|
600
|
+
layout.topSystemDistance = parseFloat(topDist);
|
|
601
|
+
layout.topSystemDistanceRaw = topDist;
|
|
602
|
+
}
|
|
603
|
+
const dividers = getElementContent(elements, "system-dividers");
|
|
604
|
+
if (dividers) {
|
|
605
|
+
layout.systemDividers = {};
|
|
606
|
+
for (const el of dividers) {
|
|
607
|
+
if (el["left-divider"]) {
|
|
608
|
+
const attrs = getAttributes(el);
|
|
609
|
+
layout.systemDividers.leftDivider = {
|
|
610
|
+
printObject: attrs["print-object"] === "yes" ? true : attrs["print-object"] === "no" ? false : void 0,
|
|
611
|
+
halign: attrs["halign"],
|
|
612
|
+
valign: attrs["valign"]
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
if (el["right-divider"]) {
|
|
616
|
+
const attrs = getAttributes(el);
|
|
617
|
+
layout.systemDividers.rightDivider = {
|
|
618
|
+
printObject: attrs["print-object"] === "yes" ? true : attrs["print-object"] === "no" ? false : void 0,
|
|
619
|
+
halign: attrs["halign"],
|
|
620
|
+
valign: attrs["valign"]
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
566
625
|
return layout;
|
|
567
626
|
}
|
|
568
627
|
function parseCredits(elements) {
|
|
@@ -574,6 +633,7 @@ function parseCredits(elements) {
|
|
|
574
633
|
const cw = { text: extractText(c) };
|
|
575
634
|
if (a["default-x"]) cw.defaultX = parseFloat(a["default-x"]);
|
|
576
635
|
if (a["default-y"]) cw.defaultY = parseFloat(a["default-y"]);
|
|
636
|
+
if (a["font-family"]) cw.fontFamily = a["font-family"];
|
|
577
637
|
if (a["font-size"]) cw.fontSize = a["font-size"];
|
|
578
638
|
if (a["font-weight"]) cw.fontWeight = a["font-weight"];
|
|
579
639
|
if (a["font-style"]) cw.fontStyle = a["font-style"];
|
|
@@ -797,6 +857,15 @@ function parseMeasure(elements, attrs) {
|
|
|
797
857
|
measure.entries.push(parseFiguredBass(el["figured-bass"], getAttributes(el)));
|
|
798
858
|
} else if (el["sound"]) {
|
|
799
859
|
measure.entries.push(parseSound(el["sound"], getAttributes(el)));
|
|
860
|
+
} else if (el["grouping"] !== void 0) {
|
|
861
|
+
const grpAttrs = getAttributes(el);
|
|
862
|
+
const grouping = {
|
|
863
|
+
_id: generateId(),
|
|
864
|
+
type: "grouping",
|
|
865
|
+
groupingType: grpAttrs["type"] || "start"
|
|
866
|
+
};
|
|
867
|
+
if (grpAttrs["number"]) grouping.number = grpAttrs["number"];
|
|
868
|
+
measure.entries.push(grouping);
|
|
800
869
|
}
|
|
801
870
|
}
|
|
802
871
|
if (barlines.length > 0) measure.barlines = barlines;
|
|
@@ -863,6 +932,7 @@ function parseAttributes(elements) {
|
|
|
863
932
|
const key = parseKeySignature(keyContent);
|
|
864
933
|
if (keyAttrs["number"]) key.number = parseInt(keyAttrs["number"], 10);
|
|
865
934
|
if (keyAttrs["print-object"] === "no") key.printObject = false;
|
|
935
|
+
else if (keyAttrs["print-object"] === "yes") key.printObject = true;
|
|
866
936
|
keys.push(key);
|
|
867
937
|
}
|
|
868
938
|
}
|
|
@@ -914,14 +984,15 @@ function parseTimeSignature(elements, parentElements) {
|
|
|
914
984
|
return time2;
|
|
915
985
|
}
|
|
916
986
|
}
|
|
917
|
-
const
|
|
987
|
+
const beatsStrList = collectElements(elements, "beats", (c) => extractText(c));
|
|
918
988
|
const beatTypeList = collectElements(elements, "beat-type", (c) => parseInt(extractText(c), 10));
|
|
919
989
|
const time = {
|
|
920
|
-
beats:
|
|
990
|
+
beats: beatsStrList.length > 0 ? beatsStrList[0] : "4",
|
|
921
991
|
beatType: beatTypeList.length > 0 ? beatTypeList[0] : 4
|
|
922
992
|
};
|
|
923
|
-
if (
|
|
924
|
-
time.beatsList =
|
|
993
|
+
if (beatsStrList.length > 1 || beatTypeList.length > 1) {
|
|
994
|
+
time.beatsList = beatsStrList.map((b) => parseInt(b, 10));
|
|
995
|
+
time.beatsStrList = beatsStrList;
|
|
925
996
|
time.beatTypeList = beatTypeList;
|
|
926
997
|
}
|
|
927
998
|
for (const el of parentElements) {
|
|
@@ -960,6 +1031,7 @@ function parseKeySignature(elements) {
|
|
|
960
1031
|
const keyOctaves = collectElements(elements, "key-octave", (c, a) => {
|
|
961
1032
|
const ko = { number: parseInt(a["number"] || "1", 10), octave: parseInt(extractText(c), 10) };
|
|
962
1033
|
if (a["cancel"] === "yes") ko.cancel = true;
|
|
1034
|
+
else if (a["cancel"] === "no") ko.cancel = false;
|
|
963
1035
|
return ko;
|
|
964
1036
|
});
|
|
965
1037
|
if (keySteps.length > 0) key.keySteps = keySteps;
|
|
@@ -969,8 +1041,11 @@ function parseKeySignature(elements) {
|
|
|
969
1041
|
}
|
|
970
1042
|
function parseClef(elements, attrs) {
|
|
971
1043
|
const sign = getElementText(elements, "sign") || "G";
|
|
972
|
-
const
|
|
973
|
-
const clef = { sign
|
|
1044
|
+
const lineText = getElementText(elements, "line");
|
|
1045
|
+
const clef = { sign };
|
|
1046
|
+
if (lineText) {
|
|
1047
|
+
clef.line = parseInt(lineText, 10);
|
|
1048
|
+
}
|
|
974
1049
|
if (attrs["number"]) {
|
|
975
1050
|
clef.staff = parseInt(attrs["number"], 10);
|
|
976
1051
|
}
|
|
@@ -980,6 +1055,8 @@ function parseClef(elements, attrs) {
|
|
|
980
1055
|
}
|
|
981
1056
|
if (attrs["print-object"] === "no") {
|
|
982
1057
|
clef.printObject = false;
|
|
1058
|
+
} else if (attrs["print-object"] === "yes") {
|
|
1059
|
+
clef.printObject = true;
|
|
983
1060
|
}
|
|
984
1061
|
if (attrs["after-barline"] === "yes") {
|
|
985
1062
|
clef.afterBarline = true;
|
|
@@ -1001,15 +1078,20 @@ function parseNote(elements, attrs) {
|
|
|
1001
1078
|
const note = {
|
|
1002
1079
|
_id: generateId(),
|
|
1003
1080
|
type: "note",
|
|
1004
|
-
duration: getElementTextAsInt(elements, "duration", 0)
|
|
1005
|
-
voice: getElementTextAsInt(elements, "voice", 1)
|
|
1081
|
+
duration: getElementTextAsInt(elements, "duration", 0)
|
|
1006
1082
|
};
|
|
1083
|
+
const voiceValue = getElementTextAsInt(elements, "voice");
|
|
1084
|
+
if (voiceValue !== void 0) {
|
|
1085
|
+
note.voice = voiceValue;
|
|
1086
|
+
}
|
|
1007
1087
|
if (attrs["default-x"]) note.defaultX = parseFloat(attrs["default-x"]);
|
|
1008
1088
|
if (attrs["default-y"]) note.defaultY = parseFloat(attrs["default-y"]);
|
|
1009
1089
|
if (attrs["relative-x"]) note.relativeX = parseFloat(attrs["relative-x"]);
|
|
1010
1090
|
if (attrs["relative-y"]) note.relativeY = parseFloat(attrs["relative-y"]);
|
|
1011
1091
|
if (attrs["dynamics"]) note.dynamics = parseFloat(attrs["dynamics"]);
|
|
1012
1092
|
if (attrs["print-object"] === "no") note.printObject = false;
|
|
1093
|
+
if (attrs["print-dot"] === "no") note.printDot = false;
|
|
1094
|
+
if (attrs["print-dot"] === "yes") note.printDot = true;
|
|
1013
1095
|
if (attrs["print-spacing"] === "yes") note.printSpacing = true;
|
|
1014
1096
|
if (attrs["print-spacing"] === "no") note.printSpacing = false;
|
|
1015
1097
|
if (hasElement(elements, "cue")) {
|
|
@@ -1122,6 +1204,7 @@ function parseNote(elements, attrs) {
|
|
|
1122
1204
|
const graceAttrs = getAttributes(el);
|
|
1123
1205
|
note.grace = {};
|
|
1124
1206
|
if (graceAttrs["slash"] === "yes") note.grace.slash = true;
|
|
1207
|
+
else if (graceAttrs["slash"] === "no") note.grace.slash = false;
|
|
1125
1208
|
if (graceAttrs["steal-time-previous"]) {
|
|
1126
1209
|
note.grace.stealTimePrevious = parseFloat(graceAttrs["steal-time-previous"]);
|
|
1127
1210
|
}
|
|
@@ -1367,6 +1450,14 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1367
1450
|
notations.push(tremNotation);
|
|
1368
1451
|
}
|
|
1369
1452
|
}
|
|
1453
|
+
const ornamentNotationsAdded = notations.filter((n) => n.type === "ornament" && n.notationsIndex === notationsIndex);
|
|
1454
|
+
if (ornamentNotationsAdded.length === 0) {
|
|
1455
|
+
notations.push({
|
|
1456
|
+
type: "ornament",
|
|
1457
|
+
ornament: "empty",
|
|
1458
|
+
notationsIndex
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1370
1461
|
} else if (el["technical"]) {
|
|
1371
1462
|
const techContent = el["technical"];
|
|
1372
1463
|
const technicalWithText = ["hammer-on", "pull-off", "tap", "pluck", "fingering", "other-technical"];
|
|
@@ -1416,8 +1507,7 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1416
1507
|
if (bendAlter) techNotation.bendAlter = parseFloat(bendAlter);
|
|
1417
1508
|
if (hasElement(bendContent, "pre-bend")) techNotation.preBend = true;
|
|
1418
1509
|
if (hasElement(bendContent, "release")) techNotation.release = true;
|
|
1419
|
-
|
|
1420
|
-
if (withBar) techNotation.withBar = parseFloat(withBar);
|
|
1510
|
+
if (hasElement(bendContent, "with-bar")) techNotation.withBar = true;
|
|
1421
1511
|
notations.push(techNotation);
|
|
1422
1512
|
}
|
|
1423
1513
|
for (const techType of technicalTypes) {
|
|
@@ -1454,6 +1544,7 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1454
1544
|
if (typeAttr === "start" || typeAttr === "stop") {
|
|
1455
1545
|
notation.startStop = typeAttr;
|
|
1456
1546
|
}
|
|
1547
|
+
if (techAttrs["number"]) notation.number = parseInt(techAttrs["number"], 10);
|
|
1457
1548
|
}
|
|
1458
1549
|
if (techType === "fingering") {
|
|
1459
1550
|
if (techAttrs["substitution"] === "yes") notation.fingeringSubstitution = true;
|
|
@@ -1536,11 +1627,33 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1536
1627
|
notations.push(fermataNotation);
|
|
1537
1628
|
} else if (el["arpeggiate"] !== void 0) {
|
|
1538
1629
|
const arpAttrs = getAttributes(el);
|
|
1539
|
-
|
|
1630
|
+
const arpNotation = {
|
|
1540
1631
|
type: "arpeggiate",
|
|
1541
1632
|
direction: arpAttrs["direction"],
|
|
1542
1633
|
number: arpAttrs["number"] ? parseInt(arpAttrs["number"], 10) : void 0,
|
|
1543
1634
|
notationsIndex
|
|
1635
|
+
};
|
|
1636
|
+
if (arpAttrs["default-x"]) arpNotation.defaultX = parseFloat(arpAttrs["default-x"]);
|
|
1637
|
+
if (arpAttrs["default-y"]) arpNotation.defaultY = parseFloat(arpAttrs["default-y"]);
|
|
1638
|
+
notations.push(arpNotation);
|
|
1639
|
+
} else if (el["non-arpeggiate"] !== void 0) {
|
|
1640
|
+
const nonArpAttrs = getAttributes(el);
|
|
1641
|
+
notations.push({
|
|
1642
|
+
type: "non-arpeggiate",
|
|
1643
|
+
nonArpeggiateType: nonArpAttrs["type"],
|
|
1644
|
+
number: nonArpAttrs["number"] ? parseInt(nonArpAttrs["number"], 10) : void 0,
|
|
1645
|
+
placement: nonArpAttrs["placement"],
|
|
1646
|
+
notationsIndex
|
|
1647
|
+
});
|
|
1648
|
+
} else if (el["accidental-mark"]) {
|
|
1649
|
+
const amAttrs = getAttributes(el);
|
|
1650
|
+
const amContent = el["accidental-mark"];
|
|
1651
|
+
const value = extractText(amContent);
|
|
1652
|
+
notations.push({
|
|
1653
|
+
type: "accidental-mark",
|
|
1654
|
+
value,
|
|
1655
|
+
placement: amAttrs["placement"],
|
|
1656
|
+
notationsIndex
|
|
1544
1657
|
});
|
|
1545
1658
|
} else if (el["glissando"]) {
|
|
1546
1659
|
const glissAttrs = getAttributes(el);
|
|
@@ -1562,13 +1675,17 @@ function parseNotations(elements, notationsIndex = 0) {
|
|
|
1562
1675
|
});
|
|
1563
1676
|
} else if (el["slide"]) {
|
|
1564
1677
|
const slideAttrs = getAttributes(el);
|
|
1565
|
-
|
|
1678
|
+
const slideContent = el["slide"];
|
|
1679
|
+
const slideText = extractText(slideContent);
|
|
1680
|
+
const slideNotation = {
|
|
1566
1681
|
type: "slide",
|
|
1567
1682
|
slideType: slideAttrs["type"] === "stop" ? "stop" : "start",
|
|
1568
1683
|
number: slideAttrs["number"] ? parseInt(slideAttrs["number"], 10) : void 0,
|
|
1569
1684
|
lineType: slideAttrs["line-type"],
|
|
1570
1685
|
notationsIndex
|
|
1571
|
-
}
|
|
1686
|
+
};
|
|
1687
|
+
if (slideText) slideNotation.text = slideText;
|
|
1688
|
+
notations.push(slideNotation);
|
|
1572
1689
|
}
|
|
1573
1690
|
}
|
|
1574
1691
|
return notations;
|
|
@@ -1589,8 +1706,9 @@ function parseLyric(elements, attrs) {
|
|
|
1589
1706
|
break;
|
|
1590
1707
|
}
|
|
1591
1708
|
}
|
|
1592
|
-
} else if (el["text"]) {
|
|
1709
|
+
} else if (el["text"] !== void 0) {
|
|
1593
1710
|
const content = el["text"];
|
|
1711
|
+
let foundText = false;
|
|
1594
1712
|
for (const item of content) {
|
|
1595
1713
|
if (item["#text"] !== void 0) {
|
|
1596
1714
|
textElements.push({
|
|
@@ -1598,9 +1716,17 @@ function parseLyric(elements, attrs) {
|
|
|
1598
1716
|
syllabic: currentSyllabic
|
|
1599
1717
|
});
|
|
1600
1718
|
currentSyllabic = void 0;
|
|
1719
|
+
foundText = true;
|
|
1601
1720
|
break;
|
|
1602
1721
|
}
|
|
1603
1722
|
}
|
|
1723
|
+
if (!foundText) {
|
|
1724
|
+
textElements.push({
|
|
1725
|
+
text: "",
|
|
1726
|
+
syllabic: currentSyllabic
|
|
1727
|
+
});
|
|
1728
|
+
currentSyllabic = void 0;
|
|
1729
|
+
}
|
|
1604
1730
|
} else if (el["elision"] !== void 0) {
|
|
1605
1731
|
hasElision = true;
|
|
1606
1732
|
}
|
|
@@ -1769,6 +1895,7 @@ function parseDirectionTypes(elements) {
|
|
|
1769
1895
|
"pf"
|
|
1770
1896
|
];
|
|
1771
1897
|
for (const dyn of dynContent) {
|
|
1898
|
+
let foundStandard = false;
|
|
1772
1899
|
for (const dv of dynamicsValues) {
|
|
1773
1900
|
if (dyn[dv] !== void 0) {
|
|
1774
1901
|
const result = { kind: "dynamics", value: dv };
|
|
@@ -1777,9 +1904,22 @@ function parseDirectionTypes(elements) {
|
|
|
1777
1904
|
if (dynAttrs["relative-x"]) result.relativeX = parseFloat(dynAttrs["relative-x"]);
|
|
1778
1905
|
if (dynAttrs["halign"]) result.halign = dynAttrs["halign"];
|
|
1779
1906
|
results.push(result);
|
|
1907
|
+
foundStandard = true;
|
|
1780
1908
|
break;
|
|
1781
1909
|
}
|
|
1782
1910
|
}
|
|
1911
|
+
if (!foundStandard && dyn["other-dynamics"] !== void 0) {
|
|
1912
|
+
const otherDynContent = dyn["other-dynamics"];
|
|
1913
|
+
const otherDynText = extractText(otherDynContent);
|
|
1914
|
+
if (otherDynText) {
|
|
1915
|
+
const result = { kind: "dynamics", otherDynamics: otherDynText };
|
|
1916
|
+
if (dynAttrs["default-x"]) result.defaultX = parseFloat(dynAttrs["default-x"]);
|
|
1917
|
+
if (dynAttrs["default-y"]) result.defaultY = parseFloat(dynAttrs["default-y"]);
|
|
1918
|
+
if (dynAttrs["relative-x"]) result.relativeX = parseFloat(dynAttrs["relative-x"]);
|
|
1919
|
+
if (dynAttrs["halign"]) result.halign = dynAttrs["halign"];
|
|
1920
|
+
results.push(result);
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1783
1923
|
}
|
|
1784
1924
|
continue;
|
|
1785
1925
|
}
|
|
@@ -1904,11 +2044,14 @@ function parseDirectionTypes(elements) {
|
|
|
1904
2044
|
for (const acc of accContent) {
|
|
1905
2045
|
if (acc["accordion-high"] !== void 0) {
|
|
1906
2046
|
result.high = true;
|
|
1907
|
-
} else if (acc["accordion-middle"]) {
|
|
2047
|
+
} else if (acc["accordion-middle"] !== void 0) {
|
|
2048
|
+
result.middlePresent = true;
|
|
1908
2049
|
const midContent = acc["accordion-middle"];
|
|
1909
2050
|
for (const item of midContent) {
|
|
1910
2051
|
if (item["#text"] !== void 0) {
|
|
1911
|
-
|
|
2052
|
+
const textValue = String(item["#text"]);
|
|
2053
|
+
const numValue = parseInt(textValue, 10);
|
|
2054
|
+
result.middle = !isNaN(numValue) ? numValue : textValue;
|
|
1912
2055
|
break;
|
|
1913
2056
|
}
|
|
1914
2057
|
}
|
|
@@ -2085,6 +2228,9 @@ function parseBarline(elements, attrs) {
|
|
|
2085
2228
|
if (repeatAttrs["times"]) {
|
|
2086
2229
|
barline.repeat.times = parseInt(repeatAttrs["times"], 10);
|
|
2087
2230
|
}
|
|
2231
|
+
if (repeatAttrs["winged"]) {
|
|
2232
|
+
barline.repeat.winged = repeatAttrs["winged"];
|
|
2233
|
+
}
|
|
2088
2234
|
}
|
|
2089
2235
|
} else if (el["ending"]) {
|
|
2090
2236
|
const endingAttrs = getAttributes(el);
|
|
@@ -2092,6 +2238,11 @@ function parseBarline(elements, attrs) {
|
|
|
2092
2238
|
const type = endingAttrs["type"];
|
|
2093
2239
|
if (number && (type === "start" || type === "stop" || type === "discontinue")) {
|
|
2094
2240
|
barline.ending = { number, type };
|
|
2241
|
+
const endingContent = el["ending"];
|
|
2242
|
+
const endingText = extractText(endingContent);
|
|
2243
|
+
if (endingText) barline.ending.text = endingText;
|
|
2244
|
+
if (endingAttrs["default-y"]) barline.ending.defaultY = parseFloat(endingAttrs["default-y"]);
|
|
2245
|
+
if (endingAttrs["end-length"]) barline.ending.endLength = parseFloat(endingAttrs["end-length"]);
|
|
2095
2246
|
}
|
|
2096
2247
|
}
|
|
2097
2248
|
}
|
|
@@ -2217,6 +2368,8 @@ function parseStaffDetails(elements, attrs) {
|
|
|
2217
2368
|
if (attrs["number"]) sd.number = parseInt(attrs["number"], 10);
|
|
2218
2369
|
if (attrs["print-object"] === "no") sd.printObject = false;
|
|
2219
2370
|
else if (attrs["print-object"] === "yes") sd.printObject = true;
|
|
2371
|
+
if (attrs["print-spacing"] === "yes") sd.printSpacing = true;
|
|
2372
|
+
else if (attrs["print-spacing"] === "no") sd.printSpacing = false;
|
|
2220
2373
|
const staffType = getElementText(elements, "staff-type");
|
|
2221
2374
|
if (staffType && ["ossia", "cue", "editorial", "regular", "alternate"].includes(staffType)) {
|
|
2222
2375
|
sd.staffType = staffType;
|
|
@@ -2280,7 +2433,9 @@ function parseMeasureStyle(elements, attrs) {
|
|
|
2280
2433
|
const slAttrs = getAttributes(el);
|
|
2281
2434
|
ms.slash = { type: slAttrs["type"] === "stop" ? "stop" : "start" };
|
|
2282
2435
|
if (slAttrs["use-dots"] === "yes") ms.slash.useDots = true;
|
|
2436
|
+
else if (slAttrs["use-dots"] === "no") ms.slash.useDots = false;
|
|
2283
2437
|
if (slAttrs["use-stems"] === "yes") ms.slash.useStems = true;
|
|
2438
|
+
else if (slAttrs["use-stems"] === "no") ms.slash.useStems = false;
|
|
2284
2439
|
}
|
|
2285
2440
|
}
|
|
2286
2441
|
return ms;
|
|
@@ -2320,19 +2475,29 @@ function parseHarmony(elements, attrs) {
|
|
|
2320
2475
|
break;
|
|
2321
2476
|
}
|
|
2322
2477
|
}
|
|
2323
|
-
if (kindAttrs["text"]) harmony.kindText = kindAttrs["text"];
|
|
2478
|
+
if (kindAttrs["text"] !== void 0) harmony.kindText = kindAttrs["text"];
|
|
2479
|
+
if (kindAttrs["halign"]) harmony.kindHalign = kindAttrs["halign"];
|
|
2324
2480
|
break;
|
|
2325
2481
|
}
|
|
2326
2482
|
}
|
|
2327
|
-
const
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2483
|
+
for (const el of elements) {
|
|
2484
|
+
if (el["bass"]) {
|
|
2485
|
+
const bassAttrs = getAttributes(el);
|
|
2486
|
+
const bassContent = el["bass"];
|
|
2487
|
+
const bassStep = getElementText(bassContent, "bass-step");
|
|
2488
|
+
if (bassStep) {
|
|
2489
|
+
harmony.bass = { bassStep };
|
|
2490
|
+
const bassAlter = getElementText(bassContent, "bass-alter");
|
|
2491
|
+
if (bassAlter) harmony.bass.bassAlter = parseFloat(bassAlter);
|
|
2492
|
+
if (bassAttrs["arrangement"]) harmony.bass.arrangement = bassAttrs["arrangement"];
|
|
2493
|
+
}
|
|
2494
|
+
break;
|
|
2334
2495
|
}
|
|
2335
2496
|
}
|
|
2497
|
+
const inversionText = getElementText(elements, "inversion");
|
|
2498
|
+
if (inversionText) {
|
|
2499
|
+
harmony.inversion = parseInt(inversionText, 10);
|
|
2500
|
+
}
|
|
2336
2501
|
const degrees = [];
|
|
2337
2502
|
for (const el of elements) {
|
|
2338
2503
|
if (el["degree"]) {
|
|
@@ -3099,7 +3264,7 @@ function validateVoiceStaff(measure, staves, location) {
|
|
|
3099
3264
|
for (let entryIndex = 0; entryIndex < measure.entries.length; entryIndex++) {
|
|
3100
3265
|
const entry = measure.entries[entryIndex];
|
|
3101
3266
|
if (entry.type !== "note") continue;
|
|
3102
|
-
if (entry.voice <= 0) {
|
|
3267
|
+
if (entry.voice !== void 0 && entry.voice <= 0) {
|
|
3103
3268
|
errors.push({
|
|
3104
3269
|
code: "INVALID_VOICE_NUMBER",
|
|
3105
3270
|
level: "error",
|
|
@@ -3595,7 +3760,7 @@ function validateSlursAcrossMeasures(part) {
|
|
|
3595
3760
|
|
|
3596
3761
|
// src/exporters/musicxml.ts
|
|
3597
3762
|
function serialize(score, options = {}) {
|
|
3598
|
-
const version = options.version || "4.0";
|
|
3763
|
+
const version = options.version || score.version || "4.0";
|
|
3599
3764
|
const indent = options.indent ?? " ";
|
|
3600
3765
|
if (options.validate) {
|
|
3601
3766
|
const result = validate(score, options.validateOptions);
|
|
@@ -3610,11 +3775,7 @@ ${errorMessages}`);
|
|
|
3610
3775
|
}
|
|
3611
3776
|
const lines = [];
|
|
3612
3777
|
lines.push('<?xml version="1.0" encoding="UTF-8"?>');
|
|
3613
|
-
|
|
3614
|
-
lines.push('<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 4.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">');
|
|
3615
|
-
} else {
|
|
3616
|
-
lines.push('<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">');
|
|
3617
|
-
}
|
|
3778
|
+
lines.push(`<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML ${version} Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">`);
|
|
3618
3779
|
lines.push(`<score-partwise version="${version}">`);
|
|
3619
3780
|
lines.push(...serializeMetadata(score.metadata, indent));
|
|
3620
3781
|
if (score.defaults) {
|
|
@@ -3748,6 +3909,11 @@ function serializeDefaults(defaults, indent) {
|
|
|
3748
3909
|
lines.push(`${indent}${indent}${indent}<distance type="${escapeXml(d.type)}">${d.value}</distance>`);
|
|
3749
3910
|
}
|
|
3750
3911
|
}
|
|
3912
|
+
if (app["glyphs"]) {
|
|
3913
|
+
for (const g of app["glyphs"]) {
|
|
3914
|
+
lines.push(`${indent}${indent}${indent}<glyph type="${escapeXml(g.type)}">${escapeXml(g.value)}</glyph>`);
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3751
3917
|
lines.push(`${indent}${indent}</appearance>`);
|
|
3752
3918
|
}
|
|
3753
3919
|
if (defaults.musicFont) {
|
|
@@ -3804,16 +3970,16 @@ function serializePageLayout(layout, indent) {
|
|
|
3804
3970
|
const typeAttr = m.type ? ` type="${m.type}"` : "";
|
|
3805
3971
|
lines.push(`${indent} <page-margins${typeAttr}>`);
|
|
3806
3972
|
if (m.leftMargin !== void 0) {
|
|
3807
|
-
lines.push(`${indent} <left-margin>${m.leftMargin}</left-margin>`);
|
|
3973
|
+
lines.push(`${indent} <left-margin>${m.leftMarginRaw ?? m.leftMargin}</left-margin>`);
|
|
3808
3974
|
}
|
|
3809
3975
|
if (m.rightMargin !== void 0) {
|
|
3810
|
-
lines.push(`${indent} <right-margin>${m.rightMargin}</right-margin>`);
|
|
3976
|
+
lines.push(`${indent} <right-margin>${m.rightMarginRaw ?? m.rightMargin}</right-margin>`);
|
|
3811
3977
|
}
|
|
3812
3978
|
if (m.topMargin !== void 0) {
|
|
3813
|
-
lines.push(`${indent} <top-margin>${m.topMargin}</top-margin>`);
|
|
3979
|
+
lines.push(`${indent} <top-margin>${m.topMarginRaw ?? m.topMargin}</top-margin>`);
|
|
3814
3980
|
}
|
|
3815
3981
|
if (m.bottomMargin !== void 0) {
|
|
3816
|
-
lines.push(`${indent} <bottom-margin>${m.bottomMargin}</bottom-margin>`);
|
|
3982
|
+
lines.push(`${indent} <bottom-margin>${m.bottomMarginRaw ?? m.bottomMargin}</bottom-margin>`);
|
|
3817
3983
|
}
|
|
3818
3984
|
lines.push(`${indent} </page-margins>`);
|
|
3819
3985
|
}
|
|
@@ -3827,18 +3993,48 @@ function serializeSystemLayout(layout, indent) {
|
|
|
3827
3993
|
if (layout.systemMargins) {
|
|
3828
3994
|
lines.push(`${indent} <system-margins>`);
|
|
3829
3995
|
if (layout.systemMargins.leftMargin !== void 0) {
|
|
3830
|
-
lines.push(`${indent} <left-margin>${layout.systemMargins.leftMargin}</left-margin>`);
|
|
3996
|
+
lines.push(`${indent} <left-margin>${layout.systemMargins.leftMarginRaw ?? layout.systemMargins.leftMargin}</left-margin>`);
|
|
3831
3997
|
}
|
|
3832
3998
|
if (layout.systemMargins.rightMargin !== void 0) {
|
|
3833
|
-
lines.push(`${indent} <right-margin>${layout.systemMargins.rightMargin}</right-margin>`);
|
|
3999
|
+
lines.push(`${indent} <right-margin>${layout.systemMargins.rightMarginRaw ?? layout.systemMargins.rightMargin}</right-margin>`);
|
|
3834
4000
|
}
|
|
3835
4001
|
lines.push(`${indent} </system-margins>`);
|
|
3836
4002
|
}
|
|
3837
4003
|
if (layout.systemDistance !== void 0) {
|
|
3838
|
-
lines.push(`${indent} <system-distance>${layout.systemDistance}</system-distance>`);
|
|
4004
|
+
lines.push(`${indent} <system-distance>${layout.systemDistanceRaw ?? layout.systemDistance}</system-distance>`);
|
|
3839
4005
|
}
|
|
3840
4006
|
if (layout.topSystemDistance !== void 0) {
|
|
3841
|
-
lines.push(`${indent} <top-system-distance>${layout.topSystemDistance}</top-system-distance>`);
|
|
4007
|
+
lines.push(`${indent} <top-system-distance>${layout.topSystemDistanceRaw ?? layout.topSystemDistance}</top-system-distance>`);
|
|
4008
|
+
}
|
|
4009
|
+
if (layout.systemDividers) {
|
|
4010
|
+
lines.push(`${indent} <system-dividers>`);
|
|
4011
|
+
if (layout.systemDividers.leftDivider) {
|
|
4012
|
+
let attrs = "";
|
|
4013
|
+
if (layout.systemDividers.leftDivider.printObject !== void 0) {
|
|
4014
|
+
attrs += ` print-object="${layout.systemDividers.leftDivider.printObject ? "yes" : "no"}"`;
|
|
4015
|
+
}
|
|
4016
|
+
if (layout.systemDividers.leftDivider.halign) {
|
|
4017
|
+
attrs += ` halign="${layout.systemDividers.leftDivider.halign}"`;
|
|
4018
|
+
}
|
|
4019
|
+
if (layout.systemDividers.leftDivider.valign) {
|
|
4020
|
+
attrs += ` valign="${layout.systemDividers.leftDivider.valign}"`;
|
|
4021
|
+
}
|
|
4022
|
+
lines.push(`${indent} <left-divider${attrs}/>`);
|
|
4023
|
+
}
|
|
4024
|
+
if (layout.systemDividers.rightDivider) {
|
|
4025
|
+
let attrs = "";
|
|
4026
|
+
if (layout.systemDividers.rightDivider.printObject !== void 0) {
|
|
4027
|
+
attrs += ` print-object="${layout.systemDividers.rightDivider.printObject ? "yes" : "no"}"`;
|
|
4028
|
+
}
|
|
4029
|
+
if (layout.systemDividers.rightDivider.halign) {
|
|
4030
|
+
attrs += ` halign="${layout.systemDividers.rightDivider.halign}"`;
|
|
4031
|
+
}
|
|
4032
|
+
if (layout.systemDividers.rightDivider.valign) {
|
|
4033
|
+
attrs += ` valign="${layout.systemDividers.rightDivider.valign}"`;
|
|
4034
|
+
}
|
|
4035
|
+
lines.push(`${indent} <right-divider${attrs}/>`);
|
|
4036
|
+
}
|
|
4037
|
+
lines.push(`${indent} </system-dividers>`);
|
|
3842
4038
|
}
|
|
3843
4039
|
lines.push(`${indent}</system-layout>`);
|
|
3844
4040
|
return lines;
|
|
@@ -3859,6 +4055,7 @@ function serializeCredit(credit, indent) {
|
|
|
3859
4055
|
let attrs2 = "";
|
|
3860
4056
|
if (cw.defaultX !== void 0) attrs2 += ` default-x="${cw.defaultX}"`;
|
|
3861
4057
|
if (cw.defaultY !== void 0) attrs2 += ` default-y="${cw.defaultY}"`;
|
|
4058
|
+
if (cw.fontFamily) attrs2 += ` font-family="${escapeXml(cw.fontFamily)}"`;
|
|
3862
4059
|
if (cw.fontSize) attrs2 += ` font-size="${escapeXml(cw.fontSize)}"`;
|
|
3863
4060
|
if (cw.fontWeight) attrs2 += ` font-weight="${escapeXml(cw.fontWeight)}"`;
|
|
3864
4061
|
if (cw.fontStyle) attrs2 += ` font-style="${escapeXml(cw.fontStyle)}"`;
|
|
@@ -4153,6 +4350,7 @@ function serializeKey(key, indent) {
|
|
|
4153
4350
|
let keyAttrs = "";
|
|
4154
4351
|
if (key.number !== void 0) keyAttrs += ` number="${key.number}"`;
|
|
4155
4352
|
if (key.printObject === false) keyAttrs += ' print-object="no"';
|
|
4353
|
+
else if (key.printObject === true) keyAttrs += ' print-object="yes"';
|
|
4156
4354
|
lines.push(`${indent}<key${keyAttrs}>`);
|
|
4157
4355
|
if (key.cancel !== void 0) {
|
|
4158
4356
|
const locationAttr = key.cancelLocation ? ` location="${key.cancelLocation}"` : "";
|
|
@@ -4200,7 +4398,8 @@ function serializeTime(time, indent) {
|
|
|
4200
4398
|
const maxLen = Math.max(time.beatsList.length, time.beatTypeList.length);
|
|
4201
4399
|
for (let i = 0; i < maxLen; i++) {
|
|
4202
4400
|
if (i < time.beatsList.length) {
|
|
4203
|
-
|
|
4401
|
+
const beatsValue = time.beatsStrList && i < time.beatsStrList.length ? time.beatsStrList[i] : time.beatsList[i];
|
|
4402
|
+
lines.push(`${indent} <beats>${beatsValue}</beats>`);
|
|
4204
4403
|
}
|
|
4205
4404
|
if (i < time.beatTypeList.length) {
|
|
4206
4405
|
lines.push(`${indent} <beat-type>${time.beatTypeList[i]}</beat-type>`);
|
|
@@ -4217,10 +4416,13 @@ function serializeClef(clef, indent) {
|
|
|
4217
4416
|
const lines = [];
|
|
4218
4417
|
let attrs = clef.staff ? ` number="${clef.staff}"` : "";
|
|
4219
4418
|
if (clef.printObject === false) attrs += ' print-object="no"';
|
|
4419
|
+
else if (clef.printObject === true) attrs += ' print-object="yes"';
|
|
4220
4420
|
if (clef.afterBarline) attrs += ' after-barline="yes"';
|
|
4221
4421
|
lines.push(`${indent}<clef${attrs}>`);
|
|
4222
4422
|
lines.push(`${indent} <sign>${clef.sign}</sign>`);
|
|
4223
|
-
|
|
4423
|
+
if (clef.line !== void 0) {
|
|
4424
|
+
lines.push(`${indent} <line>${clef.line}</line>`);
|
|
4425
|
+
}
|
|
4224
4426
|
if (clef.clefOctaveChange !== void 0) {
|
|
4225
4427
|
lines.push(`${indent} <clef-octave-change>${clef.clefOctaveChange}</clef-octave-change>`);
|
|
4226
4428
|
}
|
|
@@ -4256,6 +4458,12 @@ function serializeEntry(entry, indent) {
|
|
|
4256
4458
|
return serializeSound(entry, indent);
|
|
4257
4459
|
case "attributes":
|
|
4258
4460
|
return serializeAttributes(entry.attributes, indent, entry._id);
|
|
4461
|
+
case "grouping": {
|
|
4462
|
+
const grp = entry;
|
|
4463
|
+
let grpAttrs = ` type="${grp.groupingType}"`;
|
|
4464
|
+
if (grp.number) grpAttrs += ` number="${grp.number}"`;
|
|
4465
|
+
return [`${indent}<grouping${grpAttrs}/>`];
|
|
4466
|
+
}
|
|
4259
4467
|
default:
|
|
4260
4468
|
return [];
|
|
4261
4469
|
}
|
|
@@ -4270,12 +4478,13 @@ function serializeNote(note, indent) {
|
|
|
4270
4478
|
"relative-y": note.relativeY,
|
|
4271
4479
|
"dynamics": note.dynamics,
|
|
4272
4480
|
"print-object": note.printObject === false ? false : void 0,
|
|
4481
|
+
"print-dot": note.printDot !== void 0 ? note.printDot : void 0,
|
|
4273
4482
|
"print-spacing": note.printSpacing
|
|
4274
4483
|
});
|
|
4275
4484
|
lines.push(`${indent}<note${noteAttrs}>`);
|
|
4276
4485
|
if (note.grace) {
|
|
4277
4486
|
const graceAttrs = buildAttrs({
|
|
4278
|
-
"slash": note.grace.slash
|
|
4487
|
+
"slash": note.grace.slash !== void 0 ? note.grace.slash : void 0,
|
|
4279
4488
|
"steal-time-previous": note.grace.stealTimePrevious,
|
|
4280
4489
|
"steal-time-following": note.grace.stealTimeFollowing
|
|
4281
4490
|
});
|
|
@@ -4330,7 +4539,9 @@ function serializeNote(note, indent) {
|
|
|
4330
4539
|
} else if (note.tie) {
|
|
4331
4540
|
lines.push(`${indent} <tie type="${note.tie.type}"/>`);
|
|
4332
4541
|
}
|
|
4333
|
-
|
|
4542
|
+
if (note.voice !== void 0) {
|
|
4543
|
+
lines.push(`${indent} <voice>${note.voice}</voice>`);
|
|
4544
|
+
}
|
|
4334
4545
|
if (note.noteType) {
|
|
4335
4546
|
const typeAttrs = note.noteTypeSize ? ` size="${escapeXml(note.noteTypeSize)}"` : "";
|
|
4336
4547
|
lines.push(`${indent} <type${typeAttrs}>${note.noteType}</type>`);
|
|
@@ -4438,154 +4649,200 @@ function serializeNotations(notations, indent) {
|
|
|
4438
4649
|
function serializeNotationsGroup(notations, indent) {
|
|
4439
4650
|
const lines = [];
|
|
4440
4651
|
lines.push(`${indent}<notations>`);
|
|
4441
|
-
const
|
|
4442
|
-
const ornaments = [];
|
|
4443
|
-
const technicals = [];
|
|
4444
|
-
const others = [];
|
|
4652
|
+
const chunks = [];
|
|
4445
4653
|
for (const notation of notations) {
|
|
4446
4654
|
if (notation.type === "articulation") {
|
|
4447
4655
|
const artIdx = notation.articulationsIndex ?? 0;
|
|
4448
|
-
|
|
4449
|
-
|
|
4656
|
+
const last = chunks[chunks.length - 1];
|
|
4657
|
+
if (last && last.kind === "articulations" && last.articulationsIndex === artIdx) {
|
|
4658
|
+
last.items.push(notation);
|
|
4659
|
+
} else {
|
|
4660
|
+
chunks.push({ kind: "articulations", items: [notation], articulationsIndex: artIdx });
|
|
4450
4661
|
}
|
|
4451
|
-
articulationsGroups.get(artIdx).push(notation);
|
|
4452
4662
|
} else if (notation.type === "ornament") {
|
|
4453
|
-
|
|
4663
|
+
const last = chunks[chunks.length - 1];
|
|
4664
|
+
if (last && last.kind === "ornaments") {
|
|
4665
|
+
last.items.push(notation);
|
|
4666
|
+
} else {
|
|
4667
|
+
chunks.push({ kind: "ornaments", items: [notation] });
|
|
4668
|
+
}
|
|
4454
4669
|
} else if (notation.type === "technical") {
|
|
4455
|
-
|
|
4670
|
+
const last = chunks[chunks.length - 1];
|
|
4671
|
+
if (last && last.kind === "technical") {
|
|
4672
|
+
last.items.push(notation);
|
|
4673
|
+
} else {
|
|
4674
|
+
chunks.push({ kind: "technical", items: [notation] });
|
|
4675
|
+
}
|
|
4456
4676
|
} else {
|
|
4457
|
-
|
|
4677
|
+
chunks.push({ kind: "standalone", notation });
|
|
4458
4678
|
}
|
|
4459
4679
|
}
|
|
4460
|
-
for (const
|
|
4461
|
-
if (
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
}
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4680
|
+
for (const chunk of chunks) {
|
|
4681
|
+
if (chunk.kind === "standalone") {
|
|
4682
|
+
lines.push(...serializeStandaloneNotation(chunk.notation, indent));
|
|
4683
|
+
} else if (chunk.kind === "articulations") {
|
|
4684
|
+
lines.push(...serializeArticulationsGroup(chunk.items, indent));
|
|
4685
|
+
} else if (chunk.kind === "ornaments") {
|
|
4686
|
+
lines.push(...serializeOrnamentsGroup(chunk.items, indent));
|
|
4687
|
+
} else if (chunk.kind === "technical") {
|
|
4688
|
+
lines.push(...serializeTechnicalGroup(chunk.items, indent));
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
lines.push(`${indent}</notations>`);
|
|
4692
|
+
return lines;
|
|
4693
|
+
}
|
|
4694
|
+
function serializeStandaloneNotation(notation, indent) {
|
|
4695
|
+
const lines = [];
|
|
4696
|
+
if (notation.type === "tied") {
|
|
4697
|
+
let attrs = ` type="${notation.tiedType}"`;
|
|
4698
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4699
|
+
if (notation.orientation) attrs += ` orientation="${notation.orientation}"`;
|
|
4700
|
+
lines.push(`${indent} <tied${attrs}/>`);
|
|
4701
|
+
} else if (notation.type === "slur") {
|
|
4702
|
+
let attrs = "";
|
|
4703
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4704
|
+
attrs += ` type="${notation.slurType}"`;
|
|
4705
|
+
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4706
|
+
if (notation.orientation) attrs += ` orientation="${notation.orientation}"`;
|
|
4707
|
+
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4708
|
+
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4709
|
+
if (notation.bezierX !== void 0) attrs += ` bezier-x="${notation.bezierX}"`;
|
|
4710
|
+
if (notation.bezierY !== void 0) attrs += ` bezier-y="${notation.bezierY}"`;
|
|
4711
|
+
if (notation.bezierX2 !== void 0) attrs += ` bezier-x2="${notation.bezierX2}"`;
|
|
4712
|
+
if (notation.bezierY2 !== void 0) attrs += ` bezier-y2="${notation.bezierY2}"`;
|
|
4713
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4714
|
+
lines.push(`${indent} <slur${attrs}/>`);
|
|
4715
|
+
} else if (notation.type === "tuplet") {
|
|
4716
|
+
let attrs = ` type="${notation.tupletType}"`;
|
|
4717
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4718
|
+
if (notation.bracket !== void 0) attrs += ` bracket="${notation.bracket ? "yes" : "no"}"`;
|
|
4719
|
+
if (notation.showNumber) attrs += ` show-number="${notation.showNumber}"`;
|
|
4720
|
+
if (notation.showType) attrs += ` show-type="${notation.showType}"`;
|
|
4721
|
+
if (notation.lineShape) attrs += ` line-shape="${notation.lineShape}"`;
|
|
4722
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4723
|
+
const tup = notation;
|
|
4724
|
+
if (tup.tupletActual || tup.tupletNormal) {
|
|
4725
|
+
lines.push(`${indent} <tuplet${attrs}>`);
|
|
4726
|
+
if (tup.tupletActual) {
|
|
4727
|
+
lines.push(`${indent} <tuplet-actual>`);
|
|
4728
|
+
if (tup.tupletActual.tupletNumber !== void 0) {
|
|
4729
|
+
lines.push(`${indent} <tuplet-number>${tup.tupletActual.tupletNumber}</tuplet-number>`);
|
|
4730
|
+
}
|
|
4731
|
+
if (tup.tupletActual.tupletType) {
|
|
4732
|
+
lines.push(`${indent} <tuplet-type>${tup.tupletActual.tupletType}</tuplet-type>`);
|
|
4733
|
+
}
|
|
4734
|
+
if (tup.tupletActual.tupletDots) {
|
|
4735
|
+
for (let i = 0; i < tup.tupletActual.tupletDots; i++) {
|
|
4736
|
+
lines.push(`${indent} <tuplet-dot/>`);
|
|
4503
4737
|
}
|
|
4504
|
-
lines.push(`${indent} </tuplet-actual>`);
|
|
4505
4738
|
}
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4739
|
+
lines.push(`${indent} </tuplet-actual>`);
|
|
4740
|
+
}
|
|
4741
|
+
if (tup.tupletNormal) {
|
|
4742
|
+
lines.push(`${indent} <tuplet-normal>`);
|
|
4743
|
+
if (tup.tupletNormal.tupletNumber !== void 0) {
|
|
4744
|
+
lines.push(`${indent} <tuplet-number>${tup.tupletNormal.tupletNumber}</tuplet-number>`);
|
|
4745
|
+
}
|
|
4746
|
+
if (tup.tupletNormal.tupletType) {
|
|
4747
|
+
lines.push(`${indent} <tuplet-type>${tup.tupletNormal.tupletType}</tuplet-type>`);
|
|
4748
|
+
}
|
|
4749
|
+
if (tup.tupletNormal.tupletDots) {
|
|
4750
|
+
for (let i = 0; i < tup.tupletNormal.tupletDots; i++) {
|
|
4751
|
+
lines.push(`${indent} <tuplet-dot/>`);
|
|
4518
4752
|
}
|
|
4519
|
-
lines.push(`${indent} </tuplet-normal>`);
|
|
4520
4753
|
}
|
|
4521
|
-
lines.push(`${indent}
|
|
4522
|
-
} else {
|
|
4523
|
-
lines.push(`${indent} <tuplet${attrs}/>`);
|
|
4524
|
-
}
|
|
4525
|
-
} else if (notation.type === "dynamics") {
|
|
4526
|
-
const placementAttr = notation.placement ? ` placement="${notation.placement}"` : "";
|
|
4527
|
-
lines.push(`${indent} <dynamics${placementAttr}>`);
|
|
4528
|
-
for (const dyn of notation.dynamics) {
|
|
4529
|
-
lines.push(`${indent} <${dyn}/>`);
|
|
4530
|
-
}
|
|
4531
|
-
if (notation.otherDynamics) {
|
|
4532
|
-
lines.push(`${indent} <other-dynamics>${escapeXml(notation.otherDynamics)}</other-dynamics>`);
|
|
4533
|
-
}
|
|
4534
|
-
lines.push(`${indent} </dynamics>`);
|
|
4535
|
-
} else if (notation.type === "fermata") {
|
|
4536
|
-
let attrs = "";
|
|
4537
|
-
if (notation.fermataType) attrs += ` type="${notation.fermataType}"`;
|
|
4538
|
-
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4539
|
-
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4540
|
-
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4541
|
-
if (notation.shape) {
|
|
4542
|
-
lines.push(`${indent} <fermata${attrs}>${notation.shape}</fermata>`);
|
|
4543
|
-
} else {
|
|
4544
|
-
lines.push(`${indent} <fermata${attrs}/>`);
|
|
4545
|
-
}
|
|
4546
|
-
} else if (notation.type === "arpeggiate") {
|
|
4547
|
-
let attrs = "";
|
|
4548
|
-
if (notation.direction) attrs += ` direction="${notation.direction}"`;
|
|
4549
|
-
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4550
|
-
lines.push(`${indent} <arpeggiate${attrs}/>`);
|
|
4551
|
-
} else if (notation.type === "glissando") {
|
|
4552
|
-
let attrs = ` type="${notation.glissandoType}"`;
|
|
4553
|
-
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4554
|
-
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4555
|
-
if (notation.text) {
|
|
4556
|
-
lines.push(`${indent} <glissando${attrs}>${escapeXml(notation.text)}</glissando>`);
|
|
4557
|
-
} else {
|
|
4558
|
-
lines.push(`${indent} <glissando${attrs}/>`);
|
|
4754
|
+
lines.push(`${indent} </tuplet-normal>`);
|
|
4559
4755
|
}
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4756
|
+
lines.push(`${indent} </tuplet>`);
|
|
4757
|
+
} else {
|
|
4758
|
+
lines.push(`${indent} <tuplet${attrs}/>`);
|
|
4759
|
+
}
|
|
4760
|
+
} else if (notation.type === "dynamics") {
|
|
4761
|
+
const placementAttr = notation.placement ? ` placement="${notation.placement}"` : "";
|
|
4762
|
+
lines.push(`${indent} <dynamics${placementAttr}>`);
|
|
4763
|
+
for (const dyn of notation.dynamics) {
|
|
4764
|
+
lines.push(`${indent} <${dyn}/>`);
|
|
4765
|
+
}
|
|
4766
|
+
if (notation.otherDynamics) {
|
|
4767
|
+
lines.push(`${indent} <other-dynamics>${escapeXml(notation.otherDynamics)}</other-dynamics>`);
|
|
4768
|
+
}
|
|
4769
|
+
lines.push(`${indent} </dynamics>`);
|
|
4770
|
+
} else if (notation.type === "fermata") {
|
|
4771
|
+
let attrs = "";
|
|
4772
|
+
if (notation.fermataType) attrs += ` type="${notation.fermataType}"`;
|
|
4773
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4774
|
+
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4775
|
+
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4776
|
+
if (notation.shape) {
|
|
4777
|
+
lines.push(`${indent} <fermata${attrs}>${notation.shape}</fermata>`);
|
|
4778
|
+
} else {
|
|
4779
|
+
lines.push(`${indent} <fermata${attrs}/>`);
|
|
4780
|
+
}
|
|
4781
|
+
} else if (notation.type === "arpeggiate") {
|
|
4782
|
+
let attrs = "";
|
|
4783
|
+
if (notation.direction) attrs += ` direction="${notation.direction}"`;
|
|
4784
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4785
|
+
if (notation.defaultX !== void 0) attrs += ` default-x="${notation.defaultX}"`;
|
|
4786
|
+
if (notation.defaultY !== void 0) attrs += ` default-y="${notation.defaultY}"`;
|
|
4787
|
+
lines.push(`${indent} <arpeggiate${attrs}/>`);
|
|
4788
|
+
} else if (notation.type === "non-arpeggiate") {
|
|
4789
|
+
let attrs = ` type="${notation.nonArpeggiateType}"`;
|
|
4790
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4791
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4792
|
+
lines.push(`${indent} <non-arpeggiate${attrs}/>`);
|
|
4793
|
+
} else if (notation.type === "accidental-mark") {
|
|
4794
|
+
let attrs = "";
|
|
4795
|
+
if (notation.placement) attrs += ` placement="${notation.placement}"`;
|
|
4796
|
+
lines.push(`${indent} <accidental-mark${attrs}>${escapeXml(notation.value)}</accidental-mark>`);
|
|
4797
|
+
} else if (notation.type === "glissando") {
|
|
4798
|
+
let attrs = ` type="${notation.glissandoType}"`;
|
|
4799
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4800
|
+
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4801
|
+
if (notation.text) {
|
|
4802
|
+
lines.push(`${indent} <glissando${attrs}>${escapeXml(notation.text)}</glissando>`);
|
|
4803
|
+
} else {
|
|
4804
|
+
lines.push(`${indent} <glissando${attrs}/>`);
|
|
4805
|
+
}
|
|
4806
|
+
} else if (notation.type === "slide") {
|
|
4807
|
+
let attrs = ` type="${notation.slideType}"`;
|
|
4808
|
+
if (notation.number !== void 0) attrs += ` number="${notation.number}"`;
|
|
4809
|
+
if (notation.lineType) attrs += ` line-type="${notation.lineType}"`;
|
|
4810
|
+
if (notation.text) {
|
|
4811
|
+
lines.push(`${indent} <slide${attrs}>${escapeXml(notation.text)}</slide>`);
|
|
4812
|
+
} else {
|
|
4564
4813
|
lines.push(`${indent} <slide${attrs}/>`);
|
|
4565
4814
|
}
|
|
4566
4815
|
}
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
}
|
|
4577
|
-
if (art.defaultX !== void 0) artAttrs += ` default-x="${art.defaultX}"`;
|
|
4578
|
-
if (art.defaultY !== void 0) artAttrs += ` default-y="${art.defaultY}"`;
|
|
4579
|
-
lines.push(`${indent} <${art.articulation}${artAttrs}/>`);
|
|
4816
|
+
return lines;
|
|
4817
|
+
}
|
|
4818
|
+
function serializeArticulationsGroup(artGroup, indent) {
|
|
4819
|
+
const lines = [];
|
|
4820
|
+
lines.push(`${indent} <articulations>`);
|
|
4821
|
+
for (const art of artGroup) {
|
|
4822
|
+
if (art.type === "articulation") {
|
|
4823
|
+
let artAttrs = art.placement ? ` placement="${art.placement}"` : "";
|
|
4824
|
+
if (art.articulation === "strong-accent" && art.strongAccentType) {
|
|
4825
|
+
artAttrs += ` type="${art.strongAccentType}"`;
|
|
4580
4826
|
}
|
|
4827
|
+
if (art.defaultX !== void 0) artAttrs += ` default-x="${art.defaultX}"`;
|
|
4828
|
+
if (art.defaultY !== void 0) artAttrs += ` default-y="${art.defaultY}"`;
|
|
4829
|
+
lines.push(`${indent} <${art.articulation}${artAttrs}/>`);
|
|
4581
4830
|
}
|
|
4582
|
-
lines.push(`${indent} </articulations>`);
|
|
4583
4831
|
}
|
|
4584
|
-
|
|
4832
|
+
lines.push(`${indent} </articulations>`);
|
|
4833
|
+
return lines;
|
|
4834
|
+
}
|
|
4835
|
+
function serializeOrnamentsGroup(ornaments, indent) {
|
|
4836
|
+
const lines = [];
|
|
4837
|
+
const hasOnlyEmptyMarker = ornaments.length === 1 && ornaments[0].type === "ornament" && ornaments[0].ornament === "empty";
|
|
4838
|
+
if (hasOnlyEmptyMarker) {
|
|
4839
|
+
lines.push(`${indent} <ornaments/>`);
|
|
4840
|
+
} else {
|
|
4585
4841
|
lines.push(`${indent} <ornaments>`);
|
|
4586
4842
|
const allAccidentalMarks = [];
|
|
4587
4843
|
for (const orn of ornaments) {
|
|
4588
4844
|
if (orn.type === "ornament") {
|
|
4845
|
+
if (orn.ornament === "empty") continue;
|
|
4589
4846
|
const placementAttr = orn.placement ? ` placement="${orn.placement}"` : "";
|
|
4590
4847
|
if (orn.ornament === "wavy-line") {
|
|
4591
4848
|
let wlAttrs = "";
|
|
@@ -4621,77 +4878,80 @@ function serializeNotationsGroup(notations, indent) {
|
|
|
4621
4878
|
}
|
|
4622
4879
|
lines.push(`${indent} </ornaments>`);
|
|
4623
4880
|
}
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
}
|
|
4660
|
-
} else if (tech.technical === "hammer-on" || tech.technical === "pull-off") {
|
|
4661
|
-
let attrs = placementAttr;
|
|
4662
|
-
if (techNotation.startStop) attrs += ` type="${techNotation.startStop}"`;
|
|
4663
|
-
if (techNotation.text !== void 0) {
|
|
4664
|
-
lines.push(`${indent} <${tech.technical}${attrs}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4665
|
-
} else {
|
|
4666
|
-
lines.push(`${indent} <${tech.technical}${attrs}/>`);
|
|
4667
|
-
}
|
|
4668
|
-
} else if (tech.technical === "string" && techNotation.string !== void 0) {
|
|
4669
|
-
lines.push(`${indent} <string${placementAttr}>${techNotation.string}</string>`);
|
|
4670
|
-
} else if (tech.technical === "fret" && techNotation.fret !== void 0) {
|
|
4671
|
-
lines.push(`${indent} <fret${placementAttr}>${techNotation.fret}</fret>`);
|
|
4672
|
-
} else if (tech.technical === "fingering") {
|
|
4673
|
-
let fAttrs = placementAttr;
|
|
4674
|
-
if (techNotation.fingeringSubstitution) fAttrs += ' substitution="yes"';
|
|
4675
|
-
if (techNotation.fingeringAlternate) fAttrs += ' alternate="yes"';
|
|
4676
|
-
if (techNotation.text !== void 0) {
|
|
4677
|
-
lines.push(`${indent} <fingering${fAttrs}>${escapeXml(techNotation.text)}</fingering>`);
|
|
4678
|
-
} else {
|
|
4679
|
-
lines.push(`${indent} <fingering${fAttrs}/>`);
|
|
4680
|
-
}
|
|
4681
|
-
} else if (tech.technical === "heel" || tech.technical === "toe") {
|
|
4682
|
-
let htAttrs = placementAttr;
|
|
4683
|
-
if (techNotation.substitution) htAttrs += ' substitution="yes"';
|
|
4684
|
-
lines.push(`${indent} <${tech.technical}${htAttrs}/>`);
|
|
4685
|
-
} else if (techNotation.text !== void 0) {
|
|
4686
|
-
lines.push(`${indent} <${tech.technical}${placementAttr}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4881
|
+
return lines;
|
|
4882
|
+
}
|
|
4883
|
+
function serializeTechnicalGroup(technicals, indent) {
|
|
4884
|
+
const lines = [];
|
|
4885
|
+
lines.push(`${indent} <technical>`);
|
|
4886
|
+
for (const tech of technicals) {
|
|
4887
|
+
if (tech.type === "technical") {
|
|
4888
|
+
let placementAttr = tech.placement ? ` placement="${tech.placement}"` : "";
|
|
4889
|
+
const techNotation = tech;
|
|
4890
|
+
if (techNotation.defaultX !== void 0) placementAttr += ` default-x="${techNotation.defaultX}"`;
|
|
4891
|
+
if (techNotation.defaultY !== void 0) placementAttr += ` default-y="${techNotation.defaultY}"`;
|
|
4892
|
+
if (tech.technical === "bend" && (techNotation.bendAlter !== void 0 || techNotation.preBend || techNotation.release)) {
|
|
4893
|
+
lines.push(`${indent} <bend${placementAttr}>`);
|
|
4894
|
+
if (techNotation.bendAlter !== void 0) {
|
|
4895
|
+
lines.push(`${indent} <bend-alter>${techNotation.bendAlter}</bend-alter>`);
|
|
4896
|
+
}
|
|
4897
|
+
if (techNotation.preBend) {
|
|
4898
|
+
lines.push(`${indent} <pre-bend/>`);
|
|
4899
|
+
}
|
|
4900
|
+
if (techNotation.release) {
|
|
4901
|
+
lines.push(`${indent} <release/>`);
|
|
4902
|
+
}
|
|
4903
|
+
if (techNotation.withBar) {
|
|
4904
|
+
lines.push(`${indent} <with-bar/>`);
|
|
4905
|
+
}
|
|
4906
|
+
lines.push(`${indent} </bend>`);
|
|
4907
|
+
} else if (tech.technical === "harmonic") {
|
|
4908
|
+
const hasChildren = techNotation.harmonicNatural || techNotation.harmonicArtificial || techNotation.basePitch || techNotation.touchingPitch || techNotation.soundingPitch;
|
|
4909
|
+
if (hasChildren) {
|
|
4910
|
+
lines.push(`${indent} <harmonic${placementAttr}>`);
|
|
4911
|
+
if (techNotation.harmonicNatural) lines.push(`${indent} <natural/>`);
|
|
4912
|
+
if (techNotation.harmonicArtificial) lines.push(`${indent} <artificial/>`);
|
|
4913
|
+
if (techNotation.basePitch) lines.push(`${indent} <base-pitch/>`);
|
|
4914
|
+
if (techNotation.touchingPitch) lines.push(`${indent} <touching-pitch/>`);
|
|
4915
|
+
if (techNotation.soundingPitch) lines.push(`${indent} <sounding-pitch/>`);
|
|
4916
|
+
lines.push(`${indent} </harmonic>`);
|
|
4687
4917
|
} else {
|
|
4688
|
-
lines.push(`${indent}
|
|
4689
|
-
}
|
|
4918
|
+
lines.push(`${indent} <harmonic${placementAttr}/>`);
|
|
4919
|
+
}
|
|
4920
|
+
} else if (tech.technical === "hammer-on" || tech.technical === "pull-off") {
|
|
4921
|
+
let attrs = "";
|
|
4922
|
+
if (techNotation.number !== void 0) attrs += ` number="${techNotation.number}"`;
|
|
4923
|
+
if (techNotation.startStop) attrs += ` type="${techNotation.startStop}"`;
|
|
4924
|
+
attrs += placementAttr;
|
|
4925
|
+
if (techNotation.text !== void 0) {
|
|
4926
|
+
lines.push(`${indent} <${tech.technical}${attrs}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4927
|
+
} else {
|
|
4928
|
+
lines.push(`${indent} <${tech.technical}${attrs}/>`);
|
|
4929
|
+
}
|
|
4930
|
+
} else if (tech.technical === "string" && techNotation.string !== void 0) {
|
|
4931
|
+
lines.push(`${indent} <string${placementAttr}>${techNotation.string}</string>`);
|
|
4932
|
+
} else if (tech.technical === "fret" && techNotation.fret !== void 0) {
|
|
4933
|
+
lines.push(`${indent} <fret${placementAttr}>${techNotation.fret}</fret>`);
|
|
4934
|
+
} else if (tech.technical === "fingering") {
|
|
4935
|
+
let fAttrs = placementAttr;
|
|
4936
|
+
if (techNotation.fingeringSubstitution) fAttrs += ' substitution="yes"';
|
|
4937
|
+
if (techNotation.fingeringAlternate) fAttrs += ' alternate="yes"';
|
|
4938
|
+
if (techNotation.text !== void 0) {
|
|
4939
|
+
lines.push(`${indent} <fingering${fAttrs}>${escapeXml(techNotation.text)}</fingering>`);
|
|
4940
|
+
} else {
|
|
4941
|
+
lines.push(`${indent} <fingering${fAttrs}/>`);
|
|
4942
|
+
}
|
|
4943
|
+
} else if (tech.technical === "heel" || tech.technical === "toe") {
|
|
4944
|
+
let htAttrs = placementAttr;
|
|
4945
|
+
if (techNotation.substitution) htAttrs += ' substitution="yes"';
|
|
4946
|
+
lines.push(`${indent} <${tech.technical}${htAttrs}/>`);
|
|
4947
|
+
} else if (techNotation.text !== void 0) {
|
|
4948
|
+
lines.push(`${indent} <${tech.technical}${placementAttr}>${escapeXml(techNotation.text)}</${tech.technical}>`);
|
|
4949
|
+
} else {
|
|
4950
|
+
lines.push(`${indent} <${tech.technical}${placementAttr}/>`);
|
|
4690
4951
|
}
|
|
4691
4952
|
}
|
|
4692
|
-
lines.push(`${indent} </technical>`);
|
|
4693
4953
|
}
|
|
4694
|
-
lines.push(`${indent}</
|
|
4954
|
+
lines.push(`${indent} </technical>`);
|
|
4695
4955
|
return lines;
|
|
4696
4956
|
}
|
|
4697
4957
|
function serializeLyric(lyric, indent) {
|
|
@@ -4715,7 +4975,7 @@ function serializeLyric(lyric, indent) {
|
|
|
4715
4975
|
lines.push(`${indent} <elision/>`);
|
|
4716
4976
|
}
|
|
4717
4977
|
}
|
|
4718
|
-
} else {
|
|
4978
|
+
} else if (lyric.syllabic || lyric.text) {
|
|
4719
4979
|
if (lyric.syllabic) {
|
|
4720
4980
|
lines.push(`${indent} <syllabic>${lyric.syllabic}</syllabic>`);
|
|
4721
4981
|
}
|
|
@@ -4830,7 +5090,12 @@ function serializeDirectionType(dirType, indent) {
|
|
|
4830
5090
|
if (dirType.relativeX !== void 0) dynAttrs += ` relative-x="${dirType.relativeX}"`;
|
|
4831
5091
|
if (dirType.halign) dynAttrs += ` halign="${dirType.halign}"`;
|
|
4832
5092
|
lines.push(`${indent} <dynamics${dynAttrs}>`);
|
|
4833
|
-
|
|
5093
|
+
if (dirType.value) {
|
|
5094
|
+
lines.push(`${indent} <${dirType.value}/>`);
|
|
5095
|
+
}
|
|
5096
|
+
if (dirType.otherDynamics) {
|
|
5097
|
+
lines.push(`${indent} <other-dynamics>${escapeXml(dirType.otherDynamics)}</other-dynamics>`);
|
|
5098
|
+
}
|
|
4834
5099
|
lines.push(`${indent} </dynamics>`);
|
|
4835
5100
|
break;
|
|
4836
5101
|
}
|
|
@@ -4917,8 +5182,12 @@ function serializeDirectionType(dirType, indent) {
|
|
|
4917
5182
|
if (dirType.high) {
|
|
4918
5183
|
lines.push(`${indent} <accordion-high/>`);
|
|
4919
5184
|
}
|
|
4920
|
-
if (dirType.middle !== void 0) {
|
|
4921
|
-
|
|
5185
|
+
if (dirType.middlePresent || dirType.middle !== void 0) {
|
|
5186
|
+
if (dirType.middle !== void 0) {
|
|
5187
|
+
lines.push(`${indent} <accordion-middle>${dirType.middle}</accordion-middle>`);
|
|
5188
|
+
} else {
|
|
5189
|
+
lines.push(`${indent} <accordion-middle/>`);
|
|
5190
|
+
}
|
|
4922
5191
|
}
|
|
4923
5192
|
if (dirType.low) {
|
|
4924
5193
|
lines.push(`${indent} <accordion-low/>`);
|
|
@@ -5031,11 +5300,20 @@ function serializeBarline(barline, indent) {
|
|
|
5031
5300
|
lines.push(`${indent} <bar-style>${barline.barStyle}</bar-style>`);
|
|
5032
5301
|
}
|
|
5033
5302
|
if (barline.ending) {
|
|
5034
|
-
|
|
5303
|
+
let endingAttrs = ` number="${barline.ending.number}" type="${barline.ending.type}"`;
|
|
5304
|
+
if (barline.ending.defaultY !== void 0) endingAttrs += ` default-y="${barline.ending.defaultY}"`;
|
|
5305
|
+
if (barline.ending.endLength !== void 0) endingAttrs += ` end-length="${barline.ending.endLength}"`;
|
|
5306
|
+
if (barline.ending.text) {
|
|
5307
|
+
lines.push(`${indent} <ending${endingAttrs}>${escapeXml(barline.ending.text)}</ending>`);
|
|
5308
|
+
} else {
|
|
5309
|
+
lines.push(`${indent} <ending${endingAttrs}/>`);
|
|
5310
|
+
}
|
|
5035
5311
|
}
|
|
5036
5312
|
if (barline.repeat) {
|
|
5037
|
-
|
|
5038
|
-
|
|
5313
|
+
let repeatAttrs = ` direction="${barline.repeat.direction}"`;
|
|
5314
|
+
if (barline.repeat.times !== void 0) repeatAttrs += ` times="${barline.repeat.times}"`;
|
|
5315
|
+
if (barline.repeat.winged) repeatAttrs += ` winged="${barline.repeat.winged}"`;
|
|
5316
|
+
lines.push(`${indent} <repeat${repeatAttrs}/>`);
|
|
5039
5317
|
}
|
|
5040
5318
|
lines.push(`${indent}</barline>`);
|
|
5041
5319
|
return lines;
|
|
@@ -5068,7 +5346,8 @@ function serializeStaffDetails(sd, indent) {
|
|
|
5068
5346
|
const attrs = buildAttrs({
|
|
5069
5347
|
"number": sd.number,
|
|
5070
5348
|
"show-frets": sd.showFrets,
|
|
5071
|
-
"print-object": sd.printObject
|
|
5349
|
+
"print-object": sd.printObject,
|
|
5350
|
+
"print-spacing": sd.printSpacing
|
|
5072
5351
|
});
|
|
5073
5352
|
lines.push(`${indent}<staff-details${attrs}>`);
|
|
5074
5353
|
pushOptionalElement(lines, `${indent} `, "staff-type", sd.staffType);
|
|
@@ -5134,16 +5413,22 @@ function serializeHarmony(harmony, indent) {
|
|
|
5134
5413
|
}
|
|
5135
5414
|
lines.push(`${indent} </root>`);
|
|
5136
5415
|
let kindAttrs = "";
|
|
5137
|
-
if (harmony.kindText) kindAttrs += ` text="${escapeXml(harmony.kindText)}"`;
|
|
5416
|
+
if (harmony.kindText !== void 0) kindAttrs += ` text="${escapeXml(harmony.kindText)}"`;
|
|
5417
|
+
if (harmony.kindHalign) kindAttrs += ` halign="${escapeXml(harmony.kindHalign)}"`;
|
|
5138
5418
|
lines.push(`${indent} <kind${kindAttrs}>${escapeXml(harmony.kind)}</kind>`);
|
|
5139
5419
|
if (harmony.bass) {
|
|
5140
|
-
|
|
5420
|
+
let bassAttrs = "";
|
|
5421
|
+
if (harmony.bass.arrangement) bassAttrs += ` arrangement="${escapeXml(harmony.bass.arrangement)}"`;
|
|
5422
|
+
lines.push(`${indent} <bass${bassAttrs}>`);
|
|
5141
5423
|
lines.push(`${indent} <bass-step>${harmony.bass.bassStep}</bass-step>`);
|
|
5142
5424
|
if (harmony.bass.bassAlter !== void 0) {
|
|
5143
5425
|
lines.push(`${indent} <bass-alter>${harmony.bass.bassAlter}</bass-alter>`);
|
|
5144
5426
|
}
|
|
5145
5427
|
lines.push(`${indent} </bass>`);
|
|
5146
5428
|
}
|
|
5429
|
+
if (harmony.inversion !== void 0) {
|
|
5430
|
+
lines.push(`${indent} <inversion>${harmony.inversion}</inversion>`);
|
|
5431
|
+
}
|
|
5147
5432
|
if (harmony.degrees) {
|
|
5148
5433
|
for (const deg of harmony.degrees) {
|
|
5149
5434
|
lines.push(`${indent} <degree>`);
|
|
@@ -5829,7 +6114,7 @@ function groupByVoice(measure) {
|
|
|
5829
6114
|
for (const entry of measure.entries) {
|
|
5830
6115
|
if (entry.type !== "note") continue;
|
|
5831
6116
|
const staff = entry.staff ?? 1;
|
|
5832
|
-
const voice = entry.voice;
|
|
6117
|
+
const voice = entry.voice ?? 1;
|
|
5833
6118
|
const key = `${staff}-${voice}`;
|
|
5834
6119
|
if (!groups.has(key)) {
|
|
5835
6120
|
groups.set(key, { staff, voice, notes: [] });
|
|
@@ -5923,7 +6208,7 @@ function getVoices(measure) {
|
|
|
5923
6208
|
const voices = /* @__PURE__ */ new Set();
|
|
5924
6209
|
for (const entry of measure.entries) {
|
|
5925
6210
|
if (entry.type === "note") {
|
|
5926
|
-
voices.add(entry.voice);
|
|
6211
|
+
voices.add(entry.voice ?? 1);
|
|
5927
6212
|
}
|
|
5928
6213
|
}
|
|
5929
6214
|
return Array.from(voices).sort((a, b) => a - b);
|
|
@@ -5974,7 +6259,7 @@ function buildVoiceToStaffMap(measure) {
|
|
|
5974
6259
|
const map = /* @__PURE__ */ new Map();
|
|
5975
6260
|
for (const entry of measure.entries) {
|
|
5976
6261
|
if (entry.type === "note" && entry.staff !== void 0) {
|
|
5977
|
-
const voice = entry.voice;
|
|
6262
|
+
const voice = entry.voice ?? 1;
|
|
5978
6263
|
const staff = entry.staff;
|
|
5979
6264
|
if (!map.has(voice)) {
|
|
5980
6265
|
map.set(voice, staff);
|
|
@@ -5993,7 +6278,7 @@ function buildVoiceToStaffMapForPart(part) {
|
|
|
5993
6278
|
for (const measure of part.measures) {
|
|
5994
6279
|
for (const entry of measure.entries) {
|
|
5995
6280
|
if (entry.type === "note" && entry.staff !== void 0) {
|
|
5996
|
-
const voice = entry.voice;
|
|
6281
|
+
const voice = entry.voice ?? 1;
|
|
5997
6282
|
const staff = entry.staff;
|
|
5998
6283
|
if (!map.has(voice)) {
|
|
5999
6284
|
map.set(voice, staff);
|
|
@@ -6012,7 +6297,7 @@ function inferStaff(entry, voiceToStaffMap) {
|
|
|
6012
6297
|
if (entry.staff !== void 0) {
|
|
6013
6298
|
return entry.staff;
|
|
6014
6299
|
}
|
|
6015
|
-
const inferredStaff = voiceToStaffMap.get(entry.voice);
|
|
6300
|
+
const inferredStaff = voiceToStaffMap.get(entry.voice ?? 1);
|
|
6016
6301
|
if (inferredStaff !== void 0) {
|
|
6017
6302
|
return inferredStaff;
|
|
6018
6303
|
}
|
|
@@ -6055,7 +6340,7 @@ function getVoicesForStaff(measure, staff) {
|
|
|
6055
6340
|
if (entry.type === "note") {
|
|
6056
6341
|
const entryStaff = entry.staff ?? 1;
|
|
6057
6342
|
if (entryStaff === staff) {
|
|
6058
|
-
voices.add(entry.voice);
|
|
6343
|
+
voices.add(entry.voice ?? 1);
|
|
6059
6344
|
}
|
|
6060
6345
|
}
|
|
6061
6346
|
}
|
|
@@ -6391,6 +6676,7 @@ function getDynamics(score, options) {
|
|
|
6391
6676
|
if (dirType.kind === "dynamics") {
|
|
6392
6677
|
results.push({
|
|
6393
6678
|
dynamic: dirType.value,
|
|
6679
|
+
otherDynamics: dirType.otherDynamics,
|
|
6394
6680
|
direction: entry,
|
|
6395
6681
|
part,
|
|
6396
6682
|
partIndex,
|
|
@@ -7465,14 +7751,17 @@ function hasNotesInRange(voiceEntries, startPos, endPos) {
|
|
|
7465
7751
|
return { hasNotes: conflicting.length > 0, conflictingNotes: conflicting };
|
|
7466
7752
|
}
|
|
7467
7753
|
function createRest(duration, voice, staff) {
|
|
7468
|
-
|
|
7754
|
+
const note = {
|
|
7469
7755
|
_id: generateId(),
|
|
7470
7756
|
type: "note",
|
|
7471
7757
|
rest: { displayStep: void 0, displayOctave: void 0 },
|
|
7472
7758
|
duration,
|
|
7473
|
-
voice,
|
|
7474
7759
|
staff
|
|
7475
7760
|
};
|
|
7761
|
+
if (voice !== void 0) {
|
|
7762
|
+
note.voice = voice;
|
|
7763
|
+
}
|
|
7764
|
+
return note;
|
|
7476
7765
|
}
|
|
7477
7766
|
function rebuildMeasureWithVoice(measure, voice, newEntries, measureDuration, staff) {
|
|
7478
7767
|
const otherEntries = [];
|
|
@@ -9026,7 +9315,7 @@ function autoBeam(score, options) {
|
|
|
9026
9315
|
for (const entry of measure.entries) {
|
|
9027
9316
|
if (entry.type === "note") {
|
|
9028
9317
|
if (!entry.chord && !entry.rest) {
|
|
9029
|
-
const voice = entry.voice;
|
|
9318
|
+
const voice = entry.voice ?? 1;
|
|
9030
9319
|
if (options.voice === void 0 || voice === options.voice) {
|
|
9031
9320
|
if (!notesByVoice.has(voice)) {
|
|
9032
9321
|
notesByVoice.set(voice, []);
|