@ugfoundation/swaralipi-js 0.1.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/LICENSE +347 -0
- package/README.md +257 -0
- package/dist/batch-NF2Q2CFS.js +47 -0
- package/dist/batch-NF2Q2CFS.js.map +1 -0
- package/dist/chunk-C6O7DYU5.js +115 -0
- package/dist/chunk-C6O7DYU5.js.map +1 -0
- package/dist/chunk-GWXI2HJA.js +14 -0
- package/dist/chunk-GWXI2HJA.js.map +1 -0
- package/dist/chunk-N3NNWAOW.js +593 -0
- package/dist/chunk-N3NNWAOW.js.map +1 -0
- package/dist/cli.cjs +913 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +91 -0
- package/dist/cli.js.map +1 -0
- package/dist/convert/index.cjs +720 -0
- package/dist/convert/index.cjs.map +1 -0
- package/dist/convert/index.d.cts +270 -0
- package/dist/convert/index.d.ts +270 -0
- package/dist/convert/index.js +5 -0
- package/dist/convert/index.js.map +1 -0
- package/dist/index.cjs +143 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/player/index.cjs +775 -0
- package/dist/player/index.cjs.map +1 -0
- package/dist/player/index.d.cts +285 -0
- package/dist/player/index.d.ts +285 -0
- package/dist/player/index.js +743 -0
- package/dist/player/index.js.map +1 -0
- package/dist/schema-gxhG45OK.d.cts +467 -0
- package/dist/schema-gxhG45OK.d.ts +467 -0
- package/dist/spec/index.cjs +143 -0
- package/dist/spec/index.cjs.map +1 -0
- package/dist/spec/index.d.cts +70 -0
- package/dist/spec/index.d.ts +70 -0
- package/dist/spec/index.js +4 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/taals-DguYW0wf.d.cts +60 -0
- package/dist/taals-DguYW0wf.d.ts +60 -0
- package/dist/viewer/index.cjs +998 -0
- package/dist/viewer/index.cjs.map +1 -0
- package/dist/viewer/index.d.cts +285 -0
- package/dist/viewer/index.d.ts +285 -0
- package/dist/viewer/index.js +814 -0
- package/dist/viewer/index.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { S as Swaralipi, N as Note, T as Taal } from '../schema-gxhG45OK.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* NLTR HTML extraction — the lowest layer of the converter.
|
|
6
|
+
*
|
|
7
|
+
* The 1,738 cached NLTR pages are machine-generated and 100% structurally
|
|
8
|
+
* uniform (verified across all 2.79M cells), so extraction is deliberately
|
|
9
|
+
* a strict regex parse with a count assertion rather than a lenient DOM
|
|
10
|
+
* walk: any structural surprise fails the file loudly (`ExtractError`)
|
|
11
|
+
* instead of silently mis-treeing.
|
|
12
|
+
*
|
|
13
|
+
* Page anatomy:
|
|
14
|
+
* - a metadata table of `style3` triples: label (নাম / তাল / আবর্তন), ':',
|
|
15
|
+
* value;
|
|
16
|
+
* - one grid of cells `<td width='auto' id=R.C> <span class='styleN'>
|
|
17
|
+
* <div align='center'>TOKEN</div></span></td>` where `id` is the
|
|
18
|
+
* `row.col` coordinate (often unquoted) and ` ` marks an empty cell.
|
|
19
|
+
*/
|
|
20
|
+
/** One grid cell. `text` is entity-decoded and whitespace-normalized ('' = empty). */
|
|
21
|
+
interface RawCell {
|
|
22
|
+
row: number;
|
|
23
|
+
col: number;
|
|
24
|
+
/** `style1` = Swarabitan notation, `style2` = Bengali lyric. */
|
|
25
|
+
style: string;
|
|
26
|
+
text: string;
|
|
27
|
+
}
|
|
28
|
+
/** The style3 metadata header values, verbatim (Bengali). */
|
|
29
|
+
interface NltrHeader {
|
|
30
|
+
title?: string;
|
|
31
|
+
taalNameRaw?: string;
|
|
32
|
+
avartanRaw?: string;
|
|
33
|
+
/** NLTR's internal print node id (`/print/<id>`), for provenance. */
|
|
34
|
+
printId?: number;
|
|
35
|
+
}
|
|
36
|
+
interface NltrPage {
|
|
37
|
+
header: NltrHeader;
|
|
38
|
+
cells: RawCell[];
|
|
39
|
+
maxRow: number;
|
|
40
|
+
}
|
|
41
|
+
/** Structural surprise in the source HTML (not a decode problem). */
|
|
42
|
+
declare class ExtractError extends Error {
|
|
43
|
+
constructor(message: string);
|
|
44
|
+
}
|
|
45
|
+
/** Parse one NLTR swaralipi page. Throws `ExtractError` on structural surprise. */
|
|
46
|
+
declare function extractPage(html: string): NltrPage;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Conversion reporting: per-file decode statistics and the batch aggregate.
|
|
50
|
+
* The unknown-token histogram is the feedback loop for growing the codec.
|
|
51
|
+
*/
|
|
52
|
+
interface FileReport {
|
|
53
|
+
nltrId?: number;
|
|
54
|
+
title: string;
|
|
55
|
+
taalName?: string;
|
|
56
|
+
taalId?: string;
|
|
57
|
+
taalMatched: 'taals' | 'table' | 'geometry' | 'none';
|
|
58
|
+
systems: number;
|
|
59
|
+
notationCells: number;
|
|
60
|
+
lyricCells: number;
|
|
61
|
+
annotationCells: number;
|
|
62
|
+
/** Notation cells with ≥1 semantic note and no unknown chunk. */
|
|
63
|
+
decodedCells: number;
|
|
64
|
+
/** Notation cells consisting only of understood-but-raw marks. */
|
|
65
|
+
knownRawCells: number;
|
|
66
|
+
/** Notation cells containing ≥1 chunk outside the grammar. */
|
|
67
|
+
unknownCells: number;
|
|
68
|
+
unknownTokens: Record<string, number>;
|
|
69
|
+
lyricAlignMismatches: number;
|
|
70
|
+
warnings: string[];
|
|
71
|
+
}
|
|
72
|
+
interface BatchFailure {
|
|
73
|
+
file: string;
|
|
74
|
+
error: string;
|
|
75
|
+
}
|
|
76
|
+
interface BatchReport {
|
|
77
|
+
files: number;
|
|
78
|
+
ok: number;
|
|
79
|
+
failed: number;
|
|
80
|
+
failures: BatchFailure[];
|
|
81
|
+
systems: number;
|
|
82
|
+
notationCells: number;
|
|
83
|
+
lyricCells: number;
|
|
84
|
+
annotationCells: number;
|
|
85
|
+
decodedCells: number;
|
|
86
|
+
knownRawCells: number;
|
|
87
|
+
unknownCells: number;
|
|
88
|
+
/** decoded / (decoded + knownRaw + unknown) over notation cells. */
|
|
89
|
+
decodeRate: number;
|
|
90
|
+
unknownRate: number;
|
|
91
|
+
/** All unknown tokens, sorted by frequency (descending). */
|
|
92
|
+
unknownTokens: Record<string, number>;
|
|
93
|
+
lyricAlignMismatches: number;
|
|
94
|
+
/** taalName → count + resolution outcome. */
|
|
95
|
+
taals: Record<string, {
|
|
96
|
+
count: number;
|
|
97
|
+
taalId?: string;
|
|
98
|
+
matched: string;
|
|
99
|
+
}>;
|
|
100
|
+
warningCounts: Record<string, number>;
|
|
101
|
+
}
|
|
102
|
+
declare function aggregate(reports: FileReport[], failures: BatchFailure[]): BatchReport;
|
|
103
|
+
declare function formatSummary(r: BatchReport): string;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Assembly: systems → spec document.
|
|
107
|
+
*
|
|
108
|
+
* Each system becomes one `Row`. Within a row, columns are walked in order;
|
|
109
|
+
* a notation cell's decoded notes join the row, with the column-aligned
|
|
110
|
+
* lyric / above / below content attached to the cell's first note. Columns
|
|
111
|
+
* that have lyric or annotation content but no notation emit a carrier note
|
|
112
|
+
* (legal per the spec refine). The whole song is one unnamed part: NLTR
|
|
113
|
+
* prints no section labels, and `ll` cannot be split on safely because it
|
|
114
|
+
* also marks mid-song asthayi returns.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
interface ConvertOptions {
|
|
118
|
+
/** NLTR song/node id (usually the source filename). */
|
|
119
|
+
nltrId?: number;
|
|
120
|
+
/** Override the provenance URL stored in `meta.source`. */
|
|
121
|
+
source?: string;
|
|
122
|
+
}
|
|
123
|
+
interface ConvertResult {
|
|
124
|
+
doc: Swaralipi;
|
|
125
|
+
report: FileReport;
|
|
126
|
+
}
|
|
127
|
+
/** Split a lyric cell into grapheme clusters (ক+া = 1, র+্ = 1, ৹ = 1). */
|
|
128
|
+
declare function splitLyric(text: string): string[];
|
|
129
|
+
declare function assemble(page: NltrPage, opts?: ConvertOptions): ConvertResult;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Grid → systems.
|
|
133
|
+
*
|
|
134
|
+
* Rows group into 4-row "systems", role given by `row % 4` (verified with
|
|
135
|
+
* zero exceptions across the whole corpus):
|
|
136
|
+
* 0 → annotation row rendered ABOVE the staff (alt-on-repeat passages,
|
|
137
|
+
* stop marks, beat numbers — sparse),
|
|
138
|
+
* 1 → notation row (style1, Swarabitan codes),
|
|
139
|
+
* 2 → annotation row rendered BELOW the staff (sparse),
|
|
140
|
+
* 3 → lyric row (style2, Bengali).
|
|
141
|
+
* Cells align across the four rows strictly by column id (rows can be
|
|
142
|
+
* ragged, so never align by index).
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
interface System {
|
|
146
|
+
/** System index (source rows 4k..4k+3). */
|
|
147
|
+
index: number;
|
|
148
|
+
above: Map<number, string>;
|
|
149
|
+
notation: Map<number, string>;
|
|
150
|
+
below: Map<number, string>;
|
|
151
|
+
lyric: Map<number, string>;
|
|
152
|
+
maxCol: number;
|
|
153
|
+
}
|
|
154
|
+
declare function buildSystems(page: NltrPage): {
|
|
155
|
+
systems: System[];
|
|
156
|
+
warnings: string[];
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The Swarabitan ASCII codec: decode one grid-cell text into spec `Note`s.
|
|
161
|
+
*
|
|
162
|
+
* NLTR renders notation through the legacy "Swarabitan" webfont, which maps
|
|
163
|
+
* ASCII to akarmatrik glyphs. The table below was derived by dumping every
|
|
164
|
+
* glyph of `Swarabitan.woff` (tools/font-dump/) and cross-checking against
|
|
165
|
+
* the Swarabitan legend scans, the rendered reference screenshot of song
|
|
166
|
+
* 4270, and corpus-wide token statistics. Evidence per assignment:
|
|
167
|
+
*
|
|
168
|
+
* Letters (full-size glyphs):
|
|
169
|
+
* s=স r=র g=গ m=ম p=প q=ধ n=ন — the seven shuddha letters
|
|
170
|
+
* d=দ (komal dha) t=জ্ঞ (komal ga) — legend: কোমল র—ঋ, কোমল গ—জ্ঞ,
|
|
171
|
+
* k=ক্ষ (tivra ma) u=ণ (komal ni) — কড়ি ম—ক্ষ, কোমল ধ—দ, কোমল ন—ণ
|
|
172
|
+
* v=ঋ (komal re)
|
|
173
|
+
* Modifiers:
|
|
174
|
+
* f = রেফ above → taar octave (zero-width high combining mark)
|
|
175
|
+
* h = হসন্ত below → mandra octave (low combining mark; corpus nh/uh/dh/ph)
|
|
176
|
+
* leading '-' = no new vowel attack (melisma; lyric row shows ৹)
|
|
177
|
+
* trailing 'a' = the আ-কার matra carrier; k letter-units in one cell
|
|
178
|
+
* share it → k notes of 1/k matra each
|
|
179
|
+
* UPPERCASE letter = small raised form = কণ (kan/grace) prefix; takes its
|
|
180
|
+
* own f/h (corpus: Sfua, NHsa, QHpha); width ratios ~0.65
|
|
181
|
+
* confirm uppercase↔lowercase pairing
|
|
182
|
+
* Structurals (own cells):
|
|
183
|
+
* A = thin full-height bar → দাঁড়ি vibhag separator (fixed columns)
|
|
184
|
+
* l = serif danda I → cycle end; ll / single-glyph L = section
|
|
185
|
+
* %=সা &=নি — precomposed one-matra forms (rare)
|
|
186
|
+
* Known-but-kept-raw marks (drawn pieces the spec doesn't model yet):
|
|
187
|
+
* w x = left/right ends of a long under-arc; E J j y $ < > = _ = arc/line
|
|
188
|
+
* fill segments; | = thin yugal-dari stop mark (mostly annotation rows);
|
|
189
|
+
* digits/!/@ (+f/F sam tick) = taal beat labels; b=× o O e ` + , . i : ;
|
|
190
|
+
* = dots/ticks/duration marks; B C * ^ ~ c = rare precomposed/legacy forms.
|
|
191
|
+
*
|
|
192
|
+
* Decoding never throws: any chunk outside the grammar becomes a raw-only
|
|
193
|
+
* note and is reported as unknown — zero data loss by construction.
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
interface CellDecode {
|
|
197
|
+
notes: Note[];
|
|
198
|
+
/** Chunks that failed the grammar (reported, kept as raw notes). */
|
|
199
|
+
unknownTokens: string[];
|
|
200
|
+
/** Chunks understood but intentionally left raw (marks, beat labels …). */
|
|
201
|
+
knownRawTokens: string[];
|
|
202
|
+
/** True if at least one chunk decoded to a semantic note. */
|
|
203
|
+
decoded: boolean;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Decode one cell's text. Multi-chunk cells (whitespace-separated) emit
|
|
207
|
+
* notes in order; the first note of each chunk carries that chunk's source
|
|
208
|
+
* text in `raw`, so joining a cell's `raw` values with spaces reproduces
|
|
209
|
+
* the normalized cell text (the lossless property tests rely on this).
|
|
210
|
+
*/
|
|
211
|
+
declare function decodeCell(text: string): CellDecode;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Resolve the printed Bengali তাল name (+ the grid's own geometry) into a
|
|
215
|
+
* spec `Taal`.
|
|
216
|
+
*
|
|
217
|
+
* Evidence chain, strongest first:
|
|
218
|
+
* 1. bhaag hints in the name itself — `ধামার(৩/২/২/৩/৪)` → [3,2,2,3,4];
|
|
219
|
+
* 2. the name table below (the 7 player-sampled taals from TAALS, plus
|
|
220
|
+
* well-attested Rabindrik taals with stable definitions);
|
|
221
|
+
* 3. the grid geometry: bar/dari columns partition each cycle into bhaags
|
|
222
|
+
* (`numCols = avartan × (numBeats + nDaris) + 1` held on every checked
|
|
223
|
+
* song), which both derives unknown taals and cross-checks named ones.
|
|
224
|
+
* তালমুক্ত (free rhythm) and unresolvable names yield no `taal`; the
|
|
225
|
+
* verbatim name always lands in `meta.taalName`.
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/** Parse an integer written with Bengali or ASCII digits. */
|
|
229
|
+
declare function bnInt(s: string | undefined): number | undefined;
|
|
230
|
+
interface GridGeometry {
|
|
231
|
+
/** Total columns of the widest full notation row. */
|
|
232
|
+
numCols: number;
|
|
233
|
+
/** Matra count of one cycle (notes between cycle bars, daris excluded). */
|
|
234
|
+
numBeats?: number;
|
|
235
|
+
/** Bhaag division of one cycle, from dari positions. */
|
|
236
|
+
bhaags?: number[];
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Derive cycle geometry from the first notation row shaped `bar … bar`.
|
|
240
|
+
* Returns per-cycle numBeats/bhaags when at least one full cycle is visible.
|
|
241
|
+
*/
|
|
242
|
+
declare function deriveGeometry(systems: System[]): GridGeometry | undefined;
|
|
243
|
+
interface ResolvedTaal {
|
|
244
|
+
taal?: Taal;
|
|
245
|
+
taalName?: string;
|
|
246
|
+
avartan?: number;
|
|
247
|
+
/** Which evidence resolved the taal. */
|
|
248
|
+
matched: 'taals' | 'table' | 'geometry' | 'none';
|
|
249
|
+
warnings: string[];
|
|
250
|
+
}
|
|
251
|
+
declare function resolveTaal(nameRaw: string | undefined, avartanRaw: string | undefined, geometry: GridGeometry | undefined): ResolvedTaal;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @ugfoundation/swaralipi-js/convert
|
|
255
|
+
*
|
|
256
|
+
* NLTR HTML → swaralipi JSON converter (Node-only subpath export).
|
|
257
|
+
* `convertNltrHtml` itself is pure (string in, document out); file/dir
|
|
258
|
+
* batch helpers live in the CLI (`swaralipi convert`).
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Convert one NLTR swaralipi page (HTML source text) into a validated
|
|
263
|
+
* spec document plus a decode report.
|
|
264
|
+
*
|
|
265
|
+
* Throws `ExtractError` when the HTML does not look like an NLTR swaralipi
|
|
266
|
+
* grid; cell-level decode problems never throw (they degrade to `raw`).
|
|
267
|
+
*/
|
|
268
|
+
declare function convertNltrHtml(html: string, opts?: ConvertOptions): ConvertResult;
|
|
269
|
+
|
|
270
|
+
export { type BatchFailure, type BatchReport, type CellDecode, type ConvertOptions, type ConvertResult, ExtractError, type FileReport, type GridGeometry, type NltrHeader, type NltrPage, type RawCell, type ResolvedTaal, type System, aggregate, assemble, bnInt, buildSystems, convertNltrHtml, decodeCell, deriveGeometry, extractPage, formatSummary, resolveTaal, splitLyric };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ExtractError, aggregate, assemble, bnInt, buildSystems, convertNltrHtml, decodeCell, deriveGeometry, extractPage, formatSummary, resolveTaal, splitLyric } from '../chunk-N3NNWAOW.js';
|
|
2
|
+
import '../chunk-C6O7DYU5.js';
|
|
3
|
+
import '../chunk-GWXI2HJA.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
|
|
5
|
+
// src/spec/schema.ts
|
|
6
|
+
var octaveSchema = zod.z.enum([
|
|
7
|
+
"ati-mandra",
|
|
8
|
+
// very low
|
|
9
|
+
"mandra",
|
|
10
|
+
// low (dot below)
|
|
11
|
+
"madhyam",
|
|
12
|
+
// middle
|
|
13
|
+
"taar",
|
|
14
|
+
// high (ref/dot above)
|
|
15
|
+
"ati-taar"
|
|
16
|
+
// very high
|
|
17
|
+
]);
|
|
18
|
+
var svaraLetterSchema = zod.z.enum(["s", "r", "g", "m", "p", "d", "n"]);
|
|
19
|
+
var svaraSchema = zod.z.tuple([octaveSchema, svaraLetterSchema]);
|
|
20
|
+
var microtoneSchema = zod.z.enum(["alpakomal", "atikomal"]);
|
|
21
|
+
var barSchema = zod.z.enum(["dari", "single", "double", "quad"]);
|
|
22
|
+
var bracketSchema = zod.z.object({
|
|
23
|
+
kind: zod.z.enum(["repeat", "skip", "alt"]),
|
|
24
|
+
edge: zod.z.enum(["open", "close"])
|
|
25
|
+
});
|
|
26
|
+
var noteSchema = zod.z.lazy(
|
|
27
|
+
() => zod.z.object({
|
|
28
|
+
svara: svaraSchema.optional(),
|
|
29
|
+
komal: zod.z.boolean().optional(),
|
|
30
|
+
tivra: zod.z.boolean().optional(),
|
|
31
|
+
microtone: microtoneSchema.optional(),
|
|
32
|
+
durationMatra: zod.z.number().positive().optional(),
|
|
33
|
+
sustain: zod.z.boolean().optional(),
|
|
34
|
+
rest: zod.z.boolean().optional(),
|
|
35
|
+
kan: svaraSchema.optional(),
|
|
36
|
+
meend: zod.z.enum(["start", "end"]).optional(),
|
|
37
|
+
bar: barSchema.optional(),
|
|
38
|
+
brackets: zod.z.array(bracketSchema).optional(),
|
|
39
|
+
lyric: zod.z.string().optional(),
|
|
40
|
+
raw: zod.z.string().optional(),
|
|
41
|
+
above: zod.z.array(noteSchema).optional(),
|
|
42
|
+
below: zod.z.array(noteSchema).optional()
|
|
43
|
+
}).refine(
|
|
44
|
+
(n) => n.svara !== void 0 || n.rest === true || n.sustain === true || n.bar !== void 0 || n.raw !== void 0 || n.brackets !== void 0 && n.brackets.length > 0 || n.above !== void 0 && n.above.length > 0 || n.below !== void 0 && n.below.length > 0 || n.lyric !== void 0,
|
|
45
|
+
{
|
|
46
|
+
message: "note must carry one of: svara, rest, sustain, bar, raw, lyric, brackets, or a non-empty above/below"
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
var rowSchema = zod.z.object({
|
|
51
|
+
/** Optional line label (e.g. a tuk/section marker). */
|
|
52
|
+
label: zod.z.string().optional(),
|
|
53
|
+
notes: zod.z.array(noteSchema)
|
|
54
|
+
});
|
|
55
|
+
var partSchema = zod.z.object({
|
|
56
|
+
name: zod.z.string().optional(),
|
|
57
|
+
rows: zod.z.array(rowSchema)
|
|
58
|
+
});
|
|
59
|
+
var taalSchema = zod.z.object({
|
|
60
|
+
/** Player sample key, e.g. `dadra`, `teentaal`. */
|
|
61
|
+
id: zod.z.string(),
|
|
62
|
+
numBeats: zod.z.number().int().positive(),
|
|
63
|
+
/** Vibhag groupings; if given, they sum to numBeats. */
|
|
64
|
+
bhaags: zod.z.array(zod.z.number().int().positive()).optional(),
|
|
65
|
+
/** Sam (cycle start) beat index, 0-based. */
|
|
66
|
+
sam: zod.z.number().int().nonnegative().optional(),
|
|
67
|
+
/** Khaali (wave) beat indices, 0-based. */
|
|
68
|
+
khaali: zod.z.array(zod.z.number().int().nonnegative()).optional()
|
|
69
|
+
}).refine((t) => t.bhaags === void 0 || t.bhaags.reduce((a, b) => a + b, 0) === t.numBeats, {
|
|
70
|
+
message: "bhaags must sum to numBeats"
|
|
71
|
+
});
|
|
72
|
+
var metaSchema = zod.z.object({
|
|
73
|
+
title: zod.z.string(),
|
|
74
|
+
/** Cross-reference to a gitabitan.io song content id (filename, immutable). */
|
|
75
|
+
songId: zod.z.string().optional(),
|
|
76
|
+
/** Source NLTR node/song id. */
|
|
77
|
+
nltrId: zod.z.number().int().optional(),
|
|
78
|
+
taal: taalSchema.optional(),
|
|
79
|
+
/**
|
|
80
|
+
* The taal name exactly as printed in the source (e.g. `তালমুক্ত`,
|
|
81
|
+
* `ষষ্ঠী(২/৪)`). Always set by the NLTR converter; `taal` is set only
|
|
82
|
+
* when the name resolves to a known definition.
|
|
83
|
+
*/
|
|
84
|
+
taalName: zod.z.string().optional(),
|
|
85
|
+
/** Base pitch for playback, e.g. `C`, `C#`, or the player's `cs` form. */
|
|
86
|
+
tonic: zod.z.string().optional(),
|
|
87
|
+
/** Default playback tempo in matra/min. Player-only — the viewer ignores it.
|
|
88
|
+
* The player adopts it on `load()` (precedence: constructor `bpm` → `setBpm`
|
|
89
|
+
* tweak → this → 90). `null` is the converter's blank placeholder = unset. */
|
|
90
|
+
bpm: zod.z.number().positive().nullable().optional(),
|
|
91
|
+
raag: zod.z.string().optional(),
|
|
92
|
+
/** আবর্তন: number of taal cycles, when the source states it. */
|
|
93
|
+
avartan: zod.z.number().int().positive().optional(),
|
|
94
|
+
/** স্বরলিপিকার (notation author). */
|
|
95
|
+
notationBy: zod.z.string().optional(),
|
|
96
|
+
/** Provenance note or URL. */
|
|
97
|
+
source: zod.z.string().optional()
|
|
98
|
+
});
|
|
99
|
+
var swaralipiSchema = zod.z.object({
|
|
100
|
+
/** Spec version this document targets (see SPEC_VERSION in ./index). */
|
|
101
|
+
version: zod.z.string(),
|
|
102
|
+
meta: metaSchema,
|
|
103
|
+
parts: zod.z.array(partSchema)
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// src/spec/taals.ts
|
|
107
|
+
var TAALS = {
|
|
108
|
+
dadra: { id: "dadra", numBeats: 6, bhaags: [3, 3], sam: 0, khaali: [3] },
|
|
109
|
+
kehrwa: { id: "kehrwa", numBeats: 8, bhaags: [4, 4], sam: 0, khaali: [4] },
|
|
110
|
+
rupak: { id: "rupak", numBeats: 7, bhaags: [3, 2, 2], sam: 0, khaali: [0] },
|
|
111
|
+
jhaptaal: { id: "jhaptaal", numBeats: 10, bhaags: [2, 3, 2, 3], sam: 0, khaali: [5] },
|
|
112
|
+
ektaal: { id: "ektaal", numBeats: 12, bhaags: [2, 2, 2, 2, 2, 2], sam: 0, khaali: [2, 6] },
|
|
113
|
+
adachautaal: { id: "adachautaal", numBeats: 14, sam: 0 },
|
|
114
|
+
teentaal: { id: "teentaal", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] }
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/spec/index.ts
|
|
118
|
+
var SPEC_VERSION = "0.1.0";
|
|
119
|
+
function parseSwaralipi(data) {
|
|
120
|
+
return swaralipiSchema.parse(data);
|
|
121
|
+
}
|
|
122
|
+
function safeParseSwaralipi(data) {
|
|
123
|
+
return swaralipiSchema.safeParse(data);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
exports.SPEC_VERSION = SPEC_VERSION;
|
|
127
|
+
exports.TAALS = TAALS;
|
|
128
|
+
exports.barSchema = barSchema;
|
|
129
|
+
exports.bracketSchema = bracketSchema;
|
|
130
|
+
exports.metaSchema = metaSchema;
|
|
131
|
+
exports.microtoneSchema = microtoneSchema;
|
|
132
|
+
exports.noteSchema = noteSchema;
|
|
133
|
+
exports.octaveSchema = octaveSchema;
|
|
134
|
+
exports.parseSwaralipi = parseSwaralipi;
|
|
135
|
+
exports.partSchema = partSchema;
|
|
136
|
+
exports.rowSchema = rowSchema;
|
|
137
|
+
exports.safeParseSwaralipi = safeParseSwaralipi;
|
|
138
|
+
exports.svaraLetterSchema = svaraLetterSchema;
|
|
139
|
+
exports.svaraSchema = svaraSchema;
|
|
140
|
+
exports.swaralipiSchema = swaralipiSchema;
|
|
141
|
+
exports.taalSchema = taalSchema;
|
|
142
|
+
//# sourceMappingURL=index.cjs.map
|
|
143
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/spec/schema.ts","../src/spec/taals.ts","../src/spec/index.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\n\n/**\n * swaralipi-js JSON spec — Zod schema + inferred types.\n\n/** Octave registers */\nexport const octaveSchema = z.enum([\n 'ati-mandra', // very low\n 'mandra', // low (dot below)\n 'madhyam', // middle\n 'taar', // high (ref/dot above)\n 'ati-taar', // very high\n]);\nexport type Octave = z.infer<typeof octaveSchema>;\n\n/**\n * The seven shuddha svara letters:\n * `d` = ধৈবত (dha), `n` = নিষাদ (ni). Komal/tivra are flags, not letters.\n */\nexport const svaraLetterSchema = z.enum(['s', 'r', 'g', 'm', 'p', 'd', 'n']);\nexport type SvaraLetter = z.infer<typeof svaraLetterSchema>;\n\n/** A pitch as `[octave, letter]` */\nexport const svaraSchema = z.tuple([octaveSchema, svaraLetterSchema]);\nexport type Svara = z.infer<typeof svaraSchema>;\n\n/** Microtone variants below komal (legend: অল্পকোমল / অতিকোমল). */\nexport const microtoneSchema = z.enum(['alpakomal', 'atikomal']);\nexport type Microtone = z.infer<typeof microtoneSchema>;\n\n/**\n * Barline weights. Swarabitan distinguishes the light দাঁড়ি (।) that\n * separates vibhags *within* a taal cycle from the দণ্ড (danda, I) strokes:\n * - `dari` — । vibhag separator inside the cycle\n * - `single` — I end of one taal cycle (ফেরা)\n * - `double` — II section (kali) boundary / return-to-asthayi marker\n * - `quad` — IIII end of the song\n */\nexport const barSchema = z.enum(['dari', 'single', 'double', 'quad']);\nexport type Bar = z.infer<typeof barSchema>;\n\n/**\n * A repeat-bracket edge. Brackets span a range of notes; the opening note\n * carries `{ ..., edge: 'open' }` and the closing note `{ ..., edge: 'close' }`.\n * kind: `repeat` = {} গুন্ডবন্ধনী, `skip` = () বক্রবন্ধনী (omit on repeat),\n * `alt` = [] সরল বন্ধনী (changed notes on repeat).\n */\nexport const bracketSchema = z.object({\n kind: z.enum(['repeat', 'skip', 'alt']),\n edge: z.enum(['open', 'close']),\n});\nexport type Bracket = z.infer<typeof bracketSchema>;\n\n/**\n * A single token in a row. A token is one of: a pitched note (`svara`),\n * a rest (`rest`), an আ-কার sustain (`sustain`), a barline (`bar`), or a\n * purely raw/undecoded cell (`raw`) — possibly carrying annotations\n * (`above`/`below`) or a lyric syllable on an otherwise empty column.\n * The `.refine` enforces that a note carries at least one of these so\n * truly empty tokens can't slip through.\n *\n * `above`/`below` make `Note` recursive, so the type is hand-written and\n * the schema is typed `z.ZodType<Note>` via `z.lazy` (all fields are\n * optional, hence input ≡ output and the annotation is sound).\n */\nexport interface Note {\n /** Pitch. Omitted for rests, sustains, and barlines. */\n svara?: Svara;\n /** কোমল (flat). */\n komal?: boolean;\n /** তীব্র / কড়ি (sharp — applies to ma). */\n tivra?: boolean;\n /** Sub-komal microtone (legend: অল্পকোমল / অতিকোমল). */\n microtone?: Microtone;\n /** Duration in মাত্রা (beats): 1 (default), 0.5, 0.25, 2, … */\n durationMatra?: number;\n /**\n * আ-কার: no new syllable attack. Alone (no `svara`) it holds the previous\n * note's pitch and vowel; combined with `svara` it is a melisma — the\n * pitch moves while the previous syllable's vowel continues (Swarabitan\n * writes these with a leading hyphen, e.g. `-sfa`).\n */\n sustain?: boolean;\n /** বিরাম: a rest of `durationMatra` beats. */\n rest?: boolean;\n /** কণ স্বর: a grace note attached before this note. */\n kan?: Svara;\n /** মীড় (glide/slur) endpoint. */\n meend?: 'start' | 'end';\n /** Barline. A bar token usually has no `svara`. */\n bar?: Bar;\n /** Repeat-bracket edges opening/closing on this token. */\n brackets?: Bracket[];\n /** Lyric syllable aligned under this note */\n lyric?: string;\n /** Lossless passthrough of the source cell (e.g. raw Swarabitan code). */\n raw?: string;\n /**\n * Annotation notes rendered above this column: alt-on-repeat passages\n * (legend: পরিবর্তিত স্বর in [ ] শিরোদেশে), stop marks, beat numbers.\n */\n above?: Note[];\n /** Annotation notes rendered below this column. */\n below?: Note[];\n}\n\nexport const noteSchema: z.ZodType<Note> = z.lazy(() =>\n z\n .object({\n svara: svaraSchema.optional(),\n komal: z.boolean().optional(),\n tivra: z.boolean().optional(),\n microtone: microtoneSchema.optional(),\n durationMatra: z.number().positive().optional(),\n sustain: z.boolean().optional(),\n rest: z.boolean().optional(),\n kan: svaraSchema.optional(),\n meend: z.enum(['start', 'end']).optional(),\n bar: barSchema.optional(),\n brackets: z.array(bracketSchema).optional(),\n lyric: z.string().optional(),\n raw: z.string().optional(),\n above: z.array(noteSchema).optional(),\n below: z.array(noteSchema).optional(),\n })\n .refine(\n (n) =>\n n.svara !== undefined ||\n n.rest === true ||\n n.sustain === true ||\n n.bar !== undefined ||\n n.raw !== undefined ||\n (n.brackets !== undefined && n.brackets.length > 0) ||\n (n.above !== undefined && n.above.length > 0) ||\n (n.below !== undefined && n.below.length > 0) ||\n n.lyric !== undefined,\n {\n message:\n 'note must carry one of: svara, rest, sustain, bar, raw, lyric, brackets, or a non-empty above/below',\n },\n ),\n);\n\n/** A written line of the song: a sequence of note tokens. */\nexport const rowSchema = z.object({\n /** Optional line label (e.g. a tuk/section marker). */\n label: z.string().optional(),\n notes: z.array(noteSchema),\n});\nexport type Row = z.infer<typeof rowSchema>;\n\n/** A structural section: আস্থায়ী / অন্তরা / সঞ্চারী / আভোগ, or free text. */\nexport const partSchema = z.object({\n name: z.string().optional(),\n rows: z.array(rowSchema),\n});\nexport type Part = z.infer<typeof partSchema>;\n\n/**\n * Taal definition. `numBeats` is the cycle length in মাত্রা; `bhaags` (if\n * present) must sum to `numBeats`; `sam`/`khaali` are 0-based beat indices.\n */\nexport const taalSchema = z\n .object({\n /** Player sample key, e.g. `dadra`, `teentaal`. */\n id: z.string(),\n numBeats: z.number().int().positive(),\n /** Vibhag groupings; if given, they sum to numBeats. */\n bhaags: z.array(z.number().int().positive()).optional(),\n /** Sam (cycle start) beat index, 0-based. */\n sam: z.number().int().nonnegative().optional(),\n /** Khaali (wave) beat indices, 0-based. */\n khaali: z.array(z.number().int().nonnegative()).optional(),\n })\n .refine((t) => t.bhaags === undefined || t.bhaags.reduce((a, b) => a + b, 0) === t.numBeats, {\n message: 'bhaags must sum to numBeats',\n });\nexport type Taal = z.infer<typeof taalSchema>;\n\n/** Document-level metadata. */\nexport const metaSchema = z.object({\n title: z.string(),\n /** Cross-reference to a gitabitan.io song content id (filename, immutable). */\n songId: z.string().optional(),\n /** Source NLTR node/song id. */\n nltrId: z.number().int().optional(),\n taal: taalSchema.optional(),\n /**\n * The taal name exactly as printed in the source (e.g. `তালমুক্ত`,\n * `ষষ্ঠী(২/৪)`). Always set by the NLTR converter; `taal` is set only\n * when the name resolves to a known definition.\n */\n taalName: z.string().optional(),\n /** Base pitch for playback, e.g. `C`, `C#`, or the player's `cs` form. */\n tonic: z.string().optional(),\n /** Default playback tempo in matra/min. Player-only — the viewer ignores it.\n * The player adopts it on `load()` (precedence: constructor `bpm` → `setBpm`\n * tweak → this → 90). `null` is the converter's blank placeholder = unset. */\n bpm: z.number().positive().nullable().optional(),\n raag: z.string().optional(),\n /** আবর্তন: number of taal cycles, when the source states it. */\n avartan: z.number().int().positive().optional(),\n /** স্বরলিপিকার (notation author). */\n notationBy: z.string().optional(),\n /** Provenance note or URL. */\n source: z.string().optional(),\n});\nexport type Meta = z.infer<typeof metaSchema>;\n\n/** A complete swaralipi document. */\nexport const swaralipiSchema = z.object({\n /** Spec version this document targets (see SPEC_VERSION in ./index). */\n version: z.string(),\n meta: metaSchema,\n parts: z.array(partSchema),\n});\nexport type Swaralipi = z.infer<typeof swaralipiSchema>;\n","import type { Taal } from './schema.js';\n\n/**\n * Reference definitions for the taals the player will sample (P2.3):\n * adachautaal, dadra, ektaal, jhaptaal, kehrwa, rupak, teentaal.\n *\n * `numBeats` and the `bhaags` given below are standard Hindustani taal theory.\n * `bhaags` is omitted where a single canonical division isn't well-agreed\n * (adachautaal) — we assert only what's uncontested. `sam` is beat 0 for all.\n */\nexport const TAALS = {\n dadra: { id: 'dadra', numBeats: 6, bhaags: [3, 3], sam: 0, khaali: [3] },\n kehrwa: { id: 'kehrwa', numBeats: 8, bhaags: [4, 4], sam: 0, khaali: [4] },\n rupak: { id: 'rupak', numBeats: 7, bhaags: [3, 2, 2], sam: 0, khaali: [0] },\n jhaptaal: { id: 'jhaptaal', numBeats: 10, bhaags: [2, 3, 2, 3], sam: 0, khaali: [5] },\n ektaal: { id: 'ektaal', numBeats: 12, bhaags: [2, 2, 2, 2, 2, 2], sam: 0, khaali: [2, 6] },\n adachautaal: { id: 'adachautaal', numBeats: 14, sam: 0 },\n teentaal: { id: 'teentaal', numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] },\n} as const satisfies Record<string, Taal>;\n\nexport type TaalId = keyof typeof TAALS;\n","/**\n * @ugfoundation/swaralipi-js/spec\n *\n * The swaralipi JSON spec: Zod schemas, inferred TS types, and parse helpers.\n */\nimport { swaralipiSchema, type Swaralipi } from './schema.js';\n\n/** Current spec version. Documents declare the version they target. */\nexport const SPEC_VERSION = '0.1.0';\n\nexport {\n octaveSchema,\n svaraLetterSchema,\n svaraSchema,\n microtoneSchema,\n barSchema,\n bracketSchema,\n noteSchema,\n rowSchema,\n partSchema,\n taalSchema,\n metaSchema,\n swaralipiSchema,\n} from './schema.js';\n\nexport type {\n Octave,\n SvaraLetter,\n Svara,\n Microtone,\n Bar,\n Bracket,\n Note,\n Row,\n Part,\n Taal,\n Meta,\n Swaralipi,\n} from './schema.js';\n\nexport { TAALS, type TaalId } from './taals.js';\n\n/** Parse + validate unknown data into a `Swaralipi`. Throws `ZodError` on failure. */\nexport function parseSwaralipi(data: unknown): Swaralipi {\n return swaralipiSchema.parse(data);\n}\n\n/** Non-throwing variant: returns Zod's `{ success, data | error }` result. */\nexport function safeParseSwaralipi(data: unknown) {\n return swaralipiSchema.safeParse(data);\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { SPEC_VERSION, parseSwaralipi, safeParseSwaralipi } from './spec/index.cjs';
|
|
2
|
+
export { B as Bar, b as Bracket, M as Meta, c as Microtone, N as Note, O as Octave, P as Part, R as Row, d as Svara, a as SvaraLetter, S as Swaralipi, T as Taal, e as barSchema, f as bracketSchema, m as metaSchema, g as microtoneSchema, n as noteSchema, o as octaveSchema, p as partSchema, r as rowSchema, s as svaraLetterSchema, h as svaraSchema, i as swaralipiSchema, t as taalSchema } from './schema-gxhG45OK.cjs';
|
|
3
|
+
export { a as TAALS, T as TaalId } from './taals-DguYW0wf.cjs';
|
|
4
|
+
import 'zod';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { SPEC_VERSION, parseSwaralipi, safeParseSwaralipi } from './spec/index.js';
|
|
2
|
+
export { B as Bar, b as Bracket, M as Meta, c as Microtone, N as Note, O as Octave, P as Part, R as Row, d as Svara, a as SvaraLetter, S as Swaralipi, T as Taal, e as barSchema, f as bracketSchema, m as metaSchema, g as microtoneSchema, n as noteSchema, o as octaveSchema, p as partSchema, r as rowSchema, s as svaraLetterSchema, h as svaraSchema, i as swaralipiSchema, t as taalSchema } from './schema-gxhG45OK.js';
|
|
3
|
+
export { a as TAALS, T as TaalId } from './taals-DguYW0wf.js';
|
|
4
|
+
import 'zod';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { SPEC_VERSION, barSchema, bracketSchema, metaSchema, microtoneSchema, noteSchema, octaveSchema, parseSwaralipi, partSchema, rowSchema, safeParseSwaralipi, svaraLetterSchema, svaraSchema, swaralipiSchema, taalSchema } from './chunk-C6O7DYU5.js';
|
|
2
|
+
export { TAALS } from './chunk-GWXI2HJA.js';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|