@k-l-lambda/lilylet 0.1.57 → 0.1.58
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.
|
@@ -585,6 +585,7 @@ const parseLilyDocument = (lilyDocument) => {
|
|
|
585
585
|
const restEvent = {
|
|
586
586
|
type: 'rest',
|
|
587
587
|
duration: convertDuration(term.durationValue),
|
|
588
|
+
fullMeasure: (term.name === 'R') || undefined,
|
|
588
589
|
invisible: term.isSpacer || undefined,
|
|
589
590
|
};
|
|
590
591
|
voice.events.push(restEvent);
|
|
@@ -500,10 +500,14 @@ const serializeVoice = (voice, currentStaff, isGrandStaff = false, measureContex
|
|
|
500
500
|
for (const event of voice.events) {
|
|
501
501
|
if (event.type === 'context') {
|
|
502
502
|
const ctx = event;
|
|
503
|
-
//
|
|
504
|
-
if (ctx.staff && ctx.staff !==
|
|
503
|
+
// Cross-staff context: update activeStaff and emit \staff directive
|
|
504
|
+
if (ctx.staff && ctx.staff !== activeStaff) {
|
|
505
|
+
activeStaff = ctx.staff;
|
|
506
|
+
parts.push('\\staff "' + activeStaff + '"');
|
|
505
507
|
continue;
|
|
506
508
|
}
|
|
509
|
+
if (ctx.staff)
|
|
510
|
+
continue; // same staff, no-op
|
|
507
511
|
// Skip clef-only context events if clef already established for this staff
|
|
508
512
|
if (clefOutputted && ctx.clef && !ctx.key && !ctx.time && !ctx.ottava && !ctx.stemDirection && !ctx.tempo) {
|
|
509
513
|
continue;
|
|
@@ -511,8 +515,8 @@ const serializeVoice = (voice, currentStaff, isGrandStaff = false, measureContex
|
|
|
511
515
|
}
|
|
512
516
|
if (event.type === 'note') {
|
|
513
517
|
const noteEvt = event;
|
|
514
|
-
// Cross-staff
|
|
515
|
-
const effectiveStaff = noteEvt.staff ||
|
|
518
|
+
// Cross-staff via explicit note.staff (lilylet native cross-staff)
|
|
519
|
+
const effectiveStaff = noteEvt.staff || activeStaff;
|
|
516
520
|
if (effectiveStaff !== activeStaff) {
|
|
517
521
|
activeStaff = effectiveStaff;
|
|
518
522
|
parts.push('\\staff "' + activeStaff + '"');
|
|
@@ -679,12 +683,16 @@ export const serializeLilyletDoc = (doc) => {
|
|
|
679
683
|
// Collect clefs from this measure's voices
|
|
680
684
|
for (const part of measure.parts) {
|
|
681
685
|
for (const voice of part.voices) {
|
|
686
|
+
let clefActiveStaff = voice.staff;
|
|
682
687
|
for (const event of voice.events) {
|
|
683
|
-
if (event.type === 'context'
|
|
688
|
+
if (event.type === 'context') {
|
|
684
689
|
const ctx = event;
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
690
|
+
if (ctx.staff) {
|
|
691
|
+
clefActiveStaff = ctx.staff;
|
|
692
|
+
}
|
|
693
|
+
if (ctx.clef) {
|
|
694
|
+
staffClefs[clefActiveStaff] = ctx.clef;
|
|
695
|
+
}
|
|
688
696
|
}
|
|
689
697
|
}
|
|
690
698
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k-l-lambda/lilylet",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.58",
|
|
4
4
|
"description": "Lilylet is a lilyopnd-like sheet music language designed for Markdown rendering and symbolic music representation in AIGC applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -708,6 +708,7 @@ const parseLilyDocument = (lilyDocument: lilyParser.LilyDocument): ParsedMeasure
|
|
|
708
708
|
const restEvent: RestEvent = {
|
|
709
709
|
type: 'rest',
|
|
710
710
|
duration: convertDuration(term.durationValue),
|
|
711
|
+
fullMeasure: (term.name === 'R') || undefined,
|
|
711
712
|
invisible: term.isSpacer || undefined,
|
|
712
713
|
};
|
|
713
714
|
|
|
@@ -648,10 +648,13 @@ const serializeVoice = (
|
|
|
648
648
|
for (const event of voice.events) {
|
|
649
649
|
if (event.type === 'context') {
|
|
650
650
|
const ctx = event as ContextChange;
|
|
651
|
-
//
|
|
652
|
-
if (ctx.staff && ctx.staff !==
|
|
651
|
+
// Cross-staff context: update activeStaff and emit \staff directive
|
|
652
|
+
if (ctx.staff && ctx.staff !== activeStaff) {
|
|
653
|
+
activeStaff = ctx.staff;
|
|
654
|
+
parts.push('\\staff "' + activeStaff + '"');
|
|
653
655
|
continue;
|
|
654
656
|
}
|
|
657
|
+
if (ctx.staff) continue; // same staff, no-op
|
|
655
658
|
// Skip clef-only context events if clef already established for this staff
|
|
656
659
|
if (clefOutputted && ctx.clef && !ctx.key && !ctx.time && !ctx.ottava && !ctx.stemDirection && !ctx.tempo) {
|
|
657
660
|
continue;
|
|
@@ -661,8 +664,8 @@ const serializeVoice = (
|
|
|
661
664
|
if (event.type === 'note') {
|
|
662
665
|
const noteEvt = event as NoteEvent;
|
|
663
666
|
|
|
664
|
-
// Cross-staff
|
|
665
|
-
const effectiveStaff = noteEvt.staff ||
|
|
667
|
+
// Cross-staff via explicit note.staff (lilylet native cross-staff)
|
|
668
|
+
const effectiveStaff = noteEvt.staff || activeStaff;
|
|
666
669
|
if (effectiveStaff !== activeStaff) {
|
|
667
670
|
activeStaff = effectiveStaff;
|
|
668
671
|
parts.push('\\staff "' + activeStaff + '"');
|
|
@@ -872,12 +875,16 @@ export const serializeLilyletDoc = (doc: LilyletDoc): string => {
|
|
|
872
875
|
// Collect clefs from this measure's voices
|
|
873
876
|
for (const part of measure.parts) {
|
|
874
877
|
for (const voice of part.voices) {
|
|
878
|
+
let clefActiveStaff = voice.staff;
|
|
875
879
|
for (const event of voice.events) {
|
|
876
|
-
if (event.type === 'context'
|
|
880
|
+
if (event.type === 'context') {
|
|
877
881
|
const ctx = event as ContextChange;
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
882
|
+
if (ctx.staff) {
|
|
883
|
+
clefActiveStaff = ctx.staff;
|
|
884
|
+
}
|
|
885
|
+
if (ctx.clef) {
|
|
886
|
+
staffClefs[clefActiveStaff] = ctx.clef;
|
|
887
|
+
}
|
|
881
888
|
}
|
|
882
889
|
}
|
|
883
890
|
}
|