tonus 0.11.1 → 0.13.0
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/CHANGELOG.md +44 -0
- package/dist/data/gabc-glyphs.d.ts +34 -2
- package/dist/data/gabc-glyphs.js +62 -5
- package/dist/data/kyriale.d.ts +4 -0
- package/dist/data/kyriale.js +147 -26
- package/dist/engines/chant/ordinary.js +39 -18
- package/dist/engines/chant/types.d.ts +7 -0
- package/dist/engines/score/emitters/svg.js +49 -6
- package/dist/engines/score/ir.js +4 -0
- package/dist/engines/score/parse.js +53 -5
- package/dist/engines/score/tabula.d.ts +9 -1
- package/dist/engines/score/tabula.js +4 -0
- package/dist/engines/score/types.d.ts +24 -1
- package/docs/api/chant.md +13 -6
- package/docs/api/score.md +12 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to tonus. Newest first.
|
|
4
4
|
|
|
5
|
+
## 0.13.0 — 2026-10-01
|
|
6
|
+
|
|
7
|
+
Every written head reaches its glyph.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Breaking: the hollow is a flag, not a shape.** `WrittenShape` loses
|
|
12
|
+
`cavum` and `linea` and gains `lineaPunctum` (gabc `R`, the punctum between
|
|
13
|
+
two vertical lines). A hollow note keeps its shape and sets `hollow`, since
|
|
14
|
+
gregorio empties a punctum, an inclinatum or a lineaPunctum alike. `linea`
|
|
15
|
+
could never be parsed; its glyph was the lineaPunctum's under a wrong label.
|
|
16
|
+
- `gr1`–`gr5` were read as hollow notes. They are full notes carrying a sign.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Rows carry `liquescence` (`~` deminutive, `<` ascending, `>` descending),
|
|
21
|
+
`oriscusDirection` (written `o0`/`o1`, or toward the next pitch that differs,
|
|
22
|
+
as gregorio resolves it), `hollow`, and `signum` (gabc `r1`–`r5`).
|
|
23
|
+
- The quadrata emitter draws the liquescent puncta and inclinata, the orisci
|
|
24
|
+
both ways and liquescent, the stropha and its auctus, the cavum and the
|
|
25
|
+
lineaPunctum (full and hollow) from their own Bravura glyphs, where it drew a
|
|
26
|
+
shrunk punctum for every liquescence. The signa print over the note; the
|
|
27
|
+
reversed accentus and the cup semicircle are Bravura's mirrored. A hollow
|
|
28
|
+
inclinatum, which Bravura does not carry, is the diamond's outline traced at
|
|
29
|
+
the staff line's weight — the way the score app already hollows it.
|
|
30
|
+
- A lone `s` is a stropha, as in gregorio.
|
|
31
|
+
|
|
32
|
+
## 0.12.0 — 2026-09-24
|
|
33
|
+
|
|
34
|
+
A mass number is a Mass.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **Breaking: `mass` is one of Masses I–XVIII, or 0.** The Kyriale's appendix
|
|
39
|
+
carried its Graduale page as a mass number, so Clemens Rector read as mass
|
|
40
|
+
75 and the Requiem as 94, 101 and 102. Two ad libitum Kyries whose incipits
|
|
41
|
+
carry a numeral were worse: they read as Masses VI and X, so
|
|
42
|
+
`ordinarium({ mass: 6 })` returned an appendix Kyrie beside Mass VI's own,
|
|
43
|
+
and the era rule dated it by Mass VI's century. Every entry now carries a
|
|
44
|
+
`section` (`mass`, `credo`, `sprinkling`, `ad-libitum`, `requiem`), and only
|
|
45
|
+
the `mass` section is numbered. `ordinarium({ section: "requiem" })` replaces
|
|
46
|
+
`ordinarium({ mass: 102 })`. The appendix still rotates in the book's order,
|
|
47
|
+
now read from its Graduale pages.
|
|
48
|
+
|
|
5
49
|
## 0.11.1 — 2026-09-10
|
|
6
50
|
|
|
7
51
|
The Kyriale says where it is printed.
|
|
@@ -13,14 +13,21 @@ export declare const GLYPH: {
|
|
|
13
13
|
readonly cClef: "E906";
|
|
14
14
|
readonly punctum: "E990";
|
|
15
15
|
readonly punctumInclinatum: "E991";
|
|
16
|
+
readonly punctumInclinatumAuctum: "E992";
|
|
17
|
+
readonly punctumInclinatumDeminutum: "E993";
|
|
18
|
+
readonly auctumAsc: "E994";
|
|
19
|
+
readonly auctumDesc: "E995";
|
|
16
20
|
readonly virga: "E996";
|
|
17
21
|
readonly virgaReversa: "E997";
|
|
18
22
|
readonly cavum: "E998";
|
|
19
|
-
readonly
|
|
23
|
+
readonly lineaPunctum: "E999";
|
|
24
|
+
readonly lineaPunctumCavum: "E99A";
|
|
20
25
|
readonly quilisma: "E99B";
|
|
21
26
|
readonly oriscusAsc: "E99C";
|
|
22
27
|
readonly oriscusDesc: "E99D";
|
|
28
|
+
readonly oriscusLiquescens: "E99E";
|
|
23
29
|
readonly strophicus: "E99F";
|
|
30
|
+
readonly strophicusAuctus: "E9A0";
|
|
24
31
|
readonly punctumDeminutum: "E9A1";
|
|
25
32
|
readonly custosUp: readonly ["EA04", "EA05", "EA06"];
|
|
26
33
|
readonly custosDown: readonly ["EA07", "EA08", "EA09"];
|
|
@@ -28,14 +35,39 @@ export declare const GLYPH: {
|
|
|
28
35
|
readonly podatusUpper: "E9B1";
|
|
29
36
|
readonly ictusAbove: "E9D0";
|
|
30
37
|
readonly ictusBelow: "E9D1";
|
|
38
|
+
readonly circulus: "E9D2";
|
|
39
|
+
readonly semicirculus: "E9D4";
|
|
40
|
+
readonly accentus: "E9D6";
|
|
31
41
|
readonly episema: "E9D8";
|
|
32
42
|
readonly mora: "E9D9";
|
|
33
43
|
readonly flat: "E9E0";
|
|
34
44
|
readonly natural: "E9E1";
|
|
35
45
|
readonly sharp: "E262";
|
|
36
46
|
};
|
|
37
|
-
/** Written note shape → notehead glyph codepoint. */
|
|
47
|
+
/** Written note shape → notehead glyph codepoint, before liquescence and the hollow. */
|
|
38
48
|
export declare const SHAPE_GLYPH: Readonly<Record<string, string>>;
|
|
49
|
+
/** The fields of a note that choose its head. */
|
|
50
|
+
export interface HeadSpec {
|
|
51
|
+
shape: string;
|
|
52
|
+
liquescence: "deminutive" | "ascending" | "descending" | null;
|
|
53
|
+
oriscusDirection: "ascending" | "descending" | null;
|
|
54
|
+
hollow: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The notehead for a note, or null when Bravura draws no head for that
|
|
58
|
+
* combination (a liquescent virga or quilisma) and the caller keeps its
|
|
59
|
+
* fallback. Gregorio's rules: an oriscus takes only the deminutive
|
|
60
|
+
* liquescence; a strophicus either augmentation as its auctus. A hollow
|
|
61
|
+
* inclinatum returns the full diamond: Bravura has no cavum of it, so the
|
|
62
|
+
* emitter traces that outline instead (see `tracedHollow`).
|
|
63
|
+
*/
|
|
64
|
+
export declare function headGlyph(n: HeadSpec): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* A hollow head Bravura does not carry, drawn as its full glyph's outline:
|
|
67
|
+
* the inclinatum (gabc Gr, G<r). The score app hollows its diamond the same
|
|
68
|
+
* way, so the two agree.
|
|
69
|
+
*/
|
|
70
|
+
export declare function tracedHollow(n: HeadSpec): boolean;
|
|
39
71
|
/** Divisio mark → glyph codepoint. */
|
|
40
72
|
export declare const DIVISIO_GLYPH: Readonly<Record<string, string>>;
|
|
41
73
|
/** EntryLineAsc component for a rising interval of `steps` diatonic degrees. */
|
package/dist/data/gabc-glyphs.js
CHANGED
|
@@ -30,17 +30,27 @@ export const GLYPH = {
|
|
|
30
30
|
// clefs
|
|
31
31
|
fClef: "E902",
|
|
32
32
|
cClef: "E906",
|
|
33
|
-
// single notes
|
|
33
|
+
// single notes (SMuFL plainchant, E990–E9A1)
|
|
34
34
|
punctum: "E990",
|
|
35
35
|
punctumInclinatum: "E991",
|
|
36
|
+
punctumInclinatumAuctum: "E992",
|
|
37
|
+
punctumInclinatumDeminutum: "E993",
|
|
38
|
+
auctumAsc: "E994",
|
|
39
|
+
auctumDesc: "E995",
|
|
36
40
|
virga: "E996",
|
|
37
41
|
virgaReversa: "E997",
|
|
38
42
|
cavum: "E998",
|
|
39
|
-
|
|
43
|
+
// chantPunctumLinea: a punctum BETWEEN two vertical lines, gabc R (and, hollow,
|
|
44
|
+
// r0). Not the linea — gabc's `=` bar-shaped note, which SMuFL does not carry.
|
|
45
|
+
// gabc-smufl's map labels it "bar note, no notehead"; the outline says otherwise.
|
|
46
|
+
lineaPunctum: "E999",
|
|
47
|
+
lineaPunctumCavum: "E99A",
|
|
40
48
|
quilisma: "E99B",
|
|
41
49
|
oriscusAsc: "E99C",
|
|
42
50
|
oriscusDesc: "E99D",
|
|
51
|
+
oriscusLiquescens: "E99E",
|
|
43
52
|
strophicus: "E99F",
|
|
53
|
+
strophicusAuctus: "E9A0",
|
|
44
54
|
punctumDeminutum: "E9A1",
|
|
45
55
|
// THE CUSTOS, added to the bake 2026-08-12. Bravura carries it at EA00-EA09
|
|
46
56
|
// and the subset did not, so the emitter drew a plain punctum at a line's
|
|
@@ -75,6 +85,9 @@ export const GLYPH = {
|
|
|
75
85
|
// rhythmic signs
|
|
76
86
|
ictusAbove: "E9D0",
|
|
77
87
|
ictusBelow: "E9D1",
|
|
88
|
+
circulus: "E9D2",
|
|
89
|
+
semicirculus: "E9D4",
|
|
90
|
+
accentus: "E9D6",
|
|
78
91
|
episema: "E9D8",
|
|
79
92
|
mora: "E9D9",
|
|
80
93
|
// accidentals (medieval soft-b flat / natural; standard sharp fallback).
|
|
@@ -85,7 +98,7 @@ export const GLYPH = {
|
|
|
85
98
|
natural: "E9E1",
|
|
86
99
|
sharp: "E262",
|
|
87
100
|
};
|
|
88
|
-
/** Written note shape → notehead glyph codepoint. */
|
|
101
|
+
/** Written note shape → notehead glyph codepoint, before liquescence and the hollow. */
|
|
89
102
|
export const SHAPE_GLYPH = Object.freeze({
|
|
90
103
|
punctum: GLYPH.punctum,
|
|
91
104
|
inclinatum: GLYPH.punctumInclinatum,
|
|
@@ -94,9 +107,53 @@ export const SHAPE_GLYPH = Object.freeze({
|
|
|
94
107
|
quilisma: GLYPH.quilisma,
|
|
95
108
|
oriscus: GLYPH.oriscusAsc,
|
|
96
109
|
strophicus: GLYPH.strophicus,
|
|
97
|
-
|
|
98
|
-
linea: GLYPH.linea,
|
|
110
|
+
lineaPunctum: GLYPH.lineaPunctum,
|
|
99
111
|
});
|
|
112
|
+
/**
|
|
113
|
+
* The notehead for a note, or null when Bravura draws no head for that
|
|
114
|
+
* combination (a liquescent virga or quilisma) and the caller keeps its
|
|
115
|
+
* fallback. Gregorio's rules: an oriscus takes only the deminutive
|
|
116
|
+
* liquescence; a strophicus either augmentation as its auctus. A hollow
|
|
117
|
+
* inclinatum returns the full diamond: Bravura has no cavum of it, so the
|
|
118
|
+
* emitter traces that outline instead (see `tracedHollow`).
|
|
119
|
+
*/
|
|
120
|
+
export function headGlyph(n) {
|
|
121
|
+
const liq = n.liquescence;
|
|
122
|
+
switch (n.shape) {
|
|
123
|
+
case "punctum":
|
|
124
|
+
if (liq === "deminutive")
|
|
125
|
+
return GLYPH.punctumDeminutum;
|
|
126
|
+
if (liq === "ascending")
|
|
127
|
+
return GLYPH.auctumAsc;
|
|
128
|
+
if (liq === "descending")
|
|
129
|
+
return GLYPH.auctumDesc;
|
|
130
|
+
return n.hollow ? GLYPH.cavum : GLYPH.punctum;
|
|
131
|
+
case "inclinatum":
|
|
132
|
+
if (liq === "deminutive")
|
|
133
|
+
return GLYPH.punctumInclinatumDeminutum;
|
|
134
|
+
if (liq)
|
|
135
|
+
return GLYPH.punctumInclinatumAuctum;
|
|
136
|
+
return GLYPH.punctumInclinatum;
|
|
137
|
+
case "oriscus":
|
|
138
|
+
if (liq === "deminutive")
|
|
139
|
+
return GLYPH.oriscusLiquescens;
|
|
140
|
+
return n.oriscusDirection === "descending" ? GLYPH.oriscusDesc : GLYPH.oriscusAsc;
|
|
141
|
+
case "strophicus":
|
|
142
|
+
return liq ? GLYPH.strophicusAuctus : GLYPH.strophicus;
|
|
143
|
+
case "lineaPunctum":
|
|
144
|
+
return n.hollow ? GLYPH.lineaPunctumCavum : GLYPH.lineaPunctum;
|
|
145
|
+
default:
|
|
146
|
+
return liq ? null : SHAPE_GLYPH[n.shape] ?? null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* A hollow head Bravura does not carry, drawn as its full glyph's outline:
|
|
151
|
+
* the inclinatum (gabc Gr, G<r). The score app hollows its diamond the same
|
|
152
|
+
* way, so the two agree.
|
|
153
|
+
*/
|
|
154
|
+
export function tracedHollow(n) {
|
|
155
|
+
return n.hollow && n.shape === "inclinatum";
|
|
156
|
+
}
|
|
100
157
|
/** Divisio mark → glyph codepoint. */
|
|
101
158
|
export const DIVISIO_GLYPH = Object.freeze({
|
|
102
159
|
",": GLYPH.divisioMinima,
|
package/dist/data/kyriale.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export type KyrialeOffice = "ke" | "gl" | "cr" | "sa" | "ag" | "be" | "it" | "as" | "va";
|
|
2
|
+
/** Where the Kyriale prints an entry. Only `mass` entries carry a mass number. */
|
|
3
|
+
export type KyrialeSection = "mass" | "credo" | "sprinkling" | "ad-libitum" | "requiem";
|
|
2
4
|
export interface KyrialeEntry {
|
|
3
5
|
id: string;
|
|
4
6
|
office: KyrialeOffice;
|
|
7
|
+
section: KyrialeSection;
|
|
8
|
+
/** One of Masses I–XVIII, or null outside the numbered Masses. */
|
|
5
9
|
mass: number | null;
|
|
6
10
|
mode: string | null;
|
|
7
11
|
incipit: string;
|