@ugfoundation/swaralipi-js 0.1.5 → 0.1.6

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 (35) hide show
  1. package/dist/{batch-KKRTXF52.js → batch-IDFIHN7I.js} +5 -5
  2. package/dist/{batch-KKRTXF52.js.map → batch-IDFIHN7I.js.map} +1 -1
  3. package/dist/{chunk-R6QU5CXY.js → chunk-H6HC44PZ.js} +5 -3
  4. package/dist/chunk-H6HC44PZ.js.map +1 -0
  5. package/dist/{chunk-HTTURJ7A.js → chunk-LODUJ7OJ.js} +4 -4
  6. package/dist/{chunk-HTTURJ7A.js.map → chunk-LODUJ7OJ.js.map} +1 -1
  7. package/dist/{chunk-5PLGGEPK.js → chunk-QXDQAPE3.js} +3 -3
  8. package/dist/{chunk-5PLGGEPK.js.map → chunk-QXDQAPE3.js.map} +1 -1
  9. package/dist/cli.cjs +4 -2
  10. package/dist/cli.cjs.map +1 -1
  11. package/dist/cli.js +3 -3
  12. package/dist/convert/index.cjs +4 -2
  13. package/dist/convert/index.cjs.map +1 -1
  14. package/dist/convert/index.js +3 -3
  15. package/dist/index.cjs +4 -2
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/player/index.cjs +3 -1
  21. package/dist/player/index.cjs.map +1 -1
  22. package/dist/player/index.d.cts +1 -1
  23. package/dist/player/index.d.ts +1 -1
  24. package/dist/player/index.js +1 -1
  25. package/dist/spec/index.cjs +4 -2
  26. package/dist/spec/index.cjs.map +1 -1
  27. package/dist/spec/index.d.cts +2 -2
  28. package/dist/spec/index.d.ts +2 -2
  29. package/dist/spec/index.js +2 -2
  30. package/dist/{taals-DZU242TR.d.cts → taals-FmEulsjY.d.cts} +7 -0
  31. package/dist/{taals-DZU242TR.d.ts → taals-FmEulsjY.d.ts} +7 -0
  32. package/dist/viewer/index.cjs +4 -2
  33. package/dist/viewer/index.cjs.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-R6QU5CXY.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import { convertNltrHtml, aggregate, formatSummary } from './chunk-HTTURJ7A.js';
2
- import './chunk-5PLGGEPK.js';
3
- import './chunk-R6QU5CXY.js';
1
+ import { convertNltrHtml, aggregate, formatSummary } from './chunk-LODUJ7OJ.js';
2
+ import './chunk-QXDQAPE3.js';
3
+ import './chunk-H6HC44PZ.js';
4
4
  import { stat, readdir, mkdir, readFile, writeFile } from 'fs/promises';
5
5
  import { join, basename } from 'path';
6
6
 
@@ -43,5 +43,5 @@ async function runConvert(input, opts = {}) {
43
43
  }
44
44
 
45
45
  export { runConvert };
46
- //# sourceMappingURL=batch-KKRTXF52.js.map
47
- //# sourceMappingURL=batch-KKRTXF52.js.map
46
+ //# sourceMappingURL=batch-IDFIHN7I.js.map
47
+ //# sourceMappingURL=batch-IDFIHN7I.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/convert/batch.ts"],"names":["report"],"mappings":"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","file":"batch-KKRTXF52.js","sourcesContent":["/**\n * File/dir conversion driver for the CLI (Node-only; not part of the\n * public `/convert` export). Continues past per-file failures and reports\n * them in the aggregate.\n */\nimport { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { convertNltrHtml } from './index.js';\nimport { aggregate, formatSummary, type BatchFailure, type BatchReport, type FileReport } from './report.js';\n\nexport interface BatchOptions {\n /** Output file (single input) or directory (directory input). */\n out?: string;\n /** Write the aggregate report JSON here. */\n reportPath?: string;\n compact?: boolean;\n quiet?: boolean;\n /** Progress/summary sink (default stderr). */\n log?: (line: string) => void;\n}\n\nconst nltrIdOf = (file: string): number | undefined => {\n const m = basename(file).match(/^(\\d+)\\.html$/);\n return m ? Number(m[1]) : undefined;\n};\n\nconst serialize = (doc: unknown, compact: boolean | undefined): string =>\n (compact ? JSON.stringify(doc) : JSON.stringify(doc, null, 2)) + '\\n';\n\nexport async function runConvert(\n input: string,\n opts: BatchOptions = {},\n): Promise<{ exitCode: 0 | 1; report: BatchReport }> {\n const log = opts.log ?? ((line: string) => process.stderr.write(line + '\\n'));\n const stats = await stat(input);\n const files = stats.isDirectory()\n ? (await readdir(input))\n .filter((f) => f.endsWith('.html'))\n .sort((a, b) => (nltrIdOf(a) ?? 0) - (nltrIdOf(b) ?? 0) || a.localeCompare(b))\n .map((f) => join(input, f))\n : [input];\n\n const isDir = stats.isDirectory();\n if (isDir && !opts.out) throw new Error('directory input requires -o <outDir>');\n if (isDir && opts.out) await mkdir(opts.out, { recursive: true });\n\n const reports: FileReport[] = [];\n const failures: BatchFailure[] = [];\n for (const file of files) {\n try {\n const html = await readFile(file, 'utf8');\n const { doc, report } = convertNltrHtml(html, { nltrId: nltrIdOf(file) });\n reports.push(report);\n const json = serialize(doc, opts.compact);\n if (isDir) {\n const name = `${nltrIdOf(file) ?? basename(file, '.html')}.json`;\n await writeFile(join(opts.out!, name), json);\n } else if (opts.out) {\n await writeFile(opts.out, json);\n } else {\n process.stdout.write(json);\n }\n } catch (err) {\n failures.push({ file: basename(file), error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n const report = aggregate(reports, failures);\n if (opts.reportPath) await writeFile(opts.reportPath, serialize(report, false));\n if (!opts.quiet) log(formatSummary(report));\n return { exitCode: failures.length > 0 ? 1 : 0, report };\n}\n"]}
1
+ {"version":3,"sources":["../src/convert/batch.ts"],"names":["report"],"mappings":"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","file":"batch-IDFIHN7I.js","sourcesContent":["/**\n * File/dir conversion driver for the CLI (Node-only; not part of the\n * public `/convert` export). Continues past per-file failures and reports\n * them in the aggregate.\n */\nimport { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { convertNltrHtml } from './index.js';\nimport { aggregate, formatSummary, type BatchFailure, type BatchReport, type FileReport } from './report.js';\n\nexport interface BatchOptions {\n /** Output file (single input) or directory (directory input). */\n out?: string;\n /** Write the aggregate report JSON here. */\n reportPath?: string;\n compact?: boolean;\n quiet?: boolean;\n /** Progress/summary sink (default stderr). */\n log?: (line: string) => void;\n}\n\nconst nltrIdOf = (file: string): number | undefined => {\n const m = basename(file).match(/^(\\d+)\\.html$/);\n return m ? Number(m[1]) : undefined;\n};\n\nconst serialize = (doc: unknown, compact: boolean | undefined): string =>\n (compact ? JSON.stringify(doc) : JSON.stringify(doc, null, 2)) + '\\n';\n\nexport async function runConvert(\n input: string,\n opts: BatchOptions = {},\n): Promise<{ exitCode: 0 | 1; report: BatchReport }> {\n const log = opts.log ?? ((line: string) => process.stderr.write(line + '\\n'));\n const stats = await stat(input);\n const files = stats.isDirectory()\n ? (await readdir(input))\n .filter((f) => f.endsWith('.html'))\n .sort((a, b) => (nltrIdOf(a) ?? 0) - (nltrIdOf(b) ?? 0) || a.localeCompare(b))\n .map((f) => join(input, f))\n : [input];\n\n const isDir = stats.isDirectory();\n if (isDir && !opts.out) throw new Error('directory input requires -o <outDir>');\n if (isDir && opts.out) await mkdir(opts.out, { recursive: true });\n\n const reports: FileReport[] = [];\n const failures: BatchFailure[] = [];\n for (const file of files) {\n try {\n const html = await readFile(file, 'utf8');\n const { doc, report } = convertNltrHtml(html, { nltrId: nltrIdOf(file) });\n reports.push(report);\n const json = serialize(doc, opts.compact);\n if (isDir) {\n const name = `${nltrIdOf(file) ?? basename(file, '.html')}.json`;\n await writeFile(join(opts.out!, name), json);\n } else if (opts.out) {\n await writeFile(opts.out, json);\n } else {\n process.stdout.write(json);\n }\n } catch (err) {\n failures.push({ file: basename(file), error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n const report = aggregate(reports, failures);\n if (opts.reportPath) await writeFile(opts.reportPath, serialize(report, false));\n if (!opts.quiet) log(formatSummary(report));\n return { exitCode: failures.length > 0 ? 1 : 0, report };\n}\n"]}
@@ -12,9 +12,11 @@ var TAALS = {
12
12
  // ষষ্ঠী
13
13
  teora: { id: "teora", numBeats: 7, bhaags: [3, 2, 2], sam: 0 },
14
14
  // টেওরা
15
- teentaal: { id: "teentaal", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] }
15
+ teentaal: { id: "teentaal", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] },
16
+ aratheka: { id: "aratheka", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] }
17
+ // আড়াঠেকা
16
18
  };
17
19
 
18
20
  export { TAALS };
19
- //# sourceMappingURL=chunk-R6QU5CXY.js.map
20
- //# sourceMappingURL=chunk-R6QU5CXY.js.map
21
+ //# sourceMappingURL=chunk-H6HC44PZ.js.map
22
+ //# sourceMappingURL=chunk-H6HC44PZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/spec/taals.ts"],"names":[],"mappings":";AAcO,IAAM,KAAA,GAAQ;AAAA,EACnB,OAAO,EAAE,EAAA,EAAI,OAAA,EAAS,QAAA,EAAU,GAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAC,GAAG,GAAA,EAAK,CAAA,EAAG,MAAA,EAAQ,CAAC,CAAC,CAAA,EAAE;AAAA,EACvE,QAAQ,EAAE,EAAA,EAAI,QAAA,EAAU,QAAA,EAAU,GAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAC,GAAG,GAAA,EAAK,CAAA,EAAG,MAAA,EAAQ,CAAC,CAAC,CAAA,EAAE;AAAA,EACzE,OAAO,EAAE,EAAA,EAAI,OAAA,EAAS,QAAA,EAAU,GAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAG,MAAA,EAAQ,CAAC,CAAC,CAAA,EAAE;AAAA,EAC1E,UAAU,EAAE,EAAA,EAAI,YAAY,QAAA,EAAU,EAAA,EAAI,QAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAG,MAAA,EAAQ,CAAC,CAAC,CAAA,EAAE;AAAA,EACpF,MAAA,EAAQ,EAAE,EAAA,EAAI,QAAA,EAAU,UAAU,EAAA,EAAI,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAC,CAAA,EAAE;AAAA,EACzF,aAAa,EAAE,EAAA,EAAI,eAAe,QAAA,EAAU,EAAA,EAAI,KAAK,CAAA,EAAE;AAAA,EACvD,QAAA,EAAU,EAAE,EAAA,EAAI,UAAA,EAAY,UAAU,EAAA,EAAI,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAC,CAAA,EAAE;AAAA;AAAA,EAC7F,QAAA,EAAU,EAAE,EAAA,EAAI,UAAA,EAAY,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,CAAA,EAAE;AAAA;AAAA,EAChE,KAAA,EAAO,EAAE,EAAA,EAAI,OAAA,EAAS,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,KAAK,CAAA,EAAE;AAAA;AAAA,EAC7D,UAAU,EAAE,EAAA,EAAI,YAAY,QAAA,EAAU,EAAA,EAAI,QAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAG,MAAA,EAAQ,CAAC,CAAC,CAAA,EAAE;AAAA,EACpF,UAAU,EAAE,EAAA,EAAI,YAAY,QAAA,EAAU,EAAA,EAAI,QAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAG,MAAA,EAAQ,CAAC,CAAC,CAAA;AAAE;AACtF","file":"chunk-H6HC44PZ.js","sourcesContent":["import type { Taal } from './schema.js';\n\n/**\n * Reference definitions for the taals the player will sample:\n * adachautaal, dadra, ektaal, jhaptaal, kehrwa, rupak, shashthi, 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 *\n * Tabla loops live under `tabla/<id>/` by default; per-taal variation and\n * skip-bpm overrides (e.g. shashthi → `tabla/shashthi-pro/`) are in\n * instruments.ts's `TABLA_VARIATIONS`.\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 choutaal: { id: 'choutaal', numBeats: 12, bhaags: [2, 2, 2, 2, 2, 2], sam: 0, khaali: [2, 6] }, // চৌতাল\n shashthi: { id: 'shashthi', numBeats: 6, bhaags: [2, 4], sam: 0 }, // ষষ্ঠী\n teora: { id: 'teora', numBeats: 7, bhaags: [3, 2, 2], sam: 0 }, // টেওরা\n teentaal: { id: 'teentaal', numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] },\n aratheka: { id: 'aratheka', 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"]}
@@ -1,5 +1,5 @@
1
- import { swaralipiSchema, SPEC_VERSION } from './chunk-5PLGGEPK.js';
2
- import { TAALS } from './chunk-R6QU5CXY.js';
1
+ import { swaralipiSchema, SPEC_VERSION } from './chunk-QXDQAPE3.js';
2
+ import { TAALS } from './chunk-H6HC44PZ.js';
3
3
 
4
4
  // src/convert/codec.ts
5
5
  var LETTERS = {
@@ -589,5 +589,5 @@ function convertNltrHtml(html, opts = {}) {
589
589
  }
590
590
 
591
591
  export { ExtractError, aggregate, assemble, bnInt, buildSystems, convertNltrHtml, decodeCell, deriveGeometry, extractPage, formatSummary, resolveTaal, splitLyric };
592
- //# sourceMappingURL=chunk-HTTURJ7A.js.map
593
- //# sourceMappingURL=chunk-HTTURJ7A.js.map
592
+ //# sourceMappingURL=chunk-LODUJ7OJ.js.map
593
+ //# sourceMappingURL=chunk-LODUJ7OJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/convert/codec.ts","../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-HTTURJ7A.js","sourcesContent":["/**\n * The Swarabitan ASCII codec: decode one grid-cell text into spec `Note`s.\n *\n * NLTR renders notation through the legacy \"Swarabitan\" webfont, which maps\n * ASCII to akarmatrik glyphs. The table below was derived by dumping every\n * glyph of `Swarabitan.woff` (tools/font-dump/) and cross-checking against\n * the Swarabitan legend scans, the rendered reference screenshot of song\n * 4270, and corpus-wide token statistics. Evidence per assignment:\n *\n * Letters (full-size glyphs):\n * s=স r=র g=গ m=ম p=প q=ধ n=ন — the seven shuddha letters\n * d=দ (komal dha) t=জ্ঞ (komal ga) — legend: কোমল র—ঋ, কোমল গ—জ্ঞ,\n * k=ক্ষ (tivra ma) u=ণ (komal ni) — কড়ি ম—ক্ষ, কোমল ধ—দ, কোমল ন—ণ\n * v=ঋ (komal re)\n * Modifiers:\n * f = রেফ above → taar octave (zero-width high combining mark)\n * h = হসন্ত below → mandra octave (low combining mark; corpus nh/uh/dh/ph)\n * leading '-' = no new vowel attack (melisma; lyric row shows ৹)\n * trailing 'a' = the আ-কার matra carrier; k letter-units in one cell\n * share it → k notes of 1/k matra each\n * UPPERCASE letter = small raised form = কণ (kan/grace) prefix; takes its\n * own f/h (corpus: Sfua, NHsa, QHpha); width ratios ~0.65\n * confirm uppercase↔lowercase pairing\n * Structurals (own cells):\n * A = thin full-height bar → দাঁড়ি vibhag separator (fixed columns)\n * l = serif danda I → cycle end; ll / single-glyph L = section\n * %=সা &=নি — precomposed one-matra forms (rare)\n * Known-but-kept-raw marks (drawn pieces the spec doesn't model yet):\n * w x = left/right ends of a long under-arc; E J j y $ < > = _ = arc/line\n * fill segments; | = thin yugal-dari stop mark (mostly annotation rows);\n * digits/!/@ (+f/F sam tick) = taal beat labels; b=× o O e ` + , . i : ;\n * = dots/ticks/duration marks; B C * ^ ~ c = rare precomposed/legacy forms.\n *\n * Decoding never throws: any chunk outside the grammar becomes a raw-only\n * note and is reported as unknown — zero data loss by construction.\n */\nimport type { Note, Octave, Svara, SvaraLetter } from '../spec/index.js';\n\nexport interface CellDecode {\n notes: Note[];\n /** Chunks that failed the grammar (reported, kept as raw notes). */\n unknownTokens: string[];\n /** Chunks understood but intentionally left raw (marks, beat labels …). */\n knownRawTokens: string[];\n /** True if at least one chunk decoded to a semantic note. */\n decoded: boolean;\n}\n\ninterface LetterDef {\n letter: SvaraLetter;\n komal?: true;\n tivra?: true;\n}\n\n/** ASCII → svara letter (+ komal/tivra). The five non-shuddha glyph letters\n * are distinct characters in akarmatrik, so the flags live here. */\nconst LETTERS: Record<string, LetterDef> = {\n s: { letter: 's' },\n r: { letter: 'r' },\n g: { letter: 'g' },\n m: { letter: 'm' },\n p: { letter: 'p' },\n q: { letter: 'd' }, // ধ — shuddha dha\n n: { letter: 'n' },\n d: { letter: 'd', komal: true }, // দ\n t: { letter: 'g', komal: true }, // জ্ঞ\n k: { letter: 'm', tivra: true }, // ক্ষ\n u: { letter: 'n', komal: true }, // ণ\n v: { letter: 'r', komal: true }, // ঋ\n};\n\n/** Standalone structural tokens (bars are handled by the bar-run rule). */\nconst STRUCTURALS: Record<string, () => Note> = {\n '%': () => ({ svara: ['madhyam', 's'] }), // precomposed সা\n '&': () => ({ svara: ['madhyam', 'n'] }), // precomposed নি\n};\n\n/**\n * Bar/bracket runs: `l`(I danda) `ll`/`L`(II) `llll`/`LL`(IIII) `A`(দাঁড়ি),\n * plus composites the corpus writes into one cell — `l[]l` / `L[]L` (the\n * legend's \"I [ ] I\" return-to-asthayi-with-changed-notes marker), `AA`,\n * and `-A` (the previous note's continuation dash sharing the dari's cell).\n */\nconst BAR_RUN_RE = /^(-)?([lLA[\\]]+)$/;\n\nfunction decodeBarRun(body: string): Note[] | undefined {\n const m = body.match(BAR_RUN_RE);\n if (!m || !/[lLA]/.test(m[2]!)) return undefined;\n const notes: Note[] = [];\n if (m[1]) notes.push({ sustain: true });\n const run = m[2]!;\n let i = 0;\n while (i < run.length) {\n const ch = run[i]!;\n if (ch === 'l' || ch === 'L') {\n let j = i;\n while (j < run.length && run[j] === ch) j++;\n const strokes = (j - i) * (ch === 'L' ? 2 : 1);\n notes.push({ bar: strokes >= 4 ? 'quad' : strokes >= 2 ? 'double' : 'single' });\n i = j;\n } else if (ch === 'A') {\n notes.push({ bar: 'dari' });\n i++;\n } else {\n notes.push({ brackets: [{ kind: 'alt', edge: ch === '[' ? 'open' : 'close' }] });\n i++;\n }\n }\n return notes;\n}\n\n/** Marks/labels that are understood but deliberately preserved raw-only. */\nconst KNOWN_RAW_RE = [\n /^[wxyjEJ$<>=_]+$/, // arc & line drawing segments\n /^\\|+$/, // thin yugal-dari stop mark\n /^[0-9!@#]{1,2}[fF]?:?$/, // beat-number labels incl. 10–16 (sam tick = f/F, e.g. 1f / 1F / 2:)\n /^[oOe`+,.;:iI~^*bcBCWXYFHZz'\"?]$/, // dots, ticks, duration marks, legacy forms\n];\n\nconst OPEN_BRACKETS: Record<string, 'repeat' | 'skip' | 'alt'> = {\n '{': 'repeat',\n '(': 'skip',\n '[': 'alt',\n};\nconst CLOSE_BRACKETS: Record<string, 'repeat' | 'skip' | 'alt'> = {\n '}': 'repeat',\n ')': 'skip',\n ']': 'alt',\n};\n\nfunction octaveOf(mark: string | undefined): Octave {\n if (mark === 'f' || mark === 'F') return 'taar';\n if (mark === 'h' || mark === 'H') return 'mandra';\n return 'madhyam';\n}\n\n/**\n * Body grammar of one chunk (brackets already peeled):\n *\n * [beat-digit] ['-'] [KAN] unit* ['a'] [fh] [i:] [KAN] [beat-digit]\n *\n * where unit = letter [fh] and KAN = uppercase letter [fFhH]. Corpus\n * realities beyond the canonical `[-]KAN unit+ a` shape:\n * - octave mark typed after the আ-কার: `saf` ≡ `sfa` (taar sa) — the reph\n * applies to the last unit;\n * - trailing `i` (two stacked rings, ঃ-shaped — the ছেদ/cut mark) or `:`\n * after the matra: an articulation mark; the note decodes normally and\n * the mark stays visible in `raw`;\n * - trailing KAN (`-aR`): an anticipatory grace drawn at the cell's right\n * edge, leading into the next note — attached to this cell's last note;\n * - the cut mark may also lead or sit between units (`-iqi`, `mpimi`);\n * - leading `z` = blank spacer glyph (empty outline in the font) — skipped.\n * A standalone detached `a` (no hyphen) is a 1-matra rest per the legend\n * (\"হাইফেন-বর্জিত … বিরামের মাত্রা\").\n */\nconst BODY_RE =\n /^([0-9!@][fF]?)?([zj]*)(-)?([i:])?(?:([SRGMPQNDTKUV])([fFhH])?)?((?:[srgmpqndtkuv][fh]?[i:]?)+)?(a)?([fh])?([i:])?(?:([SRGMPQNDTKUV])([fFhH])?)?([0-9!@][fF]?)?(-)?$/;\n\nfunction decodeChunk(chunk: string): { notes: Note[]; kind: 'decoded' | 'known' | 'unknown' } {\n // 1. Peel brackets.\n const opens: ('repeat' | 'skip' | 'alt')[] = [];\n const closes: ('repeat' | 'skip' | 'alt')[] = [];\n let body = chunk;\n while (body.length > 0) {\n const kind = OPEN_BRACKETS[body[0]!];\n if (kind === undefined) break;\n opens.push(kind);\n body = body.slice(1);\n }\n while (body.length > 0) {\n const kind = CLOSE_BRACKETS[body[body.length - 1]!];\n if (kind === undefined) break;\n closes.unshift(kind);\n body = body.slice(0, -1);\n }\n\n const finish = (notes: Note[], kind: 'decoded' | 'known' | 'unknown') => {\n if (notes.length === 0) notes.push({});\n const first = notes[0]!;\n const last = notes[notes.length - 1]!;\n if (opens.length > 0) first.brackets = [...opens.map((kind_) => ({ kind: kind_, edge: 'open' as const })), ...(first.brackets ?? [])];\n if (closes.length > 0) last.brackets = [...(last.brackets ?? []), ...closes.map((kind_) => ({ kind: kind_, edge: 'close' as const }))];\n return { notes, kind };\n };\n\n // 2. Bracket-only chunk → raw carrier for the bracket edges.\n if (body === '') return finish([{}], 'decoded');\n\n // 3. Bar/bracket runs, then the remaining standalone structurals.\n const barRun = decodeBarRun(body);\n if (barRun) return finish(barRun, 'decoded');\n const structural = STRUCTURALS[body];\n if (structural) return finish([structural()], 'decoded');\n\n // 4. Known raw marks.\n if (KNOWN_RAW_RE.some((re) => re.test(body))) return finish([{}], 'known');\n\n // 5. Note grammar.\n const m = body.match(BODY_RE);\n if (m) {\n const [, , , hyphen, , kanLetter, kanOct, unitsStr, aakar, postOct, , trailKan, trailKanOct] = m;\n const attachKan = (note: Note, letter: string, oct: string | undefined) => {\n const def = LETTERS[letter.toLowerCase()]!;\n // NOTE: the spec kan is a plain [octave, letter] tuple, so a komal\n // kan letter (e.g. D = small দ) is projected onto its shuddha\n // letter; the exact glyph stays recoverable from `raw`.\n note.kan = [octaveOf(oct?.toLowerCase()), def.letter] as Svara;\n };\n if (unitsStr) {\n const units = unitsStr.match(/[srgmpqndtkuv][fh]?/g) ?? [];\n const notes: Note[] = units.map((unit) => {\n const def = LETTERS[unit[0]!]!;\n const note: Note = { svara: [octaveOf(unit[1]), def.letter] as Svara };\n if (def.komal) note.komal = true;\n if (def.tivra) note.tivra = true;\n if (units.length > 1) note.durationMatra = 1 / units.length;\n return note;\n });\n const last = notes[notes.length - 1]!;\n // Post-আকার octave mark (`saf`): applies to the last unit unless it\n // already carries its own mark.\n if (postOct && last.svara![0] === 'madhyam') {\n last.svara = [octaveOf(postOct), last.svara![1]] as Svara;\n }\n if (hyphen) notes[0]!.sustain = true;\n if (kanLetter) attachKan(notes[0]!, kanLetter, kanOct);\n if (trailKan && last.kan === undefined) attachKan(last, trailKan, trailKanOct);\n return finish(notes, 'decoded');\n }\n if (aakar) {\n // '-a' = sustain (hold previous pitch, no new attack);\n // bare detached 'a' = one-matra rest (legend: hyphen-less matra sign).\n const note: Note = hyphen ? { sustain: true } : { rest: true };\n if (trailKan) attachKan(note, trailKan, trailKanOct);\n else if (kanLetter) attachKan(note, kanLetter, kanOct);\n return finish([note], 'decoded');\n }\n if (hyphen && !kanLetter && !trailKan) {\n // A bare continuation dash (`-`, `-i`) — the আ-কার is implied.\n return finish([{ sustain: true }], 'decoded');\n }\n // Kan without units, or digit-edges with no note between — keep raw.\n }\n\n return finish([{}], 'unknown');\n}\n\n/**\n * Decode one cell's text. Multi-chunk cells (whitespace-separated) emit\n * notes in order; the first note of each chunk carries that chunk's source\n * text in `raw`, so joining a cell's `raw` values with spaces reproduces\n * the normalized cell text (the lossless property tests rely on this).\n */\nexport function decodeCell(text: string): CellDecode {\n const chunks = text.split(/\\s+/).filter((c) => c.length > 0);\n const out: CellDecode = { notes: [], unknownTokens: [], knownRawTokens: [], decoded: false };\n for (const chunk of chunks) {\n const { notes, kind } = decodeChunk(chunk);\n notes[0]!.raw = chunk;\n if (kind === 'decoded') out.decoded = true;\n else if (kind === 'known') out.knownRawTokens.push(chunk);\n else out.unknownTokens.push(chunk);\n out.notes.push(...notes);\n }\n return out;\n}\n","/**\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 * verbatim name always lands in `meta.taalName`.\n */\nimport { 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 the 7 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};\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: 'jhampak', numBeats: 5, bhaags: [3, 2], sam: 0 },\n ষষ্ঠী: { id: 'shashthi', numBeats: 6, bhaags: [2, 4], sam: 0 },\n রুপকড়া: { id: 'rupakda', numBeats: 8, bhaags: [3, 2, 3], sam: 0 },\n রূপকড়া: { id: 'rupakda', numBeats: 8, bhaags: [3, 2, 3], 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 খেমটা: 'khemta',\n আড়াঠেকা: 'araatheka',\n কাশ্মীরি: 'kashmiri',\n যৎ: 'yat',\n মধ্যমান: 'madhyaman',\n অর্দ্ধঝাঁপ: 'ardhajhanp',\n অর্ধঝাঁপ: 'ardhajhanp',\n 'বিলম্বিত ত্রিতাল': 'vilambit-teentaal',\n};\n\n/** Free-rhythm marker — never resolves to a taal. */\nconst TAAL_FREE = 'তালমুক্ত';\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 || taalName === TAAL_FREE) {\n return { taalName, avartan, matched: 'none', warnings };\n }\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"]}
1
+ {"version":3,"sources":["../src/convert/codec.ts","../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-LODUJ7OJ.js","sourcesContent":["/**\n * The Swarabitan ASCII codec: decode one grid-cell text into spec `Note`s.\n *\n * NLTR renders notation through the legacy \"Swarabitan\" webfont, which maps\n * ASCII to akarmatrik glyphs. The table below was derived by dumping every\n * glyph of `Swarabitan.woff` (tools/font-dump/) and cross-checking against\n * the Swarabitan legend scans, the rendered reference screenshot of song\n * 4270, and corpus-wide token statistics. Evidence per assignment:\n *\n * Letters (full-size glyphs):\n * s=স r=র g=গ m=ম p=প q=ধ n=ন — the seven shuddha letters\n * d=দ (komal dha) t=জ্ঞ (komal ga) — legend: কোমল র—ঋ, কোমল গ—জ্ঞ,\n * k=ক্ষ (tivra ma) u=ণ (komal ni) — কড়ি ম—ক্ষ, কোমল ধ—দ, কোমল ন—ণ\n * v=ঋ (komal re)\n * Modifiers:\n * f = রেফ above → taar octave (zero-width high combining mark)\n * h = হসন্ত below → mandra octave (low combining mark; corpus nh/uh/dh/ph)\n * leading '-' = no new vowel attack (melisma; lyric row shows ৹)\n * trailing 'a' = the আ-কার matra carrier; k letter-units in one cell\n * share it → k notes of 1/k matra each\n * UPPERCASE letter = small raised form = কণ (kan/grace) prefix; takes its\n * own f/h (corpus: Sfua, NHsa, QHpha); width ratios ~0.65\n * confirm uppercase↔lowercase pairing\n * Structurals (own cells):\n * A = thin full-height bar → দাঁড়ি vibhag separator (fixed columns)\n * l = serif danda I → cycle end; ll / single-glyph L = section\n * %=সা &=নি — precomposed one-matra forms (rare)\n * Known-but-kept-raw marks (drawn pieces the spec doesn't model yet):\n * w x = left/right ends of a long under-arc; E J j y $ < > = _ = arc/line\n * fill segments; | = thin yugal-dari stop mark (mostly annotation rows);\n * digits/!/@ (+f/F sam tick) = taal beat labels; b=× o O e ` + , . i : ;\n * = dots/ticks/duration marks; B C * ^ ~ c = rare precomposed/legacy forms.\n *\n * Decoding never throws: any chunk outside the grammar becomes a raw-only\n * note and is reported as unknown — zero data loss by construction.\n */\nimport type { Note, Octave, Svara, SvaraLetter } from '../spec/index.js';\n\nexport interface CellDecode {\n notes: Note[];\n /** Chunks that failed the grammar (reported, kept as raw notes). */\n unknownTokens: string[];\n /** Chunks understood but intentionally left raw (marks, beat labels …). */\n knownRawTokens: string[];\n /** True if at least one chunk decoded to a semantic note. */\n decoded: boolean;\n}\n\ninterface LetterDef {\n letter: SvaraLetter;\n komal?: true;\n tivra?: true;\n}\n\n/** ASCII → svara letter (+ komal/tivra). The five non-shuddha glyph letters\n * are distinct characters in akarmatrik, so the flags live here. */\nconst LETTERS: Record<string, LetterDef> = {\n s: { letter: 's' },\n r: { letter: 'r' },\n g: { letter: 'g' },\n m: { letter: 'm' },\n p: { letter: 'p' },\n q: { letter: 'd' }, // ধ — shuddha dha\n n: { letter: 'n' },\n d: { letter: 'd', komal: true }, // দ\n t: { letter: 'g', komal: true }, // জ্ঞ\n k: { letter: 'm', tivra: true }, // ক্ষ\n u: { letter: 'n', komal: true }, // ণ\n v: { letter: 'r', komal: true }, // ঋ\n};\n\n/** Standalone structural tokens (bars are handled by the bar-run rule). */\nconst STRUCTURALS: Record<string, () => Note> = {\n '%': () => ({ svara: ['madhyam', 's'] }), // precomposed সা\n '&': () => ({ svara: ['madhyam', 'n'] }), // precomposed নি\n};\n\n/**\n * Bar/bracket runs: `l`(I danda) `ll`/`L`(II) `llll`/`LL`(IIII) `A`(দাঁড়ি),\n * plus composites the corpus writes into one cell — `l[]l` / `L[]L` (the\n * legend's \"I [ ] I\" return-to-asthayi-with-changed-notes marker), `AA`,\n * and `-A` (the previous note's continuation dash sharing the dari's cell).\n */\nconst BAR_RUN_RE = /^(-)?([lLA[\\]]+)$/;\n\nfunction decodeBarRun(body: string): Note[] | undefined {\n const m = body.match(BAR_RUN_RE);\n if (!m || !/[lLA]/.test(m[2]!)) return undefined;\n const notes: Note[] = [];\n if (m[1]) notes.push({ sustain: true });\n const run = m[2]!;\n let i = 0;\n while (i < run.length) {\n const ch = run[i]!;\n if (ch === 'l' || ch === 'L') {\n let j = i;\n while (j < run.length && run[j] === ch) j++;\n const strokes = (j - i) * (ch === 'L' ? 2 : 1);\n notes.push({ bar: strokes >= 4 ? 'quad' : strokes >= 2 ? 'double' : 'single' });\n i = j;\n } else if (ch === 'A') {\n notes.push({ bar: 'dari' });\n i++;\n } else {\n notes.push({ brackets: [{ kind: 'alt', edge: ch === '[' ? 'open' : 'close' }] });\n i++;\n }\n }\n return notes;\n}\n\n/** Marks/labels that are understood but deliberately preserved raw-only. */\nconst KNOWN_RAW_RE = [\n /^[wxyjEJ$<>=_]+$/, // arc & line drawing segments\n /^\\|+$/, // thin yugal-dari stop mark\n /^[0-9!@#]{1,2}[fF]?:?$/, // beat-number labels incl. 10–16 (sam tick = f/F, e.g. 1f / 1F / 2:)\n /^[oOe`+,.;:iI~^*bcBCWXYFHZz'\"?]$/, // dots, ticks, duration marks, legacy forms\n];\n\nconst OPEN_BRACKETS: Record<string, 'repeat' | 'skip' | 'alt'> = {\n '{': 'repeat',\n '(': 'skip',\n '[': 'alt',\n};\nconst CLOSE_BRACKETS: Record<string, 'repeat' | 'skip' | 'alt'> = {\n '}': 'repeat',\n ')': 'skip',\n ']': 'alt',\n};\n\nfunction octaveOf(mark: string | undefined): Octave {\n if (mark === 'f' || mark === 'F') return 'taar';\n if (mark === 'h' || mark === 'H') return 'mandra';\n return 'madhyam';\n}\n\n/**\n * Body grammar of one chunk (brackets already peeled):\n *\n * [beat-digit] ['-'] [KAN] unit* ['a'] [fh] [i:] [KAN] [beat-digit]\n *\n * where unit = letter [fh] and KAN = uppercase letter [fFhH]. Corpus\n * realities beyond the canonical `[-]KAN unit+ a` shape:\n * - octave mark typed after the আ-কার: `saf` ≡ `sfa` (taar sa) — the reph\n * applies to the last unit;\n * - trailing `i` (two stacked rings, ঃ-shaped — the ছেদ/cut mark) or `:`\n * after the matra: an articulation mark; the note decodes normally and\n * the mark stays visible in `raw`;\n * - trailing KAN (`-aR`): an anticipatory grace drawn at the cell's right\n * edge, leading into the next note — attached to this cell's last note;\n * - the cut mark may also lead or sit between units (`-iqi`, `mpimi`);\n * - leading `z` = blank spacer glyph (empty outline in the font) — skipped.\n * A standalone detached `a` (no hyphen) is a 1-matra rest per the legend\n * (\"হাইফেন-বর্জিত … বিরামের মাত্রা\").\n */\nconst BODY_RE =\n /^([0-9!@][fF]?)?([zj]*)(-)?([i:])?(?:([SRGMPQNDTKUV])([fFhH])?)?((?:[srgmpqndtkuv][fh]?[i:]?)+)?(a)?([fh])?([i:])?(?:([SRGMPQNDTKUV])([fFhH])?)?([0-9!@][fF]?)?(-)?$/;\n\nfunction decodeChunk(chunk: string): { notes: Note[]; kind: 'decoded' | 'known' | 'unknown' } {\n // 1. Peel brackets.\n const opens: ('repeat' | 'skip' | 'alt')[] = [];\n const closes: ('repeat' | 'skip' | 'alt')[] = [];\n let body = chunk;\n while (body.length > 0) {\n const kind = OPEN_BRACKETS[body[0]!];\n if (kind === undefined) break;\n opens.push(kind);\n body = body.slice(1);\n }\n while (body.length > 0) {\n const kind = CLOSE_BRACKETS[body[body.length - 1]!];\n if (kind === undefined) break;\n closes.unshift(kind);\n body = body.slice(0, -1);\n }\n\n const finish = (notes: Note[], kind: 'decoded' | 'known' | 'unknown') => {\n if (notes.length === 0) notes.push({});\n const first = notes[0]!;\n const last = notes[notes.length - 1]!;\n if (opens.length > 0) first.brackets = [...opens.map((kind_) => ({ kind: kind_, edge: 'open' as const })), ...(first.brackets ?? [])];\n if (closes.length > 0) last.brackets = [...(last.brackets ?? []), ...closes.map((kind_) => ({ kind: kind_, edge: 'close' as const }))];\n return { notes, kind };\n };\n\n // 2. Bracket-only chunk → raw carrier for the bracket edges.\n if (body === '') return finish([{}], 'decoded');\n\n // 3. Bar/bracket runs, then the remaining standalone structurals.\n const barRun = decodeBarRun(body);\n if (barRun) return finish(barRun, 'decoded');\n const structural = STRUCTURALS[body];\n if (structural) return finish([structural()], 'decoded');\n\n // 4. Known raw marks.\n if (KNOWN_RAW_RE.some((re) => re.test(body))) return finish([{}], 'known');\n\n // 5. Note grammar.\n const m = body.match(BODY_RE);\n if (m) {\n const [, , , hyphen, , kanLetter, kanOct, unitsStr, aakar, postOct, , trailKan, trailKanOct] = m;\n const attachKan = (note: Note, letter: string, oct: string | undefined) => {\n const def = LETTERS[letter.toLowerCase()]!;\n // NOTE: the spec kan is a plain [octave, letter] tuple, so a komal\n // kan letter (e.g. D = small দ) is projected onto its shuddha\n // letter; the exact glyph stays recoverable from `raw`.\n note.kan = [octaveOf(oct?.toLowerCase()), def.letter] as Svara;\n };\n if (unitsStr) {\n const units = unitsStr.match(/[srgmpqndtkuv][fh]?/g) ?? [];\n const notes: Note[] = units.map((unit) => {\n const def = LETTERS[unit[0]!]!;\n const note: Note = { svara: [octaveOf(unit[1]), def.letter] as Svara };\n if (def.komal) note.komal = true;\n if (def.tivra) note.tivra = true;\n if (units.length > 1) note.durationMatra = 1 / units.length;\n return note;\n });\n const last = notes[notes.length - 1]!;\n // Post-আকার octave mark (`saf`): applies to the last unit unless it\n // already carries its own mark.\n if (postOct && last.svara![0] === 'madhyam') {\n last.svara = [octaveOf(postOct), last.svara![1]] as Svara;\n }\n if (hyphen) notes[0]!.sustain = true;\n if (kanLetter) attachKan(notes[0]!, kanLetter, kanOct);\n if (trailKan && last.kan === undefined) attachKan(last, trailKan, trailKanOct);\n return finish(notes, 'decoded');\n }\n if (aakar) {\n // '-a' = sustain (hold previous pitch, no new attack);\n // bare detached 'a' = one-matra rest (legend: hyphen-less matra sign).\n const note: Note = hyphen ? { sustain: true } : { rest: true };\n if (trailKan) attachKan(note, trailKan, trailKanOct);\n else if (kanLetter) attachKan(note, kanLetter, kanOct);\n return finish([note], 'decoded');\n }\n if (hyphen && !kanLetter && !trailKan) {\n // A bare continuation dash (`-`, `-i`) — the আ-কার is implied.\n return finish([{ sustain: true }], 'decoded');\n }\n // Kan without units, or digit-edges with no note between — keep raw.\n }\n\n return finish([{}], 'unknown');\n}\n\n/**\n * Decode one cell's text. Multi-chunk cells (whitespace-separated) emit\n * notes in order; the first note of each chunk carries that chunk's source\n * text in `raw`, so joining a cell's `raw` values with spaces reproduces\n * the normalized cell text (the lossless property tests rely on this).\n */\nexport function decodeCell(text: string): CellDecode {\n const chunks = text.split(/\\s+/).filter((c) => c.length > 0);\n const out: CellDecode = { notes: [], unknownTokens: [], knownRawTokens: [], decoded: false };\n for (const chunk of chunks) {\n const { notes, kind } = decodeChunk(chunk);\n notes[0]!.raw = chunk;\n if (kind === 'decoded') out.decoded = true;\n else if (kind === 'known') out.knownRawTokens.push(chunk);\n else out.unknownTokens.push(chunk);\n out.notes.push(...notes);\n }\n return out;\n}\n","/**\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 * verbatim name always lands in `meta.taalName`.\n */\nimport { 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 the 7 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};\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: 'jhampak', numBeats: 5, bhaags: [3, 2], sam: 0 },\n ষষ্ঠী: { id: 'shashthi', numBeats: 6, bhaags: [2, 4], sam: 0 },\n রুপকড়া: { id: 'rupakda', numBeats: 8, bhaags: [3, 2, 3], sam: 0 },\n রূপকড়া: { id: 'rupakda', numBeats: 8, bhaags: [3, 2, 3], 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 খেমটা: 'khemta',\n আড়াঠেকা: 'araatheka',\n কাশ্মীরি: 'kashmiri',\n যৎ: 'yat',\n মধ্যমান: 'madhyaman',\n অর্দ্ধঝাঁপ: 'ardhajhanp',\n অর্ধঝাঁপ: 'ardhajhanp',\n 'বিলম্বিত ত্রিতাল': 'vilambit-teentaal',\n};\n\n/** Free-rhythm marker — never resolves to a taal. */\nconst TAAL_FREE = 'তালমুক্ত';\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 || taalName === TAAL_FREE) {\n return { taalName, avartan, matched: 'none', warnings };\n }\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"]}
@@ -109,7 +109,7 @@ var swaralipiSchema = z.object({
109
109
  });
110
110
 
111
111
  // src/spec/index.ts
112
- var SPEC_VERSION = "0.1.5";
112
+ var SPEC_VERSION = "0.1.6";
113
113
  function parseSwaralipi(data) {
114
114
  return swaralipiSchema.parse(data);
115
115
  }
@@ -118,5 +118,5 @@ function safeParseSwaralipi(data) {
118
118
  }
119
119
 
120
120
  export { SPEC_VERSION, barSchema, bracketSchema, metaSchema, microtoneSchema, noteSchema, octaveSchema, parseSwaralipi, partSchema, rowSchema, safeParseSwaralipi, svaraLetterSchema, svaraSchema, swaralipiSchema, taalSchema };
121
- //# sourceMappingURL=chunk-5PLGGEPK.js.map
122
- //# sourceMappingURL=chunk-5PLGGEPK.js.map
121
+ //# sourceMappingURL=chunk-QXDQAPE3.js.map
122
+ //# sourceMappingURL=chunk-QXDQAPE3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/spec/schema.ts","../src/spec/index.ts"],"names":[],"mappings":"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","file":"chunk-5PLGGEPK.js","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 /**\n * Which tabla loop variation to play, e.g. `pro` (CDN dir suffix). Optional\n * and additive — omitted means the taal's default variation, so existing\n * docs are unaffected. The player honors it but never exposes a variation\n * picker; selecting a non-default variation is the consumer's premium policy.\n */\n variation: z.string().optional(),\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","/**\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.5';\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"]}
1
+ {"version":3,"sources":["../src/spec/schema.ts","../src/spec/index.ts"],"names":[],"mappings":"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","file":"chunk-QXDQAPE3.js","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 /**\n * Which tabla loop variation to play, e.g. `pro` (CDN dir suffix). Optional\n * and additive — omitted means the taal's default variation, so existing\n * docs are unaffected. The player honors it but never exposes a variation\n * picker; selecting a non-default variation is the consumer's premium policy.\n */\n variation: z.string().optional(),\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","/**\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.6';\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/cli.cjs CHANGED
@@ -144,7 +144,9 @@ var init_taals = __esm({
144
144
  // ষষ্ঠী
145
145
  teora: { id: "teora", numBeats: 7, bhaags: [3, 2, 2], sam: 0 },
146
146
  // টেওরা
147
- teentaal: { id: "teentaal", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] }
147
+ teentaal: { id: "teentaal", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] },
148
+ aratheka: { id: "aratheka", numBeats: 16, bhaags: [4, 4, 4, 4], sam: 0, khaali: [8] }
149
+ // আড়াঠেকা
148
150
  };
149
151
  }
150
152
  });
@@ -155,7 +157,7 @@ var init_spec = __esm({
155
157
  "src/spec/index.ts"() {
156
158
  init_schema();
157
159
  init_taals();
158
- SPEC_VERSION = "0.1.5";
160
+ SPEC_VERSION = "0.1.6";
159
161
  }
160
162
  });
161
163