@ugfoundation/swaralipi-js 0.12.0 → 0.13.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.
Files changed (43) hide show
  1. package/README.md +7 -1
  2. package/dist/{batch-ZNVWIGEL.js → batch-XVQRHLTN.js} +5 -4
  3. package/dist/batch-XVQRHLTN.js.map +1 -0
  4. package/dist/chunk-BSZ3WQUP.js +164 -0
  5. package/dist/chunk-BSZ3WQUP.js.map +1 -0
  6. package/dist/{chunk-A7R3VFIV.js → chunk-GKS4WZZ6.js} +3 -3
  7. package/dist/{chunk-A7R3VFIV.js.map → chunk-GKS4WZZ6.js.map} +1 -1
  8. package/dist/{chunk-A6Z7X2LX.js → chunk-L6YZ3GC6.js} +227 -63
  9. package/dist/chunk-L6YZ3GC6.js.map +1 -0
  10. package/dist/{chunk-ISNAL632.js → chunk-MORX7G6E.js} +5 -165
  11. package/dist/chunk-MORX7G6E.js.map +1 -0
  12. package/dist/cli.cjs +1 -1
  13. package/dist/cli.cjs.map +1 -1
  14. package/dist/cli.js +2 -2
  15. package/dist/convert/index.cjs +1 -1
  16. package/dist/convert/index.cjs.map +1 -1
  17. package/dist/convert/index.js +3 -2
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/player/index.cjs +470 -122
  22. package/dist/player/index.cjs.map +1 -1
  23. package/dist/player/index.d.cts +12 -2
  24. package/dist/player/index.d.ts +12 -2
  25. package/dist/player/index.js +85 -60
  26. package/dist/player/index.js.map +1 -1
  27. package/dist/{schedule-DN-8X17d.d.ts → schedule-ClyON98C.d.ts} +22 -10
  28. package/dist/{schedule-CRpjr6JH.d.cts → schedule-V-fgepvP.d.cts} +22 -10
  29. package/dist/spec/index.cjs +1 -1
  30. package/dist/spec/index.cjs.map +1 -1
  31. package/dist/spec/index.d.cts +1 -1
  32. package/dist/spec/index.d.ts +1 -1
  33. package/dist/spec/index.js +1 -1
  34. package/dist/viewer/index.cjs +366 -61
  35. package/dist/viewer/index.cjs.map +1 -1
  36. package/dist/viewer/index.d.cts +1 -1
  37. package/dist/viewer/index.d.ts +1 -1
  38. package/dist/viewer/index.js +2 -1
  39. package/dist/viewer/index.js.map +1 -1
  40. package/package.json +1 -1
  41. package/dist/batch-ZNVWIGEL.js.map +0 -1
  42. package/dist/chunk-A6Z7X2LX.js.map +0 -1
  43. package/dist/chunk-ISNAL632.js.map +0 -1
@@ -1,167 +1,7 @@
1
- import { swaralipiSchema, SPEC_VERSION } from './chunk-A7R3VFIV.js';
1
+ import { swaralipiSchema, SPEC_VERSION } from './chunk-GKS4WZZ6.js';
2
+ import { decodeCell } from './chunk-BSZ3WQUP.js';
2
3
  import { isTaalFerta, TAAL_FERTA, TAALS } from './chunk-KOHSKHXI.js';
3
4
 
4
- // src/convert/codec.ts
5
- var LETTERS = {
6
- s: { letter: "s" },
7
- r: { letter: "r" },
8
- g: { letter: "g" },
9
- m: { letter: "m" },
10
- p: { letter: "p" },
11
- q: { letter: "d" },
12
- // ধ — shuddha dha
13
- n: { letter: "n" },
14
- d: { letter: "d", komal: true },
15
- // দ
16
- t: { letter: "g", komal: true },
17
- // জ্ঞ
18
- k: { letter: "m", tivra: true },
19
- // ক্ষ
20
- u: { letter: "n", komal: true },
21
- // ণ
22
- v: { letter: "r", komal: true }
23
- // ঋ
24
- };
25
- var STRUCTURALS = {
26
- "%": () => ({ svara: ["madhyam", "s"] }),
27
- // precomposed সা
28
- "&": () => ({ svara: ["madhyam", "n"] })
29
- // precomposed নি
30
- };
31
- var BAR_RUN_RE = /^(-)?([lLA[\]]+)$/;
32
- function decodeBarRun(body) {
33
- const m = body.match(BAR_RUN_RE);
34
- if (!m || !/[lLA]/.test(m[2])) return void 0;
35
- const notes = [];
36
- if (m[1]) notes.push({ sustain: true });
37
- const run = m[2];
38
- let i = 0;
39
- while (i < run.length) {
40
- const ch = run[i];
41
- if (ch === "l" || ch === "L") {
42
- let j = i;
43
- while (j < run.length && run[j] === ch) j++;
44
- const strokes = (j - i) * (ch === "L" ? 2 : 1);
45
- notes.push({ bar: strokes >= 4 ? "quad" : strokes >= 2 ? "double" : "single" });
46
- i = j;
47
- } else if (ch === "A") {
48
- notes.push({ bar: "dari" });
49
- i++;
50
- } else {
51
- notes.push({ brackets: [{ kind: "alt", edge: ch === "[" ? "open" : "close" }] });
52
- i++;
53
- }
54
- }
55
- return notes;
56
- }
57
- var KNOWN_RAW_RE = [
58
- /^[wxyjEJ$<>=_]+$/,
59
- // arc & line drawing segments
60
- /^\|+$/,
61
- // thin yugal-dari stop mark
62
- /^[0-9!@#]{1,2}[fF]?:?$/,
63
- // beat-number labels incl. 10–16 (sam tick = f/F, e.g. 1f / 1F / 2:)
64
- /^[oOe`+,.;:iI~^*bcBCWXYFHZz'"?]$/
65
- // dots, ticks, duration marks, legacy forms
66
- ];
67
- var OPEN_BRACKETS = {
68
- "{": "repeat",
69
- "(": "skip",
70
- "[": "alt"
71
- };
72
- var CLOSE_BRACKETS = {
73
- "}": "repeat",
74
- ")": "skip",
75
- "]": "alt"
76
- };
77
- function octaveOf(mark) {
78
- if (mark === "f" || mark === "F") return "taar";
79
- if (mark === "h" || mark === "H") return "mandra";
80
- return "madhyam";
81
- }
82
- var BODY_RE = /^([0-9!@][fF]?)?([zj]*)(-)?([i:])?(?:([SRGMPQNDTKUV])([fFhH])?)?((?:[srgmpqndtkuv][fh]?[i:]?)+)?(a)?([fh])?([i:])?(?:([SRGMPQNDTKUV])([fFhH])?)?([0-9!@][fF]?)?(-)?$/;
83
- function decodeChunk(chunk) {
84
- const opens = [];
85
- const closes = [];
86
- let body = chunk;
87
- while (body.length > 0) {
88
- const kind = OPEN_BRACKETS[body[0]];
89
- if (kind === void 0) break;
90
- opens.push(kind);
91
- body = body.slice(1);
92
- }
93
- while (body.length > 0) {
94
- const kind = CLOSE_BRACKETS[body[body.length - 1]];
95
- if (kind === void 0) break;
96
- closes.unshift(kind);
97
- body = body.slice(0, -1);
98
- }
99
- const finish = (notes, kind) => {
100
- if (notes.length === 0) notes.push({});
101
- const first = notes[0];
102
- const last = notes[notes.length - 1];
103
- if (opens.length > 0) first.brackets = [...opens.map((kind_) => ({ kind: kind_, edge: "open" })), ...first.brackets ?? []];
104
- if (closes.length > 0) last.brackets = [...last.brackets ?? [], ...closes.map((kind_) => ({ kind: kind_, edge: "close" }))];
105
- return { notes, kind };
106
- };
107
- if (body === "") return finish([{}], "decoded");
108
- const barRun = decodeBarRun(body);
109
- if (barRun) return finish(barRun, "decoded");
110
- const structural = STRUCTURALS[body];
111
- if (structural) return finish([structural()], "decoded");
112
- if (KNOWN_RAW_RE.some((re) => re.test(body))) return finish([{}], "known");
113
- const m = body.match(BODY_RE);
114
- if (m) {
115
- const [, , , hyphen, , kanLetter, kanOct, unitsStr, aakar, postOct, , trailKan, trailKanOct] = m;
116
- const attachKan = (note, letter, oct) => {
117
- const def = LETTERS[letter.toLowerCase()];
118
- note.kan = [octaveOf(oct?.toLowerCase()), def.letter];
119
- };
120
- if (unitsStr) {
121
- const units = unitsStr.match(/[srgmpqndtkuv][fh]?/g) ?? [];
122
- const notes = units.map((unit) => {
123
- const def = LETTERS[unit[0]];
124
- const note = { svara: [octaveOf(unit[1]), def.letter] };
125
- if (def.komal) note.komal = true;
126
- if (def.tivra) note.tivra = true;
127
- if (units.length > 1) note.durationMatra = 1 / units.length;
128
- return note;
129
- });
130
- const last = notes[notes.length - 1];
131
- if (postOct && last.svara[0] === "madhyam") {
132
- last.svara = [octaveOf(postOct), last.svara[1]];
133
- }
134
- if (hyphen) notes[0].sustain = true;
135
- if (kanLetter) attachKan(notes[0], kanLetter, kanOct);
136
- if (trailKan && last.kan === void 0) attachKan(last, trailKan, trailKanOct);
137
- return finish(notes, "decoded");
138
- }
139
- if (aakar) {
140
- const note = hyphen ? { sustain: true } : { rest: true };
141
- if (trailKan) attachKan(note, trailKan, trailKanOct);
142
- else if (kanLetter) attachKan(note, kanLetter, kanOct);
143
- return finish([note], "decoded");
144
- }
145
- if (hyphen && !kanLetter && !trailKan) {
146
- return finish([{ sustain: true }], "decoded");
147
- }
148
- }
149
- return finish([{}], "unknown");
150
- }
151
- function decodeCell(text) {
152
- const chunks = text.split(/\s+/).filter((c) => c.length > 0);
153
- const out = { notes: [], unknownTokens: [], knownRawTokens: [], decoded: false };
154
- for (const chunk of chunks) {
155
- const { notes, kind } = decodeChunk(chunk);
156
- notes[0].raw = chunk;
157
- if (kind === "decoded") out.decoded = true;
158
- else if (kind === "known") out.knownRawTokens.push(chunk);
159
- else out.unknownTokens.push(chunk);
160
- out.notes.push(...notes);
161
- }
162
- return out;
163
- }
164
-
165
5
  // src/convert/grid.ts
166
6
  var ROLES = ["above", "notation", "below", "lyric"];
167
7
  function buildSystems(page) {
@@ -590,6 +430,6 @@ function convertNltrHtml(html, opts = {}) {
590
430
  return assemble(extractPage(html), opts);
591
431
  }
592
432
 
593
- export { ExtractError, aggregate, assemble, bnInt, buildSystems, convertNltrHtml, decodeCell, deriveGeometry, extractPage, formatSummary, resolveTaal, splitLyric };
594
- //# sourceMappingURL=chunk-ISNAL632.js.map
595
- //# sourceMappingURL=chunk-ISNAL632.js.map
433
+ export { ExtractError, aggregate, assemble, bnInt, buildSystems, convertNltrHtml, deriveGeometry, extractPage, formatSummary, resolveTaal, splitLyric };
434
+ //# sourceMappingURL=chunk-MORX7G6E.js.map
435
+ //# sourceMappingURL=chunk-MORX7G6E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/convert/grid.ts","../src/convert/taal-map.ts","../src/convert/assemble.ts","../src/convert/extract.ts","../src/convert/report.ts","../src/convert/index.ts"],"names":[],"mappings":"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","file":"chunk-MORX7G6E.js","sourcesContent":["/**\n * Grid → systems.\n *\n * Rows group into 4-row \"systems\", role given by `row % 4` (verified with\n * zero exceptions across the whole corpus):\n * 0 → annotation row rendered ABOVE the staff (alt-on-repeat passages,\n * stop marks, beat numbers — sparse),\n * 1 → notation row (style1, Swarabitan codes),\n * 2 → annotation row rendered BELOW the staff (sparse),\n * 3 → lyric row (style2, Bengali).\n * Cells align across the four rows strictly by column id (rows can be\n * ragged, so never align by index).\n */\nimport type { NltrPage } from './extract.js';\n\nexport interface System {\n /** System index (source rows 4k..4k+3). */\n index: number;\n above: Map<number, string>;\n notation: Map<number, string>;\n below: Map<number, string>;\n lyric: Map<number, string>;\n maxCol: number;\n}\n\nconst ROLES = ['above', 'notation', 'below', 'lyric'] as const;\n\nexport function buildSystems(page: NltrPage): { systems: System[]; warnings: string[] } {\n const warnings: string[] = [];\n const byIndex = new Map<number, System>();\n let styleMismatches = 0;\n\n for (const cell of page.cells) {\n if (cell.text === '') continue;\n const role = ROLES[cell.row % 4]!;\n // Notation/annotation rows are style1, lyric rows style2 — corpus-wide\n // invariant. A mismatch is recorded but the row role (from row % 4) wins.\n const expected = role === 'lyric' ? 'style2' : 'style1';\n if (cell.style !== expected) styleMismatches++;\n\n const index = Math.floor(cell.row / 4);\n let system = byIndex.get(index);\n if (!system) {\n system = {\n index,\n above: new Map(),\n notation: new Map(),\n below: new Map(),\n lyric: new Map(),\n maxCol: 0,\n };\n byIndex.set(index, system);\n }\n system[role].set(cell.col, cell.text);\n if (cell.col > system.maxCol) system.maxCol = cell.col;\n }\n\n if (styleMismatches > 0) {\n warnings.push(`${styleMismatches} cell(s) had an unexpected style class for their row role`);\n }\n\n // Keep source order; drop systems with no content at all (trailing blank\n // systems are common).\n const systems = [...byIndex.values()].sort((a, b) => a.index - b.index);\n return { systems, warnings };\n}\n","/**\n * Resolve the printed Bengali তাল name (+ the grid's own geometry) into a\n * spec `Taal`.\n *\n * Evidence chain, strongest first:\n * 1. bhaag hints in the name itself — `ধামার(৩/২/২/৩/৪)` → [3,2,2,3,4];\n * 2. the name table below (the 7 player-sampled taals from TAALS, plus\n * well-attested Rabindrik taals with stable definitions);\n * 3. the grid geometry: bar/dari columns partition each cycle into bhaags\n * (`numCols = avartan × (numBeats + nDaris) + 1` held on every checked\n * song), which both derives unknown taals and cross-checks named ones.\n * তালমুক্ত/মুক্তছন্দ (free rhythm) and unresolvable names yield no `taal`; the\n * name lands in `meta.taalName` verbatim, except free rhythm which is\n * normalised to মুক্তছন্দ.\n */\nimport { isTaalFerta, TAAL_FERTA, TAALS, type Taal } from '../spec/index.js';\nimport type { System } from './grid.js';\n\nconst BN_DIGIT_MAP: Record<string, string> = {\n '০': '0',\n '১': '1',\n '২': '2',\n '৩': '3',\n '৪': '4',\n '৫': '5',\n '৬': '6',\n '৭': '7',\n '৮': '8',\n '৯': '9',\n};\n\n/** Parse an integer written with Bengali or ASCII digits. */\nexport function bnInt(s: string | undefined): number | undefined {\n if (s === undefined) return undefined;\n const ascii = s.trim().replace(/[০-৯]/g, (d) => BN_DIGIT_MAP[d] ?? d);\n return /^\\d+$/.test(ascii) ? Number(ascii) : undefined;\n}\n\n/** Names mapping straight onto player-sampled TAALS ids. */\nconst BN_TAAL_MAP: Record<string, keyof typeof TAALS> = {\n দাদরা: 'dadra',\n কাহারবা: 'kehrwa',\n একতালা: 'ektaal',\n একতাল: 'ektaal',\n তিনতালা: 'teentaal',\n ত্রিতাল: 'teentaal',\n ঝাঁপতাল: 'jhaptaal',\n ঝাঁপ: 'jhaptaal',\n রুপক: 'rupak',\n রূপক: 'rupak',\n আড়াচৌতাল: 'adachautaal',\n ঝম্পক: 'jhampak',\n রুপকড়া: 'rupakra',\n রূপকড়া: 'rupakra',\n খেমটা: 'khemta',\n};\n\n/** Long-tail taals with stable textbook definitions (ids transliterated). */\nconst BN_TAAL_DEFS: Record<string, Taal> = {\n তেওড়া: { id: 'teora', numBeats: 7, bhaags: [3, 2, 2], sam: 0 },\n তেওরা: { id: 'teora', numBeats: 7, bhaags: [3, 2, 2], sam: 0 },\n ষষ্ঠী: { id: 'shashthi', numBeats: 6, bhaags: [2, 4], sam: 0 },\n নবতাল: { id: 'nabataal', numBeats: 9, bhaags: [5, 4], sam: 0 },\n একাদশী: { id: 'ekadashi', numBeats: 11, bhaags: [3, 4, 4], sam: 0 },\n নবপঞ্চ: { id: 'nabapancha', numBeats: 18, bhaags: [2, 4, 4, 4, 4], sam: 0 },\n ধামার: { id: 'dhamar', numBeats: 14, bhaags: [3, 2, 2, 3, 4], sam: 0 },\n চৌতাল: { id: 'choutaal', numBeats: 12, bhaags: [2, 2, 2, 2, 2, 2], sam: 0 },\n সুরফাঁক: { id: 'surphank', numBeats: 10, sam: 0 },\n};\n\n/**\n * Readable ids for the remaining census names whose beat count varies by\n * song (or isn't well-attested) — numBeats comes from hints/geometry only.\n */\nconst BN_TAAL_IDS: Record<string, string> = {\n কাওয়ালি: 'kawali',\n আড়াঠেকা: 'araatheka',\n কাশ্মীরি: 'kashmiri',\n যৎ: 'yat',\n মধ্যমান: 'madhyaman',\n অর্দ্ধঝাঁপ: 'ardhajhanp',\n অর্ধঝাঁপ: 'ardhajhanp',\n 'বিলম্বিত ত্রিতাল': 'vilambit-teentaal',\n};\n\n/**\n * Free-rhythm markers — never resolve to a taal. The sources print তালমুক্ত;\n * the emitted `taalName` is normalised to the canonical মুক্তছন্দ.\n */\nconst TAAL_FREE = ['তালমুক্ত', 'মুক্তছন্দ'];\nconst TAAL_FREE_CANON = 'মুক্তছন্দ';\n\nexport interface GridGeometry {\n /** Total columns of the widest full notation row. */\n numCols: number;\n /** Matra count of one cycle (notes between cycle bars, daris excluded). */\n numBeats?: number;\n /** Bhaag division of one cycle, from dari positions. */\n bhaags?: number[];\n}\n\n/** Bar-class tokens (cycle/section dandas) and the vibhag dari. */\nconst BAR_TOKENS = new Set(['l', 'll', 'lll', 'llll', 'L', 'LL', '|']);\nconst DARI_TOKEN = 'A';\n\n/**\n * Derive cycle geometry from the first notation row shaped `bar … bar`.\n * Returns per-cycle numBeats/bhaags when at least one full cycle is visible.\n */\nexport function deriveGeometry(systems: System[]): GridGeometry | undefined {\n let numCols = 0;\n for (const system of systems) {\n if (system.notation.size === 0) continue;\n const cols = [...system.notation.keys()].sort((a, b) => a - b);\n numCols = Math.max(numCols, cols.length);\n const barCols = cols.filter((c) => BAR_TOKENS.has(system.notation.get(c)!));\n if (barCols.length < 2) continue;\n // First full cycle: between the first two bar columns.\n const from = barCols[0]!;\n const to = barCols[1]!;\n const inner = cols.filter((c) => c > from && c < to);\n if (inner.length === 0) continue;\n const bhaags: number[] = [];\n let run = 0;\n for (const c of inner) {\n if (system.notation.get(c) === DARI_TOKEN) {\n if (run > 0) bhaags.push(run);\n run = 0;\n } else {\n run++;\n }\n }\n if (run > 0) bhaags.push(run);\n const numBeats = bhaags.reduce((a, b) => a + b, 0);\n if (numBeats === 0) continue;\n return { numCols: cols.length, numBeats, bhaags: bhaags.length > 1 ? bhaags : undefined };\n }\n return numCols > 0 ? { numCols } : undefined;\n}\n\nexport interface ResolvedTaal {\n taal?: Taal;\n taalName?: string;\n avartan?: number;\n /** Which evidence resolved the taal. */\n matched: 'taals' | 'table' | 'geometry' | 'none';\n warnings: string[];\n}\n\nexport function resolveTaal(\n nameRaw: string | undefined,\n avartanRaw: string | undefined,\n geometry: GridGeometry | undefined,\n): ResolvedTaal {\n const warnings: string[] = [];\n const avartan = bnInt(avartanRaw);\n const taalName = nameRaw?.trim() || undefined;\n\n if (!taalName || TAAL_FREE.includes(taalName)) {\n return { taalName: taalName ? TAAL_FREE_CANON : undefined, avartan, matched: 'none', warnings };\n }\n // তালফেরতা is a heading, not a taal: the song changes taal row by row\n // (`row.taal`), so there is no single one to resolve — and nothing to warn.\n if (isTaalFerta(taalName)) return { taalName: TAAL_FERTA, avartan, matched: 'none', warnings };\n\n // 1. Split `name(৩/২/…)` into base name + bhaag hint.\n const parenMatch = taalName.match(/^(.*?)\\s*\\(([০-৯\\d/\\s]+)\\)\\s*$/);\n const base = (parenMatch ? parenMatch[1]! : taalName).trim();\n let hintBhaags: number[] | undefined;\n if (parenMatch) {\n const parts = parenMatch[2]!.split('/').map((p) => bnInt(p));\n if (parts.every((p): p is number => p !== undefined) && parts.length > 0) {\n hintBhaags = parts;\n }\n }\n // `অখন্ড ৬ মাত্রা` — \"unbroken N matra\".\n const akhandaMatch = base.match(/^অখন্ড\\s+([০-৯\\d]+)\\s*মাত্রা$/);\n\n // 2. Name lookup.\n let taal: Taal | undefined;\n let matched: ResolvedTaal['matched'] = 'none';\n const mappedId = BN_TAAL_MAP[base];\n if (mappedId) {\n taal = { ...TAALS[mappedId] };\n matched = 'taals';\n } else if (BN_TAAL_DEFS[base]) {\n taal = { ...BN_TAAL_DEFS[base] };\n matched = 'table';\n } else if (akhandaMatch) {\n const beats = bnInt(akhandaMatch[1]);\n if (beats) {\n taal = { id: `akhanda-${beats}`, numBeats: beats, sam: 0 };\n matched = 'table';\n }\n }\n\n // 3. Reconcile with the source's own declaration. A parens hint is part\n // of the printed taal name, so it overrides the table; grid geometry is\n // our own derivation and only ever warns against a name-resolved taal.\n const hintBeats = hintBhaags?.reduce((a, b) => a + b, 0);\n if (taal) {\n if (hintBeats !== undefined && hintBeats !== taal.numBeats) {\n warnings.push(\n `taal ${taal.id}: name declares ${hintBeats} beats (${hintBhaags!.join('/')}), table says ${taal.numBeats} — using the name's`,\n );\n taal = { id: taal.id, numBeats: hintBeats, sam: 0 };\n if (hintBhaags!.length > 1) taal.bhaags = hintBhaags;\n } else if (hintBhaags && hintBhaags.length > 1) {\n const tableBhaags = taal.bhaags?.join('/');\n if (tableBhaags && tableBhaags !== hintBhaags.join('/')) {\n warnings.push(\n `taal ${taal.id}: name declares bhaags ${hintBhaags.join('/')}, table says ${tableBhaags} — using the name's`,\n );\n const { khaali: _khaali, ...rest } = taal;\n taal = { ...rest, bhaags: hintBhaags };\n }\n }\n } else if (hintBeats !== undefined || geometry?.numBeats !== undefined) {\n const evidenceBeats = (hintBeats ?? geometry?.numBeats)!;\n const evidenceBhaags = hintBhaags ?? geometry?.bhaags;\n // 4. Unknown name — derive entirely from evidence; keep a readable id\n // (transliteration table, else the Bengali name itself — ids are free-form).\n taal = { id: BN_TAAL_IDS[base] ?? base, numBeats: evidenceBeats, sam: 0 };\n if (evidenceBhaags && evidenceBhaags.length > 1) taal.bhaags = evidenceBhaags;\n matched = 'geometry';\n } else {\n warnings.push(`unresolved taal name: ${taalName}`);\n }\n\n // Geometry cross-check for table-resolved taals.\n if (taal && geometry?.numBeats !== undefined && geometry.numBeats !== taal.numBeats) {\n warnings.push(\n `grid geometry says ${geometry.numBeats} beats per cycle but taal ${taal.id} has ${taal.numBeats}`,\n );\n }\n\n return { taal, taalName, avartan, matched, warnings };\n}\n","/**\n * Assembly: systems → spec document.\n *\n * Each system becomes one `Row`. Within a row, columns are walked in order;\n * a notation cell's decoded notes join the row, with the column-aligned\n * lyric / above / below content attached to the cell's first note. Columns\n * that have lyric or annotation content but no notation emit a carrier note\n * (legal per the spec refine). The whole song is one unnamed part: NLTR\n * prints no section labels, and `ll` cannot be split on safely because it\n * also marks mid-song asthayi returns.\n */\nimport { SPEC_VERSION, swaralipiSchema, type Meta, type Note, type Row, type Swaralipi } from '../spec/index.js';\nimport { decodeCell } from './codec.js';\nimport type { NltrPage } from './extract.js';\nimport { buildSystems } from './grid.js';\nimport { deriveGeometry, resolveTaal } from './taal-map.js';\nimport type { FileReport } from './report.js';\n\nexport interface ConvertOptions {\n /** NLTR song/node id (usually the source filename). */\n nltrId?: number;\n /** Override the provenance URL stored in `meta.source`. */\n source?: string;\n}\n\nexport interface ConvertResult {\n doc: Swaralipi;\n report: FileReport;\n}\n\nconst segmenter = new Intl.Segmenter('bn', { granularity: 'grapheme' });\n\n/** Split a lyric cell into grapheme clusters (ক+া = 1, র+্ = 1, ৹ = 1). */\nexport function splitLyric(text: string): string[] {\n return [...segmenter.segment(text)].map((s) => s.segment);\n}\n\nexport function assemble(page: NltrPage, opts: ConvertOptions = {}): ConvertResult {\n const { systems, warnings } = buildSystems(page);\n const geometry = deriveGeometry(systems);\n const resolved = resolveTaal(page.header.taalNameRaw, page.header.avartanRaw, geometry);\n warnings.push(...resolved.warnings);\n\n const report: FileReport = {\n nltrId: opts.nltrId,\n title: page.header.title ?? '',\n taalName: resolved.taalName,\n taalId: resolved.taal?.id,\n taalMatched: resolved.matched,\n systems: 0,\n notationCells: 0,\n lyricCells: 0,\n annotationCells: 0,\n decodedCells: 0,\n knownRawCells: 0,\n unknownCells: 0,\n unknownTokens: {},\n lyricAlignMismatches: 0,\n warnings,\n };\n const countUnknown = (tokens: string[]) => {\n for (const t of tokens) report.unknownTokens[t] = (report.unknownTokens[t] ?? 0) + 1;\n };\n\n const rows: Row[] = [];\n for (const system of systems) {\n const notes: Note[] = [];\n for (let col = 0; col <= system.maxCol; col++) {\n const notationText = system.notation.get(col);\n const lyricText = system.lyric.get(col);\n const aboveText = system.above.get(col);\n const belowText = system.below.get(col);\n if (\n notationText === undefined &&\n lyricText === undefined &&\n aboveText === undefined &&\n belowText === undefined\n ) {\n continue;\n }\n\n let cellNotes: Note[];\n if (notationText !== undefined) {\n report.notationCells++;\n const decode = decodeCell(notationText);\n countUnknown(decode.unknownTokens);\n if (decode.unknownTokens.length > 0) report.unknownCells++;\n else if (decode.decoded) report.decodedCells++;\n else report.knownRawCells++;\n cellNotes = decode.notes;\n } else {\n cellNotes = [{}]; // carrier for lyric/annotation on an empty column\n }\n\n if (lyricText !== undefined) {\n report.lyricCells++;\n attachLyric(cellNotes, lyricText, report);\n }\n if (aboveText !== undefined) {\n report.annotationCells++;\n const decode = decodeCell(aboveText);\n countUnknown(decode.unknownTokens);\n cellNotes[0]!.above = decode.notes;\n }\n if (belowText !== undefined) {\n report.annotationCells++;\n const decode = decodeCell(belowText);\n countUnknown(decode.unknownTokens);\n cellNotes[0]!.below = decode.notes;\n }\n notes.push(...cellNotes);\n }\n if (notes.length > 0) {\n rows.push({ notes });\n report.systems++;\n }\n }\n\n const meta: Meta = { title: page.header.title ?? `NLTR ${opts.nltrId ?? 'song'}` };\n if (opts.nltrId !== undefined) meta.nltrId = opts.nltrId;\n if (resolved.taal) meta.taal = resolved.taal;\n if (resolved.taalName) meta.taalName = resolved.taalName;\n if (resolved.avartan !== undefined) meta.avartan = resolved.avartan;\n const source =\n opts.source ??\n (opts.nltrId !== undefined\n ? `https://rabindra-rachanabali.nltr.org/node/${opts.nltrId}`\n : page.header.printId !== undefined\n ? `https://rabindra-rachanabali.nltr.org/node/${page.header.printId}`\n : undefined);\n if (source) meta.source = source;\n\n // Validate against the spec before returning — an assembler bug must fail\n // the file, never emit an invalid document.\n const doc = swaralipiSchema.parse({ version: SPEC_VERSION, meta, parts: [{ rows }] });\n return { doc, report };\n}\n\n/**\n * Attach a lyric cell to its notation cell's notes. When the grapheme\n * cluster count matches the cell's note count the sub-syllables map 1:1\n * (e.g. `অ৹` onto the two notes of `nsfa`); otherwise the whole string\n * lands on the first note (never invent splits).\n */\nfunction attachLyric(cellNotes: Note[], lyricText: string, report: FileReport): void {\n if (cellNotes.length > 1) {\n const clusters = splitLyric(lyricText);\n if (clusters.length === cellNotes.length) {\n clusters.forEach((cluster, i) => {\n cellNotes[i]!.lyric = cluster;\n });\n return;\n }\n report.lyricAlignMismatches++;\n }\n cellNotes[0]!.lyric = lyricText;\n}\n","/**\n * NLTR HTML extraction — the lowest layer of the converter.\n *\n * The 1,738 cached NLTR pages are machine-generated and 100% structurally\n * uniform (verified across all 2.79M cells), so extraction is deliberately\n * a strict regex parse with a count assertion rather than a lenient DOM\n * walk: any structural surprise fails the file loudly (`ExtractError`)\n * instead of silently mis-treeing.\n *\n * Page anatomy:\n * - a metadata table of `style3` triples: label (নাম / তাল / আবর্তন), ':',\n * value;\n * - one grid of cells `<td width='auto' id=R.C> <span class='styleN'>\n * <div align='center'>TOKEN</div></span></td>` where `id` is the\n * `row.col` coordinate (often unquoted) and `&nbsp;` marks an empty cell.\n */\n\n/** One grid cell. `text` is entity-decoded and whitespace-normalized ('' = empty). */\nexport interface RawCell {\n row: number;\n col: number;\n /** `style1` = Swarabitan notation, `style2` = Bengali lyric. */\n style: string;\n text: string;\n}\n\n/** The style3 metadata header values, verbatim (Bengali). */\nexport interface NltrHeader {\n title?: string;\n taalNameRaw?: string;\n avartanRaw?: string;\n /** NLTR's internal print node id (`/print/<id>`), for provenance. */\n printId?: number;\n}\n\nexport interface NltrPage {\n header: NltrHeader;\n cells: RawCell[];\n maxRow: number;\n}\n\n/** Structural surprise in the source HTML (not a decode problem). */\nexport class ExtractError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ExtractError';\n }\n}\n\nconst NAMED_ENTITIES: Record<string, string> = {\n nbsp: ' ',\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n};\n\n/** Decode the handful of entities NLTR emits (named + numeric). */\nexport function decodeEntities(s: string): string {\n return s.replace(/&(?:#x([0-9a-fA-F]+)|#(\\d+)|([a-zA-Z]+));/g, (m, hex, dec, name) => {\n if (hex) return String.fromCodePoint(parseInt(hex, 16));\n if (dec) return String.fromCodePoint(parseInt(dec, 10));\n return NAMED_ENTITIES[name] ?? m;\n });\n}\n\n/**\n * Normalize cell text: decode entities, drop format/control characters\n * (U+200E etc. occur in lyric cells), collapse whitespace (incl. NBSP),\n * and canonicalize to NFC (NLTR mixes precomposed/decomposed forms of\n * ড়/ঢ়/য়; NFC settles both on the decomposed form since these are\n * composition exclusions).\n */\nfunction normalizeCellText(s: string): string {\n return decodeEntities(s)\n .replace(/\\p{Cf}/gu, '')\n .replace(/[\\s ]+/gu, ' ')\n .trim()\n .normalize('NFC');\n}\n\n// Cell alignment is center except for arc end-pieces (w/x), which NLTR\n// emits with align='right'/'left' so they visually join the neighbor cell.\nconst CELL_RE =\n /<td width='auto' id=[\"']?(\\d+)\\.(\\d+)[\"']?\\s*>\\s*<span class='(style\\d)'><div align='(?:center|left|right)'>([\\s\\S]*?)<\\/div><\\/span><\\/td>/g;\n\nconst META_ROW_RE =\n /<tr><td><div align='left'><span class='style3'>([^<]*)<\\/span><\\/div><\\/td><td><div align='left'><span class='style3'>:<\\/span><\\/div><\\/td><td><div align='left'><span class='style3'>([^<]*)<\\/span><\\/div><\\/td><\\/tr>/g;\n\n/** Parse one NLTR swaralipi page. Throws `ExtractError` on structural surprise. */\nexport function extractPage(html: string): NltrPage {\n const header: NltrHeader = {};\n for (const m of html.matchAll(META_ROW_RE)) {\n const label = normalizeCellText(m[1]!);\n const value = normalizeCellText(m[2]!);\n if (label === 'নাম') header.title = value;\n else if (label === 'তাল') header.taalNameRaw = value;\n else if (label === 'আবর্তন') header.avartanRaw = value;\n }\n const printMatch = html.match(/\\/print\\/(\\d+)/);\n if (printMatch) header.printId = Number(printMatch[1]);\n\n const cells: RawCell[] = [];\n let maxRow = 0;\n for (const m of html.matchAll(CELL_RE)) {\n const row = Number(m[1]);\n const col = Number(m[2]);\n cells.push({ row, col, style: m[3]!, text: normalizeCellText(m[4]!) });\n if (row > maxRow) maxRow = row;\n }\n\n // Strict-parse assertion: every grid <td> must have been captured.\n const tdCount = (html.match(/<td width='auto' id=/g) ?? []).length;\n if (cells.length !== tdCount) {\n throw new ExtractError(\n `grid cell mismatch: matched ${cells.length} cells but found ${tdCount} '<td width=' openers`,\n );\n }\n if (cells.length === 0) throw new ExtractError('no swaralipi grid cells found');\n if (header.title === undefined) throw new ExtractError('no নাম metadata row found');\n\n return { header, cells, maxRow };\n}\n","/**\n * Conversion reporting: per-file decode statistics and the batch aggregate.\n * The unknown-token histogram is the feedback loop for growing the codec.\n */\n\nexport interface FileReport {\n nltrId?: number;\n title: string;\n taalName?: string;\n taalId?: string;\n taalMatched: 'taals' | 'table' | 'geometry' | 'none';\n systems: number;\n notationCells: number;\n lyricCells: number;\n annotationCells: number;\n /** Notation cells with ≥1 semantic note and no unknown chunk. */\n decodedCells: number;\n /** Notation cells consisting only of understood-but-raw marks. */\n knownRawCells: number;\n /** Notation cells containing ≥1 chunk outside the grammar. */\n unknownCells: number;\n unknownTokens: Record<string, number>;\n lyricAlignMismatches: number;\n warnings: string[];\n}\n\nexport interface BatchFailure {\n file: string;\n error: string;\n}\n\nexport interface BatchReport {\n files: number;\n ok: number;\n failed: number;\n failures: BatchFailure[];\n systems: number;\n notationCells: number;\n lyricCells: number;\n annotationCells: number;\n decodedCells: number;\n knownRawCells: number;\n unknownCells: number;\n /** decoded / (decoded + knownRaw + unknown) over notation cells. */\n decodeRate: number;\n unknownRate: number;\n /** All unknown tokens, sorted by frequency (descending). */\n unknownTokens: Record<string, number>;\n lyricAlignMismatches: number;\n /** taalName → count + resolution outcome. */\n taals: Record<string, { count: number; taalId?: string; matched: string }>;\n warningCounts: Record<string, number>;\n}\n\nexport function aggregate(reports: FileReport[], failures: BatchFailure[]): BatchReport {\n const out: BatchReport = {\n files: reports.length + failures.length,\n ok: reports.length,\n failed: failures.length,\n failures,\n systems: 0,\n notationCells: 0,\n lyricCells: 0,\n annotationCells: 0,\n decodedCells: 0,\n knownRawCells: 0,\n unknownCells: 0,\n decodeRate: 0,\n unknownRate: 0,\n unknownTokens: {},\n lyricAlignMismatches: 0,\n taals: {},\n warningCounts: {},\n };\n const unknown = new Map<string, number>();\n for (const r of reports) {\n out.systems += r.systems;\n out.notationCells += r.notationCells;\n out.lyricCells += r.lyricCells;\n out.annotationCells += r.annotationCells;\n out.decodedCells += r.decodedCells;\n out.knownRawCells += r.knownRawCells;\n out.unknownCells += r.unknownCells;\n out.lyricAlignMismatches += r.lyricAlignMismatches;\n for (const [tok, n] of Object.entries(r.unknownTokens)) {\n unknown.set(tok, (unknown.get(tok) ?? 0) + n);\n }\n const taalKey = r.taalName ?? '<none>';\n const taalEntry = (out.taals[taalKey] ??= { count: 0, taalId: r.taalId, matched: r.taalMatched });\n taalEntry.count++;\n for (const w of r.warnings) {\n // Collapse per-file numbers so identical warning shapes aggregate.\n const shape = w.replace(/\\d+/g, 'N');\n out.warningCounts[shape] = (out.warningCounts[shape] ?? 0) + 1;\n }\n }\n out.unknownTokens = Object.fromEntries([...unknown.entries()].sort((a, b) => b[1] - a[1]));\n if (out.notationCells > 0) {\n out.decodeRate = out.decodedCells / out.notationCells;\n out.unknownRate = out.unknownCells / out.notationCells;\n }\n return out;\n}\n\nexport function formatSummary(r: BatchReport): string {\n const pct = (x: number) => `${(x * 100).toFixed(2)}%`;\n const lines = [\n `files: ${r.ok}/${r.files} converted${r.failed ? ` (${r.failed} FAILED)` : ''}`,\n `systems: ${r.systems} notation cells: ${r.notationCells} lyric cells: ${r.lyricCells} annotation cells: ${r.annotationCells}`,\n `decoded: ${r.decodedCells} (${pct(r.decodeRate)}) known-raw: ${r.knownRawCells} unknown: ${r.unknownCells} (${pct(r.unknownRate)})`,\n `lyric alignment fallbacks: ${r.lyricAlignMismatches}`,\n ];\n const unknowns = Object.entries(r.unknownTokens);\n if (unknowns.length > 0) {\n lines.push(`unknown tokens (${unknowns.length} distinct, top 20):`);\n for (const [tok, n] of unknowns.slice(0, 20)) lines.push(` ${String(n).padStart(6)} ${JSON.stringify(tok)}`);\n }\n const taalLines = Object.entries(r.taals).sort((a, b) => b[1].count - a[1].count);\n lines.push(`taals (${taalLines.length} distinct):`);\n for (const [name, info] of taalLines.slice(0, 15)) {\n lines.push(` ${String(info.count).padStart(5)} ${name} → ${info.taalId ?? '—'} [${info.matched}]`);\n }\n if (r.failed > 0) {\n lines.push('failures:');\n for (const f of r.failures.slice(0, 10)) lines.push(` ${f.file}: ${f.error}`);\n }\n return lines.join('\\n');\n}\n","/**\n * @ugfoundation/swaralipi-js/convert\n *\n * NLTR HTML → swaralipi JSON converter (Node-only subpath export).\n * `convertNltrHtml` itself is pure (string in, document out); file/dir\n * batch helpers live in the CLI (`swaralipi convert`).\n */\nimport { assemble, type ConvertOptions, type ConvertResult } from './assemble.js';\nimport { extractPage } from './extract.js';\n\nexport { ExtractError, extractPage } from './extract.js';\nexport type { NltrHeader, NltrPage, RawCell } from './extract.js';\nexport { buildSystems } from './grid.js';\nexport type { System } from './grid.js';\nexport { decodeCell } from './codec.js';\nexport type { CellDecode } from './codec.js';\nexport { bnInt, deriveGeometry, resolveTaal } from './taal-map.js';\nexport type { GridGeometry, ResolvedTaal } from './taal-map.js';\nexport { assemble, splitLyric } from './assemble.js';\nexport type { ConvertOptions, ConvertResult } from './assemble.js';\nexport { aggregate, formatSummary } from './report.js';\nexport type { BatchFailure, BatchReport, FileReport } from './report.js';\n\n/**\n * Convert one NLTR swaralipi page (HTML source text) into a validated\n * spec document plus a decode report.\n *\n * Throws `ExtractError` when the HTML does not look like an NLTR swaralipi\n * grid; cell-level decode problems never throw (they degrade to `raw`).\n */\nexport function convertNltrHtml(html: string, opts: ConvertOptions = {}): ConvertResult {\n return assemble(extractPage(html), opts);\n}\n"]}
package/dist/cli.cjs CHANGED
@@ -195,7 +195,7 @@ var init_spec = __esm({
195
195
  "src/spec/index.ts"() {
196
196
  init_schema();
197
197
  init_taals();
198
- SPEC_VERSION = "0.12.0";
198
+ SPEC_VERSION = "0.13.1";
199
199
  }
200
200
  });
201
201