@ugfoundation/swaralipi-js 0.8.1 → 0.8.2
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/{batch-NDL6CW7Q.js → batch-6FPBT5DP.js} +4 -4
- package/dist/{batch-NDL6CW7Q.js.map → batch-6FPBT5DP.js.map} +1 -1
- package/dist/{chunk-LPCKL3AM.js → chunk-FULC22MN.js} +3 -3
- package/dist/{chunk-LPCKL3AM.js.map → chunk-FULC22MN.js.map} +1 -1
- package/dist/{chunk-Z42M5JAA.js → chunk-UMBKIGVQ.js} +3 -3
- package/dist/{chunk-Z42M5JAA.js.map → chunk-UMBKIGVQ.js.map} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/convert/index.cjs +1 -1
- package/dist/convert/index.cjs.map +1 -1
- package/dist/convert/index.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/spec/index.cjs +1 -1
- package/dist/spec/index.cjs.map +1 -1
- package/dist/spec/index.d.cts +1 -1
- package/dist/spec/index.d.ts +1 -1
- package/dist/spec/index.js +1 -1
- package/dist/viewer/index.cjs +157 -109
- package/dist/viewer/index.cjs.map +1 -1
- package/dist/viewer/index.d.cts +11 -5
- package/dist/viewer/index.d.ts +11 -5
- package/dist/viewer/index.js +156 -108
- package/dist/viewer/index.js.map +1 -1
- package/package.json +1 -1
package/dist/viewer/index.cjs
CHANGED
|
@@ -260,7 +260,7 @@ var init_spec = __esm({
|
|
|
260
260
|
init_grace();
|
|
261
261
|
init_lay();
|
|
262
262
|
init_svara();
|
|
263
|
-
SPEC_VERSION = "0.8.
|
|
263
|
+
SPEC_VERSION = "0.8.2";
|
|
264
264
|
}
|
|
265
265
|
});
|
|
266
266
|
|
|
@@ -642,42 +642,64 @@ function alignRows(rows) {
|
|
|
642
642
|
}
|
|
643
643
|
function resolveArcs(cells) {
|
|
644
644
|
const arcs = [];
|
|
645
|
-
let
|
|
645
|
+
let open;
|
|
646
646
|
let sawEnds = false;
|
|
647
647
|
const fillCells = [];
|
|
648
|
-
const openAt = (
|
|
648
|
+
const openAt = (cell, note) => {
|
|
649
649
|
sawEnds = true;
|
|
650
|
-
|
|
650
|
+
open ??= { cell, note };
|
|
651
651
|
};
|
|
652
|
-
const closeAt = (
|
|
652
|
+
const closeAt = (cell, note) => {
|
|
653
653
|
sawEnds = true;
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
654
|
+
const from = open ?? { cell: 0, note: 0 };
|
|
655
|
+
arcs.push({
|
|
656
|
+
start: from.cell,
|
|
657
|
+
startNote: from.note,
|
|
658
|
+
end: cell,
|
|
659
|
+
endNote: note,
|
|
660
|
+
openLeft: open === void 0,
|
|
661
|
+
openRight: false
|
|
662
|
+
});
|
|
663
|
+
open = void 0;
|
|
660
664
|
};
|
|
661
665
|
cells.forEach((cell, i) => {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
666
|
+
const pitched = cell.notes.flatMap((n, j) => isPitched(n) ? [j] : []);
|
|
667
|
+
const first = pitched[0] ?? 0;
|
|
668
|
+
const last = pitched[pitched.length - 1] ?? cell.notes.length - 1;
|
|
669
|
+
let marks = "";
|
|
670
|
+
cell.notes.forEach((note, j) => {
|
|
671
|
+
if (note.meend === "start") openAt(i, j);
|
|
672
|
+
else if (note.meend === "end") closeAt(i, j);
|
|
673
|
+
for (const b of note.below ?? []) if (isArcRaw(b.raw)) marks += b.raw;
|
|
674
|
+
});
|
|
675
|
+
const reopens = /[xX].*[wW]/.test(marks);
|
|
676
|
+
for (const ch of marks) {
|
|
677
|
+
if (ch === "w" || ch === "W") openAt(i, reopens ? last : first);
|
|
678
|
+
else if (ch === "x" || ch === "X") closeAt(i, reopens ? first : last);
|
|
679
|
+
else if (ch === "$") {
|
|
680
|
+
openAt(i, first);
|
|
681
|
+
closeAt(i, last);
|
|
682
|
+
} else fillCells.push(i);
|
|
673
683
|
}
|
|
674
684
|
});
|
|
675
|
-
|
|
676
|
-
|
|
685
|
+
const lastCell = Math.max(cells.length - 1, 0);
|
|
686
|
+
const lastNote = (c) => Math.max((cells[c]?.notes.length ?? 1) - 1, 0);
|
|
687
|
+
if (open !== void 0) {
|
|
688
|
+
arcs.push({
|
|
689
|
+
start: open.cell,
|
|
690
|
+
startNote: open.note,
|
|
691
|
+
end: lastCell,
|
|
692
|
+
endNote: lastNote(lastCell),
|
|
693
|
+
openLeft: false,
|
|
694
|
+
openRight: true
|
|
695
|
+
});
|
|
677
696
|
} else if (!sawEnds && fillCells.length > 0) {
|
|
697
|
+
const end = Math.max(...fillCells);
|
|
678
698
|
arcs.push({
|
|
679
699
|
start: Math.min(...fillCells),
|
|
680
|
-
|
|
700
|
+
startNote: 0,
|
|
701
|
+
end,
|
|
702
|
+
endNote: lastNote(end),
|
|
681
703
|
openLeft: true,
|
|
682
704
|
openRight: true,
|
|
683
705
|
line: true
|
|
@@ -685,6 +707,35 @@ function resolveArcs(cells) {
|
|
|
685
707
|
}
|
|
686
708
|
return arcs;
|
|
687
709
|
}
|
|
710
|
+
function arcInk(cells, arcs) {
|
|
711
|
+
const ink = { cells: cells.map(() => ""), notes: cells.map((c) => c.notes.map(() => "")) };
|
|
712
|
+
const mark = (c, j, cls, clip = false) => {
|
|
713
|
+
ink.notes[c][j] += ` ${cls}`;
|
|
714
|
+
if (clip && !ink.cells[c].includes(" sw-mk")) ink.cells[c] += " sw-mk";
|
|
715
|
+
};
|
|
716
|
+
for (const arc of arcs) {
|
|
717
|
+
const { start: s, end: e, startNote: j, endNote: k } = arc;
|
|
718
|
+
const hookL = arc.line !== true && !arc.openLeft;
|
|
719
|
+
const hookR = arc.line !== true && !arc.openRight;
|
|
720
|
+
if (s === e && hookL && hookR) {
|
|
721
|
+
if (j === k) {
|
|
722
|
+
mark(s, j, "sw-mos");
|
|
723
|
+
mark(s, j, "sw-mcs");
|
|
724
|
+
} else {
|
|
725
|
+
mark(s, j, "sw-mob");
|
|
726
|
+
for (let n = j + 1; n < k; n++) mark(s, n, "sw-mf");
|
|
727
|
+
mark(s, k, "sw-mcb");
|
|
728
|
+
}
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
for (let c = s; c <= e; c++) {
|
|
732
|
+
if (c === s && hookL) mark(c, j, "sw-mo", true);
|
|
733
|
+
else if (c === e && hookR) mark(c, k, "sw-mc", true);
|
|
734
|
+
else mark(c, 0, "sw-mm", true);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return ink;
|
|
738
|
+
}
|
|
688
739
|
var SVARA_CHAR = /[srgmpqndtkuv]/;
|
|
689
740
|
function rawMarks(raw, count) {
|
|
690
741
|
if (raw === void 0) return void 0;
|
|
@@ -860,25 +911,9 @@ function renderNote(note, kind, opts, ctx) {
|
|
|
860
911
|
const raw = rawDisplay(note);
|
|
861
912
|
return bracketGlyphs(note, "open") + (raw !== void 0 ? `<span class="sw-raw" title="${escapeHtml(raw)}">${escapeHtml(raw)}</span>` : "") + bracketGlyphs(note, "close");
|
|
862
913
|
}
|
|
863
|
-
function renderArc(arc, offset) {
|
|
864
|
-
const open = arc.line === true;
|
|
865
|
-
const openL = arc.openLeft || open;
|
|
866
|
-
const openR = arc.openRight || open;
|
|
867
|
-
const fill = '<i class="sw-arc-m"></i>';
|
|
868
|
-
const hookL = openL ? "" : '<i class="sw-arc-l">w</i>';
|
|
869
|
-
const hookR = openR ? "" : '<i class="sw-arc-r">x</i>';
|
|
870
|
-
const piece = (col, cls, inner) => `<span class="sw-arc${cls}" style="grid-column:${col}">${inner}</span>`;
|
|
871
|
-
const f = offset + arc.start + COL_BASE;
|
|
872
|
-
const t = offset + arc.end + COL_BASE;
|
|
873
|
-
const openCls = (openL ? " sw-arc--openl" : "") + (openR ? " sw-arc--openr" : "");
|
|
874
|
-
if (t === f) return piece(`${f}`, openCls, hookL + fill + hookR);
|
|
875
|
-
const head = piece(`${f}`, openL ? " sw-arc--openl" : " sw-arc--head", hookL + fill);
|
|
876
|
-
const tail = piece(`${t}`, openR ? " sw-arc--openr" : " sw-arc--tail", fill + hookR);
|
|
877
|
-
const mid = t > f + 1 ? piece(`${f + 1} / ${t}`, " sw-arc--mid", fill) : "";
|
|
878
|
-
return head + mid + tail;
|
|
879
|
-
}
|
|
880
914
|
function renderRow(row, partIdx, rowIdx, offset, ctx) {
|
|
881
915
|
const cells = groupRowIntoCells(row.notes);
|
|
916
|
+
const ink = arcInk(cells, resolveArcs(cells));
|
|
882
917
|
const out = [];
|
|
883
918
|
if (row.label !== void 0)
|
|
884
919
|
out.push(`<span class="sw-label">${escapeHtml(ctx.tr(row.label))}</span>`);
|
|
@@ -888,11 +923,10 @@ function renderRow(row, partIdx, rowIdx, offset, ctx) {
|
|
|
888
923
|
const barCls = cell.kind === "bar" ? " sw-bar-cell" : "";
|
|
889
924
|
const notes = cell.notes.map((note, j) => {
|
|
890
925
|
const path = `${partIdx}.${rowIdx}.${cell.start + j}`;
|
|
891
|
-
const cls = isPitched(note) ? " sw-p" : "";
|
|
892
926
|
const bar = note.bar !== void 0 ? ` sw-bar sw-bar--${note.bar}` : "";
|
|
893
|
-
return `<span class="sw-n${
|
|
927
|
+
return `<span class="sw-n${bar}${ink.notes[ci][j]}" data-note="${path}">${renderNote(note, cell.kind, opts[j], ctx)}</span>`;
|
|
894
928
|
}).join("");
|
|
895
|
-
out.push(`<span class="sw-cell${barCls}" style="grid-column:${col}">${notes}</span>`);
|
|
929
|
+
out.push(`<span class="sw-cell${barCls}${ink.cells[ci]}" style="grid-column:${col}">${notes}</span>`);
|
|
896
930
|
const slices = cellLyricSlices(cell);
|
|
897
931
|
if (slices !== void 0) {
|
|
898
932
|
const html = slices.map((t) => `<span>${escapeHtml(lyricText(t, ctx))}</span>`).join("");
|
|
@@ -905,7 +939,6 @@ function renderRow(row, partIdx, rowIdx, offset, ctx) {
|
|
|
905
939
|
if (below.length > 0)
|
|
906
940
|
out.push(`<span class="sw-below" style="grid-column:${col}">${renderAnnotation(below, ctx)}</span>`);
|
|
907
941
|
});
|
|
908
|
-
for (const arc of resolveArcs(cells)) out.push(renderArc(arc, offset));
|
|
909
942
|
return `<div class="sw-row">${out.join("")}</div>`;
|
|
910
943
|
}
|
|
911
944
|
function renderHeader(meta, ctx) {
|
|
@@ -963,7 +996,7 @@ function fitSwaralipi(root, minScale = 0, zoom = 1, minSpacing = 0.35, minSize =
|
|
|
963
996
|
sheet.style.removeProperty("--sw-size");
|
|
964
997
|
sheet.style.removeProperty("--sw-tight");
|
|
965
998
|
const available = scroll.clientWidth;
|
|
966
|
-
let natural = block.
|
|
999
|
+
let natural = block.offsetWidth;
|
|
967
1000
|
if (available === 0 || natural === 0) continue;
|
|
968
1001
|
if (natural > available && minSpacing < 1) {
|
|
969
1002
|
let loose = minSpacing;
|
|
@@ -971,11 +1004,11 @@ function fitSwaralipi(root, minScale = 0, zoom = 1, minSpacing = 0.35, minSize =
|
|
|
971
1004
|
for (let i = 0; i < 6; i++) {
|
|
972
1005
|
const mid = (loose + tight) / 2;
|
|
973
1006
|
sheet.style.setProperty("--sw-tight", String(mid));
|
|
974
|
-
if (block.
|
|
1007
|
+
if (block.offsetWidth <= available) loose = mid;
|
|
975
1008
|
else tight = mid;
|
|
976
1009
|
}
|
|
977
1010
|
sheet.style.setProperty("--sw-tight", String(loose));
|
|
978
|
-
natural = block.
|
|
1011
|
+
natural = block.offsetWidth;
|
|
979
1012
|
}
|
|
980
1013
|
const base = parseFloat(getComputedStyle(sheet).fontSize);
|
|
981
1014
|
if (!(base > 0)) continue;
|
|
@@ -1073,31 +1106,45 @@ ${FONT_FACES}
|
|
|
1073
1106
|
column-gap: calc(var(--sw-cell-gap, 0.4em) * var(--sw-tight, 1));
|
|
1074
1107
|
align-items: end;
|
|
1075
1108
|
width: max-content;
|
|
1109
|
+
/* The last column's cell spacers overhang half a gap past the grid; clip
|
|
1110
|
+
that sideways so it neither counts as width to fit nor raises a scrollbar. */
|
|
1111
|
+
overflow-x: clip;
|
|
1076
1112
|
}
|
|
1077
1113
|
.sw-part { display: contents; }
|
|
1114
|
+
/* Four FIXED bands per row \u2014 above / notation / arc / lyric \u2014 so a beat label,
|
|
1115
|
+
* a \u0995\u09A3 or a \u09AE\u09C0\u09A1\u09BC never changes how far a line sits from its words: the
|
|
1116
|
+
* notation hugs its lyric and the next system starts a little further off,
|
|
1117
|
+
* as the printed \u09B8\u09CD\u09AC\u09B0\u09AC\u09BF\u09A4\u09BE\u09A8 sets it. Content taller than its band overflows
|
|
1118
|
+
* rather than pushing the rhythm apart. */
|
|
1078
1119
|
.sw-row {
|
|
1079
1120
|
grid-column: 1 / -1;
|
|
1080
1121
|
display: grid;
|
|
1081
1122
|
grid-template-columns: subgrid;
|
|
1082
|
-
grid-template-rows:
|
|
1123
|
+
grid-template-rows: 0.95em 1.35em 0.4em 1.35em;
|
|
1083
1124
|
align-items: end;
|
|
1084
|
-
padding: 0.
|
|
1125
|
+
padding-bottom: 0.35em;
|
|
1126
|
+
line-height: 1.35;
|
|
1085
1127
|
}
|
|
1086
1128
|
.sw-label { grid-column: 1; grid-row: 2; padding-right: 0.5em; font-weight: 600; }
|
|
1087
1129
|
|
|
1088
|
-
/* One column per cell
|
|
1089
|
-
* flex
|
|
1090
|
-
*
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
.sw-cell
|
|
1094
|
-
.sw-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
.sw-
|
|
1100
|
-
.sw-
|
|
1130
|
+
/* One column per cell, its notes set tight as one word (\u09B0\u09B8\u09BE) and centred by
|
|
1131
|
+
* two flex spacers. Each spacer overhangs half the column gap (a min-width
|
|
1132
|
+
* paid back by a negative margin, so the column is sized by the notes alone),
|
|
1133
|
+
* which lets neighbouring cells' spacers meet mid-gap: a \u09AE\u09C0\u09A1\u09BC crossing cells is
|
|
1134
|
+
* inked by these boxes with no hole between them. */
|
|
1135
|
+
.sw-cell, .sw-lyr { display: flex; justify-content: center; white-space: nowrap; }
|
|
1136
|
+
.sw-cell {
|
|
1137
|
+
--sw-half-gap: calc(var(--sw-cell-gap, 0.4em) * var(--sw-tight, 1) / 2);
|
|
1138
|
+
grid-row: 2;
|
|
1139
|
+
align-self: stretch;
|
|
1140
|
+
}
|
|
1141
|
+
.sw-cell::before, .sw-cell::after { content: ''; flex: 1 0 0; min-width: var(--sw-half-gap); }
|
|
1142
|
+
.sw-cell::before { margin-left: calc(var(--sw-half-gap) * -1); }
|
|
1143
|
+
.sw-cell::after { margin-right: calc(var(--sw-half-gap) * -1); }
|
|
1144
|
+
.sw-cell > .sw-n { position: relative; }
|
|
1145
|
+
.sw-above { grid-row: 1; font-size: 0.62em; line-height: 1; justify-self: center; white-space: nowrap; }
|
|
1146
|
+
.sw-below { grid-row: 3; font-size: 0.62em; line-height: 1; justify-self: center; white-space: nowrap; }
|
|
1147
|
+
.sw-lyr { grid-row: 4; }
|
|
1101
1148
|
|
|
1102
1149
|
/* ---- notation clusters & marks ---- */
|
|
1103
1150
|
.sw-cl { position: relative; display: inline-block; }
|
|
@@ -1118,12 +1165,16 @@ ${FONT_FACES}
|
|
|
1118
1165
|
.sw-ati-taar::before { top: -0.3em; }
|
|
1119
1166
|
.sw-ati-mandra::before { bottom: -0.35em; }
|
|
1120
1167
|
|
|
1121
|
-
/* grace notes: small raised clusters \u2014 \u0995\u09A3 before the note, \u09B0\u09C7\u09B6 after it
|
|
1168
|
+
/* grace notes: small raised clusters \u2014 \u0995\u09A3 before the note, \u09B0\u09C7\u09B6 after it.
|
|
1169
|
+
* line-height 0 (here and on .sw-micro): a raised inline box taller than the
|
|
1170
|
+
* strut grows its line box and drops that one note's baseline below its
|
|
1171
|
+
* neighbours' (css2 \xA710.8). */
|
|
1122
1172
|
.sw-kan,
|
|
1123
1173
|
.sw-resh {
|
|
1124
1174
|
position: relative;
|
|
1125
1175
|
display: inline-block;
|
|
1126
1176
|
font-size: 0.58em;
|
|
1177
|
+
line-height: 0;
|
|
1127
1178
|
vertical-align: 0.75em;
|
|
1128
1179
|
}
|
|
1129
1180
|
.sw-kan { margin-right: 0.08em; }
|
|
@@ -1155,7 +1206,7 @@ ${FONT_FACES}
|
|
|
1155
1206
|
.sw-cut::before { top: 0.2em; }
|
|
1156
1207
|
.sw-cut::after { top: 0.55em; }
|
|
1157
1208
|
.sw-br { opacity: 0.8; padding: 0 0.06em; }
|
|
1158
|
-
.sw-micro { font-size: 0.6em; vertical-align: super; opacity: 0.8; }
|
|
1209
|
+
.sw-micro { font-size: 0.6em; line-height: 0; vertical-align: super; opacity: 0.8; }
|
|
1159
1210
|
|
|
1160
1211
|
/* raw fallback: never dropped, visibly non-notation. Swarabitan first \u2014
|
|
1161
1212
|
* raw IS that font's encoding, so undecoded cells show NLTR's own glyphs
|
|
@@ -1175,49 +1226,46 @@ ${FONT_FACES}
|
|
|
1175
1226
|
/* a bar owns a whole column but needs no matra of width */
|
|
1176
1227
|
.sw-bar-cell { min-width: 0; }
|
|
1177
1228
|
|
|
1178
|
-
/* ---- \u09AE\u09C0\u09A1\u09BC under-arcs (from w/x segments and spec meend) ----
|
|
1179
|
-
* Swarabitan
|
|
1180
|
-
* flat
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
.sw-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
.sw-
|
|
1193
|
-
.sw-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
}
|
|
1206
|
-
.sw-
|
|
1207
|
-
.sw-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
margin-bottom: -0.01em;
|
|
1219
|
-
background: currentColor;
|
|
1220
|
-
}
|
|
1229
|
+
/* ---- \u09AE\u09C0\u09A1\u09BC under-arcs (from w/x/$ segments and spec meend) ----
|
|
1230
|
+
* Swarabitan's own arc, all langs: w is the opening hook, curling down from
|
|
1231
|
+
* its tip into a flat, x its mirror, y that flat alone \u2014 and they join
|
|
1232
|
+
* hole-free, so one run of text is a whole end (tools/align-check/glyph.html).
|
|
1233
|
+
* Each end sets its hook tip on its note's centre and runs the flat toward the
|
|
1234
|
+
* other end (render.ts arcInk): across cells it is cut at the mid-gap, where
|
|
1235
|
+
* the next cell's run carries on (.sw-mk clips a cell half a gap past each
|
|
1236
|
+
* side, as far as its spacers reach); inside one cell, at its note's edge. So
|
|
1237
|
+
* a long arc extends the flat and a short one trims it off. line-height 0 sets
|
|
1238
|
+
* every run's baseline the same distance below its note. The clip reaches
|
|
1239
|
+
* 0.5px further so two cells' anti-aliased edges overlap instead of leaving a
|
|
1240
|
+
* hairline seam between their identical flats. */
|
|
1241
|
+
.sw-mk { clip-path: inset(-3em calc(var(--sw-half-gap) * -1 - 0.5px)); }
|
|
1242
|
+
.sw-mo::after, .sw-mob::after, .sw-mos::after,
|
|
1243
|
+
.sw-mc::before, .sw-mcb::before, .sw-mcs::before,
|
|
1244
|
+
.sw-mf::before, .sw-mm::before {
|
|
1245
|
+
content: 'yyyyyyyyyyyy';
|
|
1246
|
+
position: absolute;
|
|
1247
|
+
top: calc(100% + 0.05em);
|
|
1248
|
+
font-family: Swarabitan;
|
|
1249
|
+
font-size: 0.9em;
|
|
1250
|
+
line-height: 0;
|
|
1251
|
+
white-space: pre;
|
|
1252
|
+
overflow-x: clip;
|
|
1253
|
+
}
|
|
1254
|
+
.sw-mo::after, .sw-mob::after, .sw-mos::after { content: 'wyyyyyyyyyyyy'; }
|
|
1255
|
+
/* rtl: a closing run cut short keeps its hook on its right edge */
|
|
1256
|
+
.sw-mc::before, .sw-mcb::before, .sw-mcs::before { content: 'yyyyyyyyyyyyx'; direction: rtl; }
|
|
1257
|
+
.sw-mo::after, .sw-mob::after { left: 50%; }
|
|
1258
|
+
.sw-mc::before, .sw-mcb::before { right: 50%; }
|
|
1259
|
+
.sw-mos::after { left: 0; }
|
|
1260
|
+
.sw-mcs::before { right: 0; }
|
|
1261
|
+
.sw-mf::before { left: 0; right: 0; }
|
|
1262
|
+
.sw-mm::before { left: -12em; }
|
|
1263
|
+
/* Inside one cell a hook gets half a note to curl in, about a third of its
|
|
1264
|
+
* curl: squeezed to half width (same stroke) it lands flat at the cut, so the
|
|
1265
|
+
* two flats meet level whatever the notes' widths \u2014 a small arc, not a V. */
|
|
1266
|
+
.sw-mob::after, .sw-mos::after, .sw-mcb::before, .sw-mcs::before { width: 100%; transform: scaleX(0.5); }
|
|
1267
|
+
.sw-mob::after, .sw-mos::after { transform-origin: left; }
|
|
1268
|
+
.sw-mcb::before, .sw-mcs::before { transform-origin: right; }
|
|
1221
1269
|
|
|
1222
1270
|
/* ---- annotation content ---- */
|
|
1223
1271
|
.sw-beat { position: relative; display: inline-block; padding: 0 0.1em; }
|