@ugfoundation/swaralipi-js 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/viewer/glyphs.ts","../../src/viewer/render.ts","../../src/viewer/styles.ts","../../src/viewer/print.ts","../../src/viewer/transliterate.ts","../../src/viewer/element.ts"],"names":["note","escapeHtml"],"mappings":";AAiCO,IAAM,OAAA,GAAgE;AAAA,EAC3E,EAAA,EAAI;AAAA,IACF,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,QAAA,EAAI;AAAA,IAC9B,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,oBAAA,EAAM;AAAA,IAChC,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,oBAAA,EAAM;AAAA,IAChC,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,QAAA,EAAI;AAAA,IAC9B,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,QAAA;AAAI,GAChC;AAAA,EACA,EAAA,EAAI;AAAA,IACF,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,QAAA,EAAI;AAAA,IAC9B,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,oBAAA,EAAM;AAAA,IAChC,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,oBAAA,EAAM;AAAA,IAChC,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,QAAA,EAAI;AAAA,IAC9B,CAAA,EAAG,EAAE,OAAA,EAAS,QAAA,EAAK,OAAO,QAAA;AAAI,GAChC;AAAA,EACA,EAAA,EAAI;AAAA,IACF,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA,EAAI;AAAA,IAClB,CAAA,EAAG,EAAE,OAAA,EAAS,GAAA;AAAI;AAEtB;AAGO,IAAM,MAAA,GAAqC;AAAA,EAChD,EAAA,EAAI,8DAAA;AAAA,EACJ,EAAA,EAAI,8DAAA;AAAA,EACJ,EAAA,EAAI;AACN;AAGA,IAAM,sCAAsB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAK,QAAG,CAAC,CAAA;AAevC,IAAM,KAAA,GAAuC;AAAA,EAClD,EAAA,EAAI,EAAE,KAAA,EAAO,QAAA,EAAK,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAS,QAAA,EAAK,GAAA,EAAK,QAAA,EAAK,IAAA,EAAM,cAAA,EAAK;AAAA,EAClE,EAAA,EAAI,EAAE,KAAA,EAAO,QAAA,EAAK,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAS,QAAA,EAAK,GAAA,EAAK,QAAA,EAAK,IAAA,EAAM,cAAA,EAAK;AAAA,EAClE,EAAA,EAAI,EAAE,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAS,MAAA,EAAK,GAAA,EAAK,GAAA,EAAK,IAAA,EAAM,EAAA;AAC9D;AAGO,IAAM,MAAA,GAGT;AAAA,EACF,EAAA,EAAI,EAAE,KAAA,EAAO,oBAAA,EAAO,IAAA,EAAM,oBAAA,EAAO,IAAA,EAAM,oBAAA,EAAO,OAAA,EAAS,sCAAA,EAAU,UAAA,EAAY,kDAAA,EAAW;AAAA,EACxF,EAAA,EAAI,EAAE,KAAA,EAAO,oBAAA,EAAO,IAAA,EAAM,oBAAA,EAAO,IAAA,EAAM,oBAAA,EAAO,OAAA,EAAS,sCAAA,EAAU,UAAA,EAAY,kDAAA,EAAW;AAAA,EACxF,EAAA,EAAI,EAAE,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,UAAA;AACnF;AA2BO,SAAS,cAAA,CAAe,QAAqB,IAAA,EAA+B;AACjF,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,IAAA,CAAK,IAAI,EAAE,MAAM,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAC7B,EAAA,MAAM,UAAoB,EAAC;AAE3B,EAAA,IAAI,OAAO,KAAA,CAAM,OAAA;AACjB,EAAA,IAAI,KAAK,KAAA,EAAO;AACd,IAAA,IAAI,KAAA,CAAM,KAAA,KAAU,MAAA,EAAW,IAAA,GAAO,KAAA,CAAM,KAAA;AAAA,SACvC,OAAA,CAAQ,KAAK,UAAU,CAAA;AAAA,EAC9B;AACA,EAAA,IAAI,KAAK,KAAA,EAAO;AACd,IAAA,IAAI,KAAA,CAAM,KAAA,KAAU,MAAA,EAAW,IAAA,GAAO,KAAA,CAAM,KAAA;AAAA,SACvC,OAAA,CAAQ,KAAK,UAAU,CAAA;AAAA,EAC9B;AACA,EAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,GAAA,CAAI,IAAI,CAAA;AAElD,EAAA,IAAI,IAAA,GAAO,IAAA;AACX,EAAA,QAAQ,KAAK,MAAA;AAAQ,IACnB,KAAK,MAAA;AAAA,IACL,KAAK,UAAA;AAGH,MAAA,IAAI,KAAA,CAAM,IAAA,KAAS,EAAA,EAAI,OAAA,CAAQ,KAAK,cAAc,CAAA;AAAA,WAAA,IACzC,aAAA,EAAe,OAAA,CAAQ,IAAA,CAAK,aAAa,CAAA;AAAA,WAC7C,IAAA,GAAO,MAAM,IAAA,GAAO,IAAA;AACzB,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,UAAA,EAAY,OAAA,CAAQ,KAAK,aAAa,CAAA;AAC1D,MAAA;AAAA,IACF,KAAK,QAAA;AAAA,IACL,KAAK,YAAA;AAGH,MAAA,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,IAAA,KAAS,EAAA,GAAK,iBAAiB,WAAW,CAAA;AAC7D,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,YAAA,EAAc,OAAA,CAAQ,KAAK,eAAe,CAAA;AAC9D,MAAA;AAEA;AAGJ,EAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,EAAA,IAAI,IAAA,CAAK,SAAA,IAAa,KAAA,CAAM,KAAA,KAAU,EAAA,EAAI;AACxC,IAAA,IAAI,eAAe,aAAA,GAAgB,IAAA;AAAA,iBACtB,KAAA,CAAM,KAAA;AAAA,EACrB;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,aAAA,EAAc;AACxC;AAGO,SAAS,cAAA,CAAe,GAAW,IAAA,EAA0B;AAClE,EAAA,MAAM,MAAA,GAAS,OAAO,IAAI,CAAA;AAC1B,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAA,KAAM,MAAA,CAAO,CAAA,CAAE,UAAA,CAAW,CAAC,CAAA,GAAI,EAAE,CAAE,CAAA;AACjE;;;ACzIA,IAAM,IAAA,GAAO,MAAA;AACb,IAAM,GAAA,GAAM,IAAA;AAEZ,IAAM,UAAA,GAAa,CAAC,CAAA,KAAc,IAAA,CAAK,GAAA,CAAI,IAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,GAAA;AAEhE,SAAS,WAAW,CAAA,EAAmB;AACrC,EAAA,OAAO,CAAA,CACJ,OAAA,CAAQ,IAAA,EAAM,OAAO,EACrB,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,QAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,OAAA,CAAQ,MAAM,QAAQ,CAAA;AAC3B;AAaA,IAAM,SAAA,GAAY,CAAC,CAAA,KAAY,CAAA,CAAE,KAAA,KAAU,UAAa,CAAA,CAAE,IAAA,KAAS,IAAA,IAAQ,CAAA,CAAE,OAAA,KAAY,IAAA;AAOzF,SAAS,WAAW,IAAA,EAAgC;AAClD,EAAA,IAAI,IAAA,CAAK,GAAA,KAAQ,MAAA,EAAW,OAAO,MAAA;AACnC,EAAA,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,MAAA,IAAU,CAAA,IAAK,CAAA,IAAK,eAAe,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,MAAA;AAC9E,EAAA,OAAO,IAAA,CAAK,GAAA;AACd;AAaO,SAAS,kBAAkB,KAAA,EAAuB;AACvD,EAAA,MAAM,QAAgB,EAAC;AACvB,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,KAAA,CAAM,KAAK,GAAG,CAAA;AACd,MAAA,GAAA,GAAM,MAAA;AAAA,IACR;AACA,IAAA,GAAA,GAAM,CAAA;AAAA,EACR,CAAA;AACA,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM;AACzB,IAAA,IAAI,IAAA,CAAK,QAAQ,MAAA,EAAW;AAC1B,MAAA,KAAA,EAAM;AACN,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,GAAG,KAAA,EAAO,CAAC,IAAI,CAAA,EAAG,CAAA;AACnD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,SAAA,CAAU,IAAI,CAAA,EAAG;AACpB,MAAA,KAAA,EAAM;AACN,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,CAAW,IAAI,CAAA,KAAM,MAAA,GAAY,KAAA,GAAQ,SAAA,EAAW,OAAO,CAAA,EAAG,KAAA,EAAO,CAAC,IAAI,GAAG,CAAA;AAChG,MAAA;AAAA,IACF;AACA,IAAA,MAAM,CAAA,GAAI,KAAK,aAAA,IAAiB,CAAA;AAChC,IAAA,IAAI,UAAA,CAAW,CAAC,CAAA,EAAG;AACjB,MAAA,KAAA,EAAM;AACN,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,GAAG,KAAA,EAAO,CAAC,IAAI,CAAA,EAAG,CAAA;AACrD,MAAA;AAAA,IACF;AACA,IAAA,GAAA,KAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA,EAAG,KAAA,EAAO,EAAC,EAAE;AAC7C,IAAA,GAAA,CAAI,KAAA,CAAM,KAAK,IAAI,CAAA;AACnB,IAAA,GAAA,IAAO,CAAA;AACP,IAAA,IAAI,GAAA,GAAM,GAAA,IAAO,UAAA,CAAW,GAAG,GAAG,KAAA,EAAM;AAAA,EAC1C,CAAC,CAAA;AACD,EAAA,KAAA,EAAM;AACN,EAAA,OAAO,KAAA;AACT;AAmBA,IAAM,UAAA,GAAa,2BAAA;AACnB,IAAM,WAAW,CAAC,GAAA,KAChB,QAAQ,MAAA,IAAa,UAAA,CAAW,KAAK,GAAG,CAAA;AAanC,SAAS,WAAA,CAAY,OAAe,SAAA,EAA0B;AACnE,EAAA,MAAM,OAAc,EAAC;AACrB,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,MAAM,MAAA,GAAS,CAAC,GAAA,KAAgB;AAC9B,IAAA,OAAA,GAAU,IAAA;AACV,IAAA,IAAI,SAAA,KAAc,QAAW,SAAA,GAAY,GAAA;AAAA,EAC3C,CAAA;AACA,EAAA,MAAM,OAAA,GAAU,CAAC,GAAA,KAAgB;AAC/B,IAAA,OAAA,GAAU,IAAA;AACV,IAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,SAAA,EAAW,MAAA,EAAQ,KAAK,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,CAAA;AACjF,MAAA,SAAA,GAAY,MAAA;AAAA,IACd,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,KAAK,QAAA,EAAU,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,CAAA;AAAA,IAC1E;AAAA,EACF,CAAA;AAEA,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,QAAA,GAAW,KAAK,KAAA,GAAQ,CAAA;AAC9B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,MAAA;AACxC,IAAA,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM;AAC9B,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,GAAQ,CAAA,GAAI,CAAA;AAC7B,MAAA,IAAI,IAAA,CAAK,KAAA,KAAU,OAAA,EAAS,MAAA,CAAO,GAAG,CAAA;AAAA,WAAA,IAC7B,IAAA,CAAK,KAAA,KAAU,KAAA,EAAO,OAAA,CAAQ,GAAG,CAAA;AAC1C,MAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG;AAChC,QAAA,IAAI,CAAC,QAAA,CAAS,CAAA,CAAE,GAAG,CAAA,EAAG;AACtB,QAAA,KAAA,MAAW,EAAA,IAAM,EAAE,GAAA,EAAK;AACtB,UAAA,IAAI,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,SAAY,QAAQ,CAAA;AAAA,eAAA,IACpC,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,UAAa,OAAO,CAAA;AAAA,eAC7C,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,OAAO,CAAA;AAAA,QACtC;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,SAAA,EAAW,QAAQ,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,CAAC,CAAA,EAAG,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,MAAM,CAAA;AAAA,EACrG,CAAA,MAAA,IAAW,CAAC,OAAA,IAAW,QAAA,CAAS,SAAS,CAAA,EAAG;AAC1C,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAA;AAAA,MAC9B,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAA;AAAA,MAC5B,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,IAAA;AAAA,MACX,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,OAAO,IAAA;AACT;AASA,SAAS,aAAa,GAAA,EAAiC;AACrD,EAAA,IAAI,GAAA,KAAQ,QAAW,OAAO,CAAA;AAC9B,EAAA,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA,IAAK,EAAC,EAAG,MAAA;AACpC;AAGA,SAAS,eAAe,GAAA,EAA2D;AACjF,EAAA,MAAM,CAAA,GAAI,GAAA,CAAI,KAAA,CAAM,yBAAyB,CAAA;AAC7C,EAAA,IAAI,CAAC,GAAG,OAAO,MAAA;AACf,EAAA,OAAO,EAAE,QAAQ,CAAA,CAAE,CAAC,GAAI,GAAA,EAAK,CAAA,CAAE,CAAC,CAAA,KAAM,MAAA,EAAU;AAClD;AAYA,IAAM,cAAA,GAAiB;AAAA,EACrB,MAAM,EAAE,MAAA,EAAQ,KAAK,IAAA,EAAM,GAAA,EAAK,KAAK,GAAA,EAAI;AAAA,EACzC,OAAO,EAAE,MAAA,EAAQ,KAAK,IAAA,EAAM,GAAA,EAAK,KAAK,GAAA;AACxC,CAAA;AAEA,SAAS,aAAA,CAAc,MAAY,IAAA,EAAgC;AACjE,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,EAAU,OAAO,EAAA;AAC3B,EAAA,OAAO,IAAA,CAAK,SACT,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,IAAI,CAAA,CAC7B,GAAA,CAAI,CAAC,MAAM,CAAA,oBAAA,EAAuB,cAAA,CAAe,IAAI,CAAA,CAAE,CAAA,CAAE,IAAI,CAAC,CAAA,OAAA,CAAS,CAAA,CACvE,IAAA,CAAK,EAAE,CAAA;AACZ;AAIA,SAAS,SAAS,GAAA,EAAkB;AAClC,EAAA,OAAO,GAAA,CAAI,KAAA,CAAM,KAAA,KAAU,EAAA,GAAK,EAAA,GAAK,wBAAwB,IAAI,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,OAAA,CAAA;AACrF;AAEA,SAAS,UAAU,GAAA,EAAkB;AAEnC,EAAA,OAAO,IAAI,KAAA,CAAM,KAAA,KAAU,EAAA,GAAK,oCAAA,GAAkC,SAAS,GAAG,CAAA;AAChF;AAEA,SAAS,SAAA,CAAU,MAAY,GAAA,EAAkB;AAC/C,EAAA,IAAI,CAAC,IAAA,CAAK,GAAA,EAAK,OAAO,EAAA;AACtB,EAAA,MAAM,CAAC,MAAA,EAAQ,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA;AAC9B,EAAA,MAAM,CAAA,GAAI,cAAA,CAAe,MAAA,EAAQ,EAAE,MAAA,EAAQ,WAAW,KAAA,EAAO,IAAA,EAAM,GAAA,CAAI,IAAA,EAAM,CAAA;AAC7E,EAAA,OAAO,CAAA,aAAA,EAAgB,CAAC,QAAA,EAAU,GAAG,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,OAAA,CAAA;AACtE;AAYA,SAAS,kBAAA,CAAmB,IAAA,EAAY,IAAA,EAAmB,GAAA,EAAkB;AAC3E,EAAA,IAAI,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,MAAM,CAAA;AACtC,EAAA,KAAA,IAAS,SAAA,CAAU,MAAM,GAAG,CAAA;AAC5B,EAAA,IAAI,KAAK,OAAA,KAAY,IAAA,WAAe,CAAA,oBAAA,EAAuB,GAAA,CAAI,MAAM,MAAM,CAAA,OAAA,CAAA;AAC3E,EAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW;AAC5B,IAAA,MAAM,CAAC,MAAA,EAAQ,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA;AAC9B,IAAA,MAAM,CAAA,GAAI,eAAe,MAAA,EAAQ;AAAA,MAC/B,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,MAAA;AAAA,MACA,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,MAAM,GAAA,CAAI;AAAA,KACX,CAAA;AACD,IAAA,KAAA,IAAS,CAAA,aAAA,EAAgB,CAAC,OAAA,EAAS,GAAG,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,OAAA,CAAA;AACrE,IAAA,IAAI,CAAA,CAAE,aAAA,EAAe,KAAA,IAAS,QAAA,CAAS,GAAG,CAAA;AAAA,EAC5C,CAAA,MAAA,IAAW,IAAA,CAAK,IAAA,KAAS,IAAA,EAAM;AAC7B,IAAA,KAAA,IAAS,UAAU,GAAG,CAAA;AAAA,EACxB,CAAA,MAAA,IAAW,IAAA,CAAK,OAAA,KAAY,IAAA,IAAQ,KAAK,SAAA,EAAW;AAClD,IAAA,KAAA,IAAS,SAAS,GAAG,CAAA;AAAA,EACvB;AACA,EAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAGhC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,KAAc,UAAA,GAAa,QAAA,GAAM,QAAA;AACnD,IAAA,KAAA,IAAS,CAAA,8BAAA,EAAiC,IAAA,CAAK,SAAS,CAAA,EAAA,EAAK,IAAI,CAAA,OAAA,CAAA;AAAA,EACnE;AACA,EAAA,MAAM,CAAA,GAAI,KAAK,aAAA,IAAiB,CAAA;AAChC,EAAA,IAAI,UAAA,CAAW,CAAC,CAAA,IAAK,CAAA,GAAI,IAAI,GAAA,EAAK,KAAA,IAAS,QAAA,CAAS,GAAG,EAAE,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,CAAC,IAAI,CAAC,CAAA;AACjF,EAAA,IAAI,IAAA,CAAK,IAAA,GAAO,CAAA,EAAG,KAAA,IAAS,CAAA,qBAAA,EAAwB,IAAI,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,OAAA,CAAA,CAAU,MAAA,CAAO,KAAK,IAAI,CAAA;AAClG,EAAA,KAAA,IAAS,aAAA,CAAc,MAAM,OAAO,CAAA;AACpC,EAAA,OAAO,KAAA;AACT;AAEA,IAAM,WAAA,GAAc,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,IAAA,EAAM,CAAA,EAAE;AAE7D,SAAS,eAAe,IAAA,EAAoB;AAC1C,EAAA,MAAM,UAAU,SAAA,CAAU,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,GAAI,CAAC,CAAA;AACvD,EAAA,OAAO,CAAA,EAAG,aAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,EAAG,OAAO,CAAA,EAAG,aAAA,CAAc,IAAA,EAAM,OAAO,CAAC,CAAA,CAAA;AAChF;AAOA,SAAS,gBAAA,CAAiB,OAAe,GAAA,EAAkB;AACzD,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,IAAA,IAAQ,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAC3C,IAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AACvB,MAAA,MAAMA,KAAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AACzB,MAAA,KAAA,CAAM,IAAA,CAAK,+BAA+BA,KAAAA,CAAK,GAAG,KAAK,cAAA,CAAeA,KAAI,CAAC,CAAA,OAAA,CAAS,CAAA;AACpF,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,SAAS,OAAA,EAAS;AACzB,MAAA,MAAM,OAAO,YAAA,CAAa,IAAA,CAAK,KAAA,CAAM,CAAC,EAAG,GAAG,CAAA;AAC5C,MAAA,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,CAACA,KAAAA,EAAM,CAAA,KAAM;AAC9B,QAAA,MAAM,IAAA,GAAO,CAAA,KAAM,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA;AACvC,QAAA,KAAA,CAAM,IAAA;AAAA,UACJ,CAAA,mBAAA,EAAsB,kBAAA,CAAmBA,KAAAA,EAAM,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,IAAA,GAAO,IAAA,GAAO,CAAA,EAAE,EAAG,GAAG,CAAC,CAAA,OAAA;AAAA,SACjG;AAAA,MACF,CAAC,CAAA;AACD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AACzB,IAAA,MAAM,GAAA,GAAM,WAAW,IAAI,CAAA;AAC3B,IAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,MAAA,MAAM,IAAA,GAAO,eAAe,GAAG,CAAA;AAC/B,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,KAAA,CAAM,IAAA;AAAA,UACJ,CAAA,oBAAA,EAAuB,IAAA,CAAK,GAAA,GAAM,SAAA,GAAY,EAAE,CAAA,EAAA,EAAK,cAAA,CAAe,IAAA,CAAK,MAAA,EAAQ,GAAA,CAAI,IAAI,CAAC,CAAA,OAAA;AAAA,SAC5F;AAAA,MACF,CAAA,MAAA,IAAW,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,EAAG;AAC5B,QAAA,KAAA,CAAM,KAAK,CAAA,sBAAA,EAAyB,SAAA,CAAU,OAAO,GAAA,CAAI,MAAM,CAAC,CAAA,OAAA,CAAS,CAAA;AAAA,MAC3E,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,IAAA,CAAK,+BAA+B,UAAA,CAAW,GAAG,CAAC,CAAA,EAAA,EAAK,UAAA,CAAW,GAAG,CAAC,CAAA,OAAA,CAAS,CAAA;AAAA,MACxF;AACA,MAAA;AAAA,IACF;AACA,IAAA,MAAM,WAAW,aAAA,CAAc,IAAA,EAAM,MAAM,CAAA,GAAI,aAAA,CAAc,MAAM,OAAO,CAAA;AAC1E,IAAA,IAAI,aAAa,EAAA,EAAI,KAAA,CAAM,IAAA,CAAK,CAAA,yBAAA,EAA4B,QAAQ,CAAA,OAAA,CAAS,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,EAAE,CAAA;AACtB;AAIA,SAAS,SAAA,CAAU,GAAW,GAAA,EAAkB;AAC9C,EAAA,OAAO,EACJ,KAAA,CAAM,QAAG,EACT,GAAA,CAAI,CAAC,SAAU,IAAA,KAAS,EAAA,GAAK,EAAA,GAAK,GAAA,CAAI,GAAG,IAAI,CAAE,EAC/C,IAAA,CAAK,GAAA,CAAI,MAAM,OAAO,CAAA;AAC3B;AAMA,SAAS,SAAA,CAAU,GAAA,EAAU,OAAA,EAAiB,MAAA,EAAgB,GAAA,EAAkB;AAC9E,EAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,GAAA,CAAI,KAAK,CAAA;AACzC,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,KAAA,EAAO,GAAA,CAAI,MAAM,MAAM,CAAA;AAChD,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,QAAA,GAAW,KAAK,KAAA,GAAQ,CAAA;AAC9B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,MAAA;AACxC,IAAA,MAAM,QAAA,GACJ,OAAA,GAAU,QAAA,GAAW,CAAA,YAAA,EAAe,QAAQ,MAAM,OAAA,GAAU,CAAC,CAAA,CAAA,GAAK,CAAA,YAAA,EAAe,QAAQ,CAAA,CAAA;AAC3F,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,KAAS,OAAA,GAAU,YAAA,CAAa,KAAK,KAAA,CAAM,CAAC,CAAA,CAAG,GAAG,CAAA,GAAI,CAAA;AAExE,IAAA,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM;AAC9B,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,GAAQ,CAAA,GAAI,CAAA;AAC7B,MAAA,MAAM,IAAA,GAAO,GAAG,OAAO,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,QAAQ,CAAC,CAAA,CAAA;AACnD,MAAA,MAAM,SAAA,GAAY,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,QAAA,GAAW,EAAE,CAAA,EAAG,CAAA,KAAM,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,WAAW,EAAE,CAAA,CAAA;AAE1F,MAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AACvB,QAAA,QAAA,CAAS,IAAA;AAAA,UACP,CAAA,4BAAA,EAA+B,IAAA,CAAK,GAAG,CAAA,EAAG,SAAS,CAAA,aAAA,EAAgB,IAAI,CAAA,qBAAA,EAAwB,GAAG,CAAA,EAAA,EAAK,cAAA,CAAe,IAAI,CAAC,CAAA,OAAA;AAAA,SAC7H;AAAA,MACF,CAAA,MAAA,IAAW,IAAA,CAAK,IAAA,KAAS,OAAA,EAAS;AAChC,QAAA,MAAM,IAAA,GAAO,CAAA,KAAM,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA;AACvC,QAAA,QAAA,CAAS,IAAA;AAAA,UACP,oBAAoB,SAAS,CAAA,aAAA,EAAgB,IAAI,CAAA,qBAAA,EAAwB,GAAG,KAAK,kBAAA,CAAmB,IAAA,EAAM,EAAE,SAAA,EAAW,MAAM,IAAA,EAAM,IAAA,GAAO,OAAO,CAAA,EAAE,EAAG,GAAG,CAAC,CAAA,OAAA;AAAA,SAC5J;AAAA,MACF,CAAA,MAAO;AACL,QAAA,MAAM,GAAA,GAAM,WAAW,IAAI,CAAA;AAC3B,QAAA,MAAM,QACJ,aAAA,CAAc,IAAA,EAAM,MAAM,CAAA,IACzB,GAAA,KAAQ,SACL,CAAA,4BAAA,EAA+B,UAAA,CAAW,GAAG,CAAC,CAAA,EAAA,EAAK,WAAW,GAAG,CAAC,YAClE,EAAA,CAAA,GACJ,aAAA,CAAc,MAAM,OAAO,CAAA;AAC7B,QAAA,IAAI,UAAU,EAAA,EAAI;AAChB,UAAA,QAAA,CAAS,IAAA;AAAA,YACP,+BAA+B,SAAS,CAAA,aAAA,EAAgB,IAAI,CAAA,qBAAA,EAAwB,GAAG,KAAK,KAAK,CAAA,OAAA;AAAA,WACnG;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW;AAC5B,QAAA,KAAA,CAAM,IAAA;AAAA,UACJ,CAAA,wCAAA,EAA2C,GAAG,CAAA,EAAA,EAAK,UAAA,CAAW,UAAU,IAAA,CAAK,KAAA,EAAO,GAAG,CAAC,CAAC,CAAA,OAAA;AAAA,SAC3F;AAAA,MACF;AACA,MAAA,IAAI,KAAK,KAAA,KAAU,MAAA,IAAa,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA,EAAG;AACrD,QAAA,KAAA,CAAM,IAAA,CAAK,iCAAiC,QAAQ,CAAA,EAAA,EAAK,iBAAiB,IAAA,CAAK,KAAA,EAAO,GAAG,CAAC,CAAA,OAAA,CAAS,CAAA;AAAA,MACrG;AACA,MAAA,MAAM,MAAA,GAAA,CAAU,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,QAAA,CAAS,CAAA,CAAE,GAAG,CAAC,CAAA;AAChE,MAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,QAAA,KAAA,CAAM,IAAA,CAAK,iCAAiC,QAAQ,CAAA,EAAA,EAAK,iBAAiB,MAAA,EAAQ,GAAG,CAAC,CAAA,OAAA,CAAS,CAAA;AAAA,MACjG;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,GAAA,GAAM;AAAA,MACV,QAAA;AAAA,MACA,GAAA,CAAI,WAAW,eAAA,GAAkB,EAAA;AAAA,MACjC,GAAA,CAAI,YAAY,eAAA,GAAkB,EAAA;AAAA,MAClC,GAAA,CAAI,IAAA,KAAS,IAAA,GAAO,cAAA,GAAiB;AAAA,KACvC,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AACX,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,GAAG,CAAA,qBAAA,EAAwB,GAAA,CAAI,QAAQ,CAAA,GAAA,EAAM,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA,SAAA,CAAW,CAAA;AAAA,EACnG;AAEA,EAAA,MAAM,KAAA,GACJ,GAAA,CAAI,KAAA,KAAU,MAAA,GAAY,CAAA,uBAAA,EAA0B,UAAA,CAAW,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,KAAK,CAAC,CAAC,CAAA,OAAA,CAAA,GAAY,EAAA;AAC/F,EAAA,OAAO,CAAA,oBAAA,EAAuB,KAAK,CAAA,qBAAA,EAAwB,KAAA,CAAM,KAAK,EAAE,CAAC,GAAG,QAAA,CAAS,IAAA,CAAK,EAAE,CAAC,CAAA,EAAG,MAAM,IAAA,CAAK,EAAE,CAAC,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,EAAE,CAAC,CAAA,YAAA,CAAA;AACjI;AAEA,SAAS,YAAA,CAAa,MAAY,GAAA,EAAkB;AAClD,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AACzB,EAAA,MAAM,OAAiB,EAAC;AACxB,EAAA,MAAM,GAAA,GAAM,CAAC,KAAA,EAAe,KAAA,KAC1B,IAAA,CAAK,IAAA;AAAA,IACH,wDAAwD,UAAA,CAAW,KAAK,CAAC,CAAA,mCAAA,EAAsC,UAAA,CAAW,KAAK,CAAC,CAAA,aAAA;AAAA,GAClI;AACF,EAAA,GAAA,CAAI,EAAE,KAAA,EAAO,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,KAAK,CAAC,CAAA;AAC/B,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,IAAA,EAAM,EAAA;AACzC,EAAA,IAAI,IAAA,KAAS,QAAW,GAAA,CAAI,CAAA,CAAE,MAAM,GAAA,CAAI,EAAA,CAAG,IAAI,CAAC,CAAA;AAChD,EAAA,IAAI,IAAA,CAAK,IAAA,KAAS,MAAA,EAAW,GAAA,CAAI,CAAA,CAAE,MAAM,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,IAAI,CAAC,CAAA;AAC1D,EAAA,IAAI,IAAA,CAAK,OAAA,KAAY,MAAA,EAAW,GAAA,CAAI,CAAA,CAAE,OAAA,EAAS,cAAA,CAAe,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG,GAAA,CAAI,IAAI,CAAC,CAAA;AAC7F,EAAA,IAAI,IAAA,CAAK,UAAA,KAAe,MAAA,EAAW,GAAA,CAAI,CAAA,CAAE,YAAY,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,UAAU,CAAC,CAAA;AAC5E,EAAA,OAAO,CAAA,0BAAA,EAA6B,IAAA,CAAK,IAAA,CAAK,EAAE,CAAC,CAAA,SAAA,CAAA;AACnD;AAKO,SAAS,YAAA,CAAa,GAAA,EAAgB,IAAA,GAAsB,EAAC,EAAW;AAC7E,EAAA,MAAM,IAAA,GAAmB,KAAK,IAAA,IAAQ,IAAA;AACtC,EAAA,MAAM,EAAA,GAAK,SAAS,IAAA,IAAQ,IAAA,CAAK,gBAAgB,IAAA,CAAK,aAAA,GAAgB,CAAC,CAAA,KAAc,CAAA;AACrF,EAAA,MAAM,MAAW,EAAE,IAAA,EAAM,OAAO,KAAA,CAAM,IAAI,GAAG,EAAA,EAAG;AAEhD,EAAA,MAAM,GAAA,GAAgB,CAAC,CAAA,4BAAA,EAA+B,IAAI,CAAA,EAAA,CAAI,CAAA;AAC9D,EAAA,IAAI,IAAA,CAAK,eAAe,KAAA,EAAO,GAAA,CAAI,KAAK,YAAA,CAAa,GAAA,CAAI,IAAA,EAAM,GAAG,CAAC,CAAA;AACnE,EAAA,GAAA,CAAI,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM;AAC7B,IAAA,GAAA,CAAI,KAAK,2BAA2B,CAAA;AACpC,IAAA,IAAI,KAAK,IAAA,KAAS,MAAA;AAChB,MAAA,GAAA,CAAI,IAAA,CAAK,4BAA4B,UAAA,CAAW,GAAA,CAAI,GAAG,IAAA,CAAK,IAAI,CAAC,CAAC,CAAA,KAAA,CAAO,CAAA;AAC3E,IAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAC,CAAA;AACjE,IAAA,GAAA,CAAI,KAAK,YAAY,CAAA;AAAA,EACvB,CAAC,CAAA;AACD,EAAA,GAAA,CAAI,KAAK,QAAQ,CAAA;AACjB,EAAA,OAAO,GAAA,CAAI,KAAK,EAAE,CAAA;AACpB;;;ACrdO,IAAM,aAAA,GAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwNtB,IAAM,mBAAA,GAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC1MnC,SAASC,YAAW,CAAA,EAAmB;AACrC,EAAA,OAAO,CAAA,CACJ,OAAA,CAAQ,IAAA,EAAM,OAAO,EACrB,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,QAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,OAAA,CAAQ,MAAM,QAAQ,CAAA;AAC3B;AAQO,SAAS,mBAAA,CAAoB,GAAA,EAAgB,IAAA,GAAqB,EAAC,EAAW;AACnF,EAAA,MAAM,IAAA,GAAmB,KAAK,IAAA,IAAQ,IAAA;AACtC,EAAA,MAAM,EAAA,GAAK,SAAS,IAAA,IAAQ,IAAA,CAAK,gBAAgB,IAAA,CAAK,aAAA,GAAgB,CAAC,CAAA,KAAc,CAAA;AACrF,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,IAAS,EAAA,CAAG,GAAA,CAAI,KAAK,KAAK,CAAA;AAC7C,EAAA,MAAM,IAAA,GAAO,aAAa,GAAA,EAAK;AAAA,IAC7B,IAAA;AAAA,IACA,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,eAAe,IAAA,CAAK;AAAA,GACrB,CAAA;AACD,EAAA,OAAO,CAAA;AAAA,YAAA,EACKA,WAAAA,CAAW,IAAI,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAIrBA,WAAAA,CAAW,KAAK,CAAC,CAAA;AAAA;AAAA,EAExB,aAAa;AAAA,EACb,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAAA,EAMb,IAAI,CAAA;AAAA,OAAA,CAAA;AAEZ;AASO,SAAS,cAAA,CAAe,GAAA,EAAgB,IAAA,GAAqB,EAAC,EAAS;AAC5E,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACnC,IAAA,MAAM,IAAI,MAAM,8EAA8E,CAAA;AAAA,EAChG;AACA,EAAA,MAAM,IAAA,GAAO,mBAAA,CAAoB,GAAA,EAAK,IAAI,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,EAAA,MAAA,CAAO,YAAA,CAAa,eAAe,MAAM,CAAA;AAGzC,EAAA,MAAA,CAAO,MAAM,OAAA,GAAU,4EAAA;AAEvB,EAAA,MAAA,CAAO,SAAS,MAAM;AACpB,IAAA,MAAM,MAAM,MAAA,CAAO,aAAA;AACnB,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,MAAA,CAAO,MAAA,EAAO;AACd,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAU,MAAM,UAAA,CAAW,MAAM,MAAA,CAAO,MAAA,IAAU,GAAI,CAAA;AAC5D,IAAA,GAAA,CAAI,iBAAiB,YAAA,EAAc,OAAA,EAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAC1D,IAAA,MAAM,KAAK,MAAM;AACf,MAAA,IAAI;AACF,QAAA,GAAA,CAAI,KAAA,EAAM;AACV,QAAA,GAAA,CAAI,KAAA,EAAM;AAAA,MACZ,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,KAAA,GAAQ,OAAO,eAAA,EAAiB,KAAA;AACtC,IAAA,IAAI,KAAA,EAAO,OAAO,KAAK,KAAA,CAAM,MAAM,IAAA,CAAK,EAAE,CAAA,CAAE,KAAA,CAAM,EAAE,CAAA;AAAA,SAC/C,UAAA,CAAW,IAAI,GAAG,CAAA;AAAA,EACzB,CAAA;AAEA,EAAA,MAAA,CAAO,MAAA,GAAS,IAAA;AAChB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAClC;;;ACxGA,IAAM,MAAA,GAAoD;AAAA,EACxD,EAAA,EAAI,YAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAQA,eAAsB,wBAAwB,IAAA,EAAuD;AACnG,EAAA,IAAI,IAAA,KAAS,MAAM,OAAO,MAAA;AAC1B,EAAA,MAAM,GAAA,GAAO,MAAM,OAAO,kCAAkC,CAAA;AAI5D,EAAA,MAAM,SAAA,GAAY,IAAI,OAAA,IAAW,GAAA;AACjC,EAAA,MAAM,MAAA,GAAS,OAAO,IAAI,CAAA;AAC1B,EAAA,OAAO,CAAC,IAAA,KAAS,SAAA,CAAU,CAAA,CAAG,IAAA,EAAM,WAAW,MAAM,CAAA;AACvD;;;ACEA,IAAM,wBAA6B,IAAI,GAAA,CAAI,CAAC,IAAA,EAAM,IAAA,EAAM,IAAI,CAAC,CAAA;AAE7D,IAAI,WAAA;AAEJ,SAAS,kBAAA,GAA+C;AACtD,EAAA,OAAO,MAAM,uBAAuB,WAAA,CAA6C;AAAA,IAC/E,OAAO,kBAAA,GAAqB,CAAC,KAAA,EAAO,QAAQ,aAAa,CAAA;AAAA,IAEzD,IAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA,GAAW,KAAA;AAAA,IACX,MAAA;AAAA,IACA,SAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA,GAAW,KAAA;AAAA,IAEX,WAAA,GAAc;AACZ,MAAA,KAAA,EAAM;AACN,MAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,YAAA,CAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AAC/C,MAAA,IACE,OAAO,kBAAkB,WAAA,IACzB,aAAA,IAAiB,cAAc,SAAA,IAC/B,oBAAA,IAAwB,KAAK,KAAA,EAC7B;AACA,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,WAAA,GAAc,IAAI,aAAA,EAAc;AAChC,UAAA,WAAA,CAAY,YAAY,aAAa,CAAA;AAAA,QACvC;AACA,QAAA,IAAA,CAAK,MAAM,kBAAA,GAAqB,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,oBAAoB,WAAW,CAAA;AAC9E,QAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,MAClB;AAAA,IACF;AAAA,IAEA,IAAI,GAAA,GAA6B;AAC/B,MAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACd;AAAA,IAEA,IAAI,IAAI,KAAA,EAA8B;AACpC,MAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AACZ,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,IAAA,CAAK,QAAA,EAAU;AACxC,QAAA,KAAK,OAAO,kBAAkB,CAAA,CAC3B,KAAK,CAAC,EAAE,oBAAmB,KAAM;AAChC,UAAA,MAAM,MAAA,GAAS,mBAAmB,KAAK,CAAA;AACvC,UAAA,IAAI,CAAC,MAAA,CAAO,OAAA,OAAc,YAAA,CAAa,MAAA,CAAO,MAAM,OAAO,CAAA;AAAA,QAC7D,CAAC,CAAA,CACA,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,MAC1B;AACA,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf;AAAA,IAEA,IAAI,KAAA,GAAoB;AACtB,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,YAAA,CAAa,MAAM,CAAA;AACrC,MAAA,OAAO,SAAS,IAAA,IAAQ,KAAA,CAAM,GAAA,CAAI,IAAI,IAAK,IAAA,GAAsB,IAAA;AAAA,IACnE;AAAA,IAEA,wBAAA,CAAyB,IAAA,EAAc,QAAA,EAAyB,QAAA,EAA+B;AAC7F,MAAA,IAAI,aAAa,QAAA,EAAU;AAC3B,MAAA,IAAI,SAAS,KAAA,EAAO;AAClB,QAAA,IAAI,QAAA,KAAa,IAAA,EAAM,KAAK,IAAA,CAAK,MAAM,QAAQ,CAAA;AAC/C,QAAA;AAAA,MACF;AACA,MAAA,IAAI,IAAA,KAAS,MAAA,EAAQ,IAAA,CAAK,qBAAA,EAAsB;AAChD,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf;AAAA,IAEA,iBAAA,GAA0B;AACxB,MAAA,IAAA,CAAK,qBAAA,EAAsB;AAC3B,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf;AAAA,IAEA,oBAAA,GAA6B;AAC3B,MAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,IACrB;AAAA,IAEA,MAAM,MAAM,GAAA,EAA4B;AACtC,MAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,MAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAClC,MAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,CAAM,QAAQ,CAAA;AACrD,QAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,MAAA,EAAS,GAAG,CAAA,OAAA,EAAU,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAC/D,QAAA,IAAA,CAAK,GAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAAA,MAC7B,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,KAAA,CAAM,OAAO,OAAA,EAAS;AAC1B,QAAA,IAAA,CAAK,aAAa,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAClE,QAAA,IAAA,CAAK,aAAA,CAAc,IAAI,UAAA,CAAW,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,OAAA,EAAS,MAAA,CAAO,GAAG,CAAA,EAAG,CAAC,CAAA;AAAA,MAClF;AAAA,IACF;AAAA;AAAA,IAGA,qBAAA,GAA8B;AAC5B,MAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,MAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,CAAK,aAAA,KAAkB,IAAA,EAAM;AAClD,MAAA,KAAK,uBAAA,CAAwB,IAAI,CAAA,CAC9B,IAAA,CAAK,CAAC,CAAA,KAAM;AACX,QAAA,IAAI,CAAA,KAAM,MAAA,IAAa,IAAA,CAAK,KAAA,KAAU,IAAA,EAAM;AAC5C,QAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AACjB,QAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,QAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,MACf,CAAC,CAAA,CACA,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,IAC1B;AAAA,IAEA,cAAA,GAAyB;AACvB,MAAA,OAAO,IAAA,CAAK,QAAA,GAAW,EAAA,GAAK,CAAA,OAAA,EAAU,aAAa,CAAA,QAAA,CAAA;AAAA,IACrD;AAAA,IAEA,OAAA,GAAgB;AACd,MAAA,IAAI,IAAA,CAAK,SAAS,MAAA,EAAW;AAC3B,QAAA,IAAA,CAAK,KAAA,CAAM,SAAA,GAAY,IAAA,CAAK,cAAA,EAAe;AAC3C,QAAA;AAAA,MACF;AACA,MAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,MAAA,MAAM,IAAA,GAAO,YAAA,CAAa,IAAA,CAAK,IAAA,EAAM;AAAA,QACnC,IAAA;AAAA,QACA,UAAA,EAAY,CAAC,IAAA,CAAK,YAAA,CAAa,aAAa,CAAA;AAAA,QAC5C,aAAA,EAAe,IAAA,CAAK,aAAA,KAAkB,IAAA,GAAO,KAAK,SAAA,GAAY;AAAA,OAC/D,CAAA;AACD,MAAA,IAAA,CAAK,KAAA,CAAM,SAAA,GAAY,IAAA,CAAK,cAAA,EAAe,GAAI,IAAA;AAAA,IACjD;AAAA,IAEA,aAAa,OAAA,EAAuB;AAClC,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,UAAA;AAChB,MAAA,GAAA,CAAI,WAAA,GAAc,OAAA;AAClB,MAAA,IAAA,CAAK,KAAA,CAAM,SAAA,GAAY,IAAA,CAAK,cAAA,EAAe;AAC3C,MAAA,IAAA,CAAK,KAAA,CAAM,YAAY,GAAG,CAAA;AAAA,IAC5B;AAAA,IAEA,UAAU,IAAA,EAAkC;AAC1C,MAAA,IAAI,CAAC,iBAAA,CAAkB,IAAA,CAAK,IAAI,GAAG,OAAO,IAAA;AAC1C,MAAA,MAAM,KAAK,IAAA,CAAK,KAAA,CAAM,aAAA,CAA2B,CAAA,YAAA,EAAe,IAAI,CAAA,EAAA,CAAI,CAAA;AACxE,MAAA,EAAA,EAAI,SAAA,CAAU,IAAI,OAAO,CAAA;AACzB,MAAA,OAAO,EAAA;AAAA,IACT;AAAA,IAEA,eAAA,GAAwB;AACtB,MAAA,KAAA,MAAW,EAAA,IAAM,KAAK,KAAA,CAAM,gBAAA,CAAiB,QAAQ,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,MAAA,CAAO,OAAO,CAAA;AAAA,IACrF;AAAA,IAEA,KAAA,CAAM,OAAA,GAAwB,EAAC,EAAS;AACtC,MAAA,IAAI,IAAA,CAAK,SAAS,MAAA,EAAW;AAC7B,MAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,MAAA,cAAA,CAAe,KAAK,IAAA,EAAM;AAAA,QACxB,IAAA;AAAA,QACA,UAAA,EAAY,CAAC,IAAA,CAAK,YAAA,CAAa,aAAa,CAAA;AAAA,QAC5C,aAAA,EAAe,IAAA,CAAK,aAAA,KAAkB,IAAA,GAAO,KAAK,SAAA,GAAY,MAAA;AAAA,QAC9D,GAAG;AAAA,OACJ,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAIA,IAAM,UAAA,uBAAiB,GAAA,EAAsC;AAMtD,SAAS,oBAAA,CAAqB,UAAU,iBAAA,EAA6C;AAC1F,EAAA,IAAI,OAAO,cAAA,KAAmB,WAAA,IAAe,OAAO,gBAAgB,WAAA,EAAa;AAC/E,IAAA,MAAM,IAAI,MAAM,8EAA8E,CAAA;AAAA,EAChG;AACA,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,OAAO,CAAA;AAC3C,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,GAAA,CAAI,OAAO,KAAK,kBAAA,EAAmB;AAC3D,EAAA,UAAA,CAAW,GAAA,CAAI,SAAS,IAAI,CAAA;AAC5B,EAAA,cAAA,CAAe,MAAA,CAAO,SAAS,IAAI,CAAA;AACnC,EAAA,OAAO,IAAA;AACT","file":"index.js","sourcesContent":["/**\n * Per-language glyph tables + Unicode cluster composition for the viewer.\n *\n * The akarmatrik system is script-portable: Bengali and Devanagari use the\n * same letters-with-distinct-komal-forms convention (legend: কোমল র—ঋ,\n * কোমল গ—জ্ঞ, কড়ি ম—ক্ষ, কোমল ধ—দ, কোমল ন—ণ), the same আ-কার matra carrier,\n * the same reph-above for taar and understroke for mandra. `en` has no\n * native convention, so it uses S R G M P D N with CSS marks (komal\n * underline, tivra prime, octave dots) and no matra carrier.\n *\n * Unicode hazards owned here (see composeCluster):\n * - mandra can NEVER be a real hasanta: letter + ্ + া is an invalid\n * cluster (virama before vowel sign → dotted circle). It is always a\n * CSS understroke (`sw-mandra`).\n * - ঋ/ऋ (komal re) is an independent VOWEL letter: both র্+ঋ (reph over a\n * vowel) and ঋ+া (vowel sign on a vowel) are invalid clusters. taar-ঋ\n * falls back to a CSS reph (`sw-reph-css`); a matra following ঋ must be\n * emitted as a separate isolated-matra span (`matraSeparate`).\n * - Isolated dependent signs (া, ঃ) need a base: U+00A0 NBSP is the\n * Unicode-sanctioned placeholder base and avoids dotted circles.\n */\nimport type { Octave, SvaraLetter } from '../spec/index.js';\n\nexport type ViewerLang = 'bn' | 'hi' | 'en';\n\ninterface LetterForms {\n shuddha: string;\n /** Distinct komal glyph (bn/hi); absent for en (CSS underline instead). */\n komal?: string;\n /** Distinct tivra glyph (bn/hi ক্ষ/क्ष); absent for en (CSS prime). */\n tivra?: string;\n}\n\nexport const LETTERS: Record<ViewerLang, Record<SvaraLetter, LetterForms>> = {\n bn: {\n s: { shuddha: 'স' },\n r: { shuddha: 'র', komal: 'ঋ' },\n g: { shuddha: 'গ', komal: 'জ্ঞ' },\n m: { shuddha: 'ম', tivra: 'ক্ষ' },\n p: { shuddha: 'প' },\n d: { shuddha: 'ধ', komal: 'দ' },\n n: { shuddha: 'ন', komal: 'ণ' },\n },\n hi: {\n s: { shuddha: 'स' },\n r: { shuddha: 'र', komal: 'ऋ' },\n g: { shuddha: 'ग', komal: 'ज्ञ' },\n m: { shuddha: 'म', tivra: 'क्ष' },\n p: { shuddha: 'प' },\n d: { shuddha: 'ध', komal: 'द' },\n n: { shuddha: 'न', komal: 'ण' },\n },\n en: {\n s: { shuddha: 'S' },\n r: { shuddha: 'R' },\n g: { shuddha: 'G' },\n m: { shuddha: 'M' },\n p: { shuddha: 'P' },\n d: { shuddha: 'D' },\n n: { shuddha: 'N' },\n },\n};\n\n/** Digits 0-9 in the target script (beat labels, avartan). */\nexport const DIGITS: Record<ViewerLang, string> = {\n bn: '০১২৩৪৫৬৭৮৯',\n hi: '०१२३४५६७८९',\n en: '0123456789',\n};\n\n/** The vowel letters whose clusters reject reph and matra (see header). */\nconst VOWEL_LETTER_GLYPHS = new Set(['ঋ', 'ऋ']);\n\nexport interface LangMarks {\n /** আ-কার matra carrier appended to a group-final cluster ('' for en). */\n matra: string;\n /** Melisma / no-new-attack dash before a sustained cluster. */\n hyphen: string;\n /** Lyric continuation mark shown under sustains (the source uses ৹). */\n melisma: string;\n /** ছেদ cut/articulation mark (two stacked rings, ঃ-shaped). */\n cut: string;\n /** Real-text reph prefix for taar ('' for en → CSS dot instead). */\n reph: string;\n}\n\nexport const MARKS: Record<ViewerLang, LangMarks> = {\n bn: { matra: 'া', hyphen: '-', melisma: '৹', cut: 'ঃ', reph: 'র্' },\n hi: { matra: 'ा', hyphen: '-', melisma: '॰', cut: 'ः', reph: 'र्' },\n en: { matra: '', hyphen: '-', melisma: '·', cut: ':', reph: '' },\n};\n\n/** Header labels (NLTR prints নাম / তাল / আবর্তন …). */\nexport const LABELS: Record<\n ViewerLang,\n { title: string; taal: string; raag: string; avartan: string; notationBy: string }\n> = {\n bn: { title: 'নাম', taal: 'তাল', raag: 'রাগ', avartan: 'আবর্তন', notationBy: 'স্বরলিপি' },\n hi: { title: 'नाम', taal: 'ताल', raag: 'राग', avartan: 'आवर्तन', notationBy: 'स्वरलिपि' },\n en: { title: 'Song', taal: 'Taal', raag: 'Raag', avartan: 'Avartan', notationBy: 'Notation' },\n};\n\n/** A composed notation cluster: text plus the CSS classes for marks the\n * text itself cannot carry (mandra understroke, ati dots, en komal/tivra,\n * CSS-reph fallback). */\nexport interface Cluster {\n text: string;\n classes: string[];\n /** Set when the matra could not join the cluster (ঋ/ऋ, or en where the\n * carrier doesn't exist) and must be emitted as an isolated-matra span. */\n matraSeparate: boolean;\n}\n\nexport interface ComposeOptions {\n komal?: boolean;\n tivra?: boolean;\n octave: Octave;\n /** Append the আ-কার matra carrier (group-final notes only). */\n withMatra: boolean;\n lang: ViewerLang;\n}\n\n/**\n * Compose one svara cluster. The single place that knows Unicode\n * composition order: reph? + base + matra?, with the ঋ/mandra/en fallbacks\n * documented in the file header.\n */\nexport function composeCluster(letter: SvaraLetter, opts: ComposeOptions): Cluster {\n const forms = LETTERS[opts.lang][letter];\n const marks = MARKS[opts.lang];\n const classes: string[] = [];\n\n let base = forms.shuddha;\n if (opts.komal) {\n if (forms.komal !== undefined) base = forms.komal;\n else classes.push('sw-komal');\n }\n if (opts.tivra) {\n if (forms.tivra !== undefined) base = forms.tivra;\n else classes.push('sw-tivra');\n }\n const isVowelLetter = VOWEL_LETTER_GLYPHS.has(base);\n\n let text = base;\n switch (opts.octave) {\n case 'taar':\n case 'ati-taar':\n // en has no reph: octave dot above (Bhatkhande-style). bn/hi: real\n // Unicode reph, except over vowel letters (ঋ/ऋ) → CSS reph fallback.\n if (marks.reph === '') classes.push('sw-dot-above');\n else if (isVowelLetter) classes.push('sw-reph-css');\n else text = marks.reph + text;\n if (opts.octave === 'ati-taar') classes.push('sw-ati-taar');\n break;\n case 'mandra':\n case 'ati-mandra':\n // en: octave dot below; bn/hi: hasanta-shaped CSS understroke (a real\n // hasanta before the matra would be an invalid cluster).\n classes.push(marks.reph === '' ? 'sw-dot-below' : 'sw-mandra');\n if (opts.octave === 'ati-mandra') classes.push('sw-ati-mandra');\n break;\n case 'madhyam':\n break;\n }\n\n let matraSeparate = false;\n if (opts.withMatra && marks.matra !== '') {\n if (isVowelLetter) matraSeparate = true;\n else text += marks.matra;\n }\n return { text, classes, matraSeparate };\n}\n\n/** Map ASCII digits in `s` to the target script's digits. */\nexport function localizeDigits(s: string, lang: ViewerLang): string {\n const digits = DIGITS[lang];\n return s.replace(/[0-9]/g, (d) => digits[d.charCodeAt(0) - 48]!);\n}\n","/**\n * Pure spec-JSON → HTML renderer. No DOM, no side effects: usable for SSR\n * (Astro/static sites emit `renderToHtml(doc)` next to a\n * `<style>${SWARALIPI_CSS}</style>`) and unit-testable in plain Node.\n *\n * Layout model (mirrors NLTR's 4-row systems): each spec `Row` becomes one\n * CSS grid with **one column per top-level note** and four grid rows —\n * above-annotations / notation / below (slur arcs, marks) / lyric. Source\n * cells (groups of sub-notes sharing one matra) become column *spans*, so\n * per-sub-note lyric alignment and P2.3's per-note highlight targets fall\n * out of the column model for free.\n *\n * Rendering is spec-driven (semantics, not `raw`): grouping derives from\n * `durationMatra` accumulation so hand-authored documents without `raw`\n * render identically. `raw` is consulted only for (a) raw-only fallback\n * notes (never dropped — dimmed monospace), (b) the ছেদ cut mark and beat\n * labels, whose grammar lives in raw (see src/convert/codec.ts).\n */\nimport type { Meta, Note, Row, Swaralipi } from '../spec/index.js';\nimport {\n composeCluster,\n LABELS,\n localizeDigits,\n MARKS,\n type LangMarks,\n type ViewerLang,\n} from './glyphs.js';\n\nexport interface RenderOptions {\n /** Notation + UI language. Default `bn`. */\n lang?: ViewerLang;\n /** Render the NLTR-style নাম/তাল/আবর্তন header block. Default true. */\n showHeader?: boolean;\n /**\n * Lyric/title transliterator for `hi`/`en` (see loadLyricTransliterator).\n * Without it, non-bn renders keep Bengali lyrics (graceful interim).\n */\n transliterate?: (bengaliText: string) => string;\n}\n\nconst NBSP = '\\u00A0';\nconst EPS = 1e-6;\n\nconst isIntegral = (x: number) => Math.abs(x - Math.round(x)) < EPS;\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/* ------------------------------------------------------------------ */\n/* Cell grouping */\n/* ------------------------------------------------------------------ */\n\nexport interface Cell {\n kind: 'bar' | 'group' | 'raw' | 'carrier';\n /** Index of the cell's first note within the row's notes array. */\n start: number;\n notes: Note[];\n}\n\nconst isPitched = (n: Note) => n.svara !== undefined || n.rest === true || n.sustain === true;\n\n/**\n * The raw text a raw-only note should display, or undefined when there is\n * nothing to show beyond what semantics already render (a bracket-only\n * chunk's raw is fully expressed by its bracket glyphs).\n */\nfunction rawDisplay(note: Note): string | undefined {\n if (note.raw === undefined) return undefined;\n if ((note.brackets?.length ?? 0) > 0 && /^[{}()[\\]]*$/.test(note.raw)) return undefined;\n return note.raw;\n}\n\n/**\n * Group a row's notes into rendered cells using a fractional-duration\n * accumulator (raw-independent — works for hand-authored docs):\n * - bar / raw-only / carrier notes force-close and form singleton cells;\n * - full-matra notes are singleton groups;\n * - fractional notes accumulate until the sum reaches an integer matra\n * boundary (epsilon for 1/3, 0.2 chains), then the group closes.\n * The converter emits k notes × 1/k per source cell, so groups coincide\n * with source cells; an incomplete trailing group still closes at row end\n * (the matra carrier lands on its last note).\n */\nexport function groupRowIntoCells(notes: Note[]): Cell[] {\n const cells: Cell[] = [];\n let cur: Cell | undefined;\n let acc = 0;\n const close = () => {\n if (cur) {\n cells.push(cur);\n cur = undefined;\n }\n acc = 0;\n };\n notes.forEach((note, i) => {\n if (note.bar !== undefined) {\n close();\n cells.push({ kind: 'bar', start: i, notes: [note] });\n return;\n }\n if (!isPitched(note)) {\n close();\n cells.push({ kind: rawDisplay(note) !== undefined ? 'raw' : 'carrier', start: i, notes: [note] });\n return;\n }\n const d = note.durationMatra ?? 1;\n if (isIntegral(d)) {\n close();\n cells.push({ kind: 'group', start: i, notes: [note] });\n return;\n }\n cur ??= { kind: 'group', start: i, notes: [] };\n cur.notes.push(note);\n acc += d;\n if (acc > EPS && isIntegral(acc)) close();\n });\n close();\n return cells;\n}\n\n/* ------------------------------------------------------------------ */\n/* Arc (slur) resolution */\n/* ------------------------------------------------------------------ */\n\nexport interface Arc {\n /** 1-based grid column of the arc's first / last note column. */\n startCol: number;\n endCol: number;\n /** True when the matching end lies on a previous / following system. */\n openLeft: boolean;\n openRight: boolean;\n /** Fill-segments-only row: render a straight underline, no curled ends. */\n line?: boolean;\n}\n\n/** Below-annotation raws that are arc drawing segments (codec known-raw):\n * w/x = left/right curled ends, the rest are straight fill pieces. */\nconst ARC_RAW_RE = /^[wWxXyYjJeEzZ$=_<>`\\\\]+$/;\nconst isArcRaw = (raw: string | undefined): raw is string =>\n raw !== undefined && ARC_RAW_RE.test(raw);\n\n/**\n * Resolve under-arcs for one row. Sources, scanned left→right:\n * - below-annotation raws: `w` opens at its cell's first column, `x`\n * closes at its cell's last column (\"xw\" in one cell = close-then-open);\n * - spec `meend: 'start' | 'end'` fields feed the same scan as synthetic\n * w/x at the note's own column.\n * Unmatched `x` → arc from column 1 with a squared-off (open) left end;\n * unclosed `w` → arc to the last column with an open right end — both\n * match the print's behavior when an arc continues across a system wrap.\n * A row with fill segments but no ends at all renders one straight line.\n */\nexport function resolveArcs(cells: Cell[], noteCount: number): Arc[] {\n const arcs: Arc[] = [];\n let openStart: number | undefined;\n let sawEnds = false;\n const fillCols: number[] = [];\n\n const openAt = (col: number) => {\n sawEnds = true;\n if (openStart === undefined) openStart = col;\n };\n const closeAt = (col: number) => {\n sawEnds = true;\n if (openStart !== undefined) {\n arcs.push({ startCol: openStart, endCol: col, openLeft: false, openRight: false });\n openStart = undefined;\n } else {\n arcs.push({ startCol: 1, endCol: col, openLeft: true, openRight: false });\n }\n };\n\n for (const cell of cells) {\n const firstCol = cell.start + 1;\n const lastCol = cell.start + cell.notes.length;\n cell.notes.forEach((note, j) => {\n const col = cell.start + j + 1;\n if (note.meend === 'start') openAt(col);\n else if (note.meend === 'end') closeAt(col);\n for (const b of note.below ?? []) {\n if (!isArcRaw(b.raw)) continue;\n for (const ch of b.raw) {\n if (ch === 'w' || ch === 'W') openAt(firstCol);\n else if (ch === 'x' || ch === 'X') closeAt(lastCol);\n else fillCols.push(firstCol, lastCol);\n }\n }\n });\n }\n\n if (openStart !== undefined) {\n arcs.push({ startCol: openStart, endCol: Math.max(noteCount, 1), openLeft: false, openRight: true });\n } else if (!sawEnds && fillCols.length > 0) {\n arcs.push({\n startCol: Math.min(...fillCols),\n endCol: Math.max(...fillCols),\n openLeft: true,\n openRight: true,\n line: true,\n });\n }\n return arcs;\n}\n\n/* ------------------------------------------------------------------ */\n/* Raw-derived marks (codec grammar: src/convert/codec.ts) */\n/* ------------------------------------------------------------------ */\n\n/** Count ছেদ cut marks in a decoded chunk's raw — every `i`/`:` in a chunk\n * that decoded to notes is a cut mark per the body grammar. Rendered as\n * group-trailing marks (positional approximation; raw keeps the truth). */\nfunction cutMarkCount(raw: string | undefined): number {\n if (raw === undefined) return 0;\n return (raw.match(/[i:]/g) ?? []).length;\n}\n\n/** Beat-number label (above rows): pure digits + optional sam tick. */\nfunction parseBeatLabel(raw: string): { digits: string; sam: boolean } | undefined {\n const m = raw.match(/^([0-9]{1,2})([fF])?:?$/);\n if (!m) return undefined;\n return { digits: m[1]!, sam: m[2] !== undefined };\n}\n\n/* ------------------------------------------------------------------ */\n/* Note / annotation fragments */\n/* ------------------------------------------------------------------ */\n\ninterface Ctx {\n lang: ViewerLang;\n marks: LangMarks;\n tr: (s: string) => string;\n}\n\nconst BRACKET_GLYPHS = {\n open: { repeat: '{', skip: '(', alt: '[' },\n close: { repeat: '}', skip: ')', alt: ']' },\n} as const;\n\nfunction bracketGlyphs(note: Note, edge: 'open' | 'close'): string {\n if (!note.brackets) return '';\n return note.brackets\n .filter((b) => b.edge === edge)\n .map((b) => `<span class=\"sw-br\">${BRACKET_GLYPHS[edge][b.kind]}</span>`)\n .join('');\n}\n\n/** NBSP-based isolated matra (the sanctioned base for a lone dependent\n * vowel — avoids dotted circles); en has no carrier. */\nfunction isoMatra(ctx: Ctx): string {\n return ctx.marks.matra === '' ? '' : `<span class=\"sw-iso\">${NBSP}${ctx.marks.matra}</span>`;\n}\n\nfunction restGlyph(ctx: Ctx): string {\n // bn/hi: a bare detached matra (legend: hyphen-less মাত্রা sign = rest).\n return ctx.marks.matra === '' ? '<span class=\"sw-iso\">–</span>' : isoMatra(ctx);\n}\n\nfunction renderKan(note: Note, ctx: Ctx): string {\n if (!note.kan) return '';\n const [octave, letter] = note.kan;\n const c = composeCluster(letter, { octave, withMatra: false, lang: ctx.lang });\n return `<span class=\"${['sw-kan', ...c.classes].join(' ')}\">${c.text}</span>`;\n}\n\ninterface PitchedOpts {\n /** This note ends its matra group → carries the আ-কার. */\n withMatra: boolean;\n /** ছেদ cut marks rendered after this (group-final) note. */\n cuts: number;\n}\n\n/** Inner HTML of one pitched/sustain/rest note. Emission order is the\n * Unicode-safe one established in glyphs.ts: brackets, kan, hyphen,\n * cluster(+matra), extra matras, cut marks, closing brackets. */\nfunction renderPitchedInner(note: Note, opts: PitchedOpts, ctx: Ctx): string {\n let inner = bracketGlyphs(note, 'open');\n inner += renderKan(note, ctx);\n if (note.sustain === true) inner += `<span class=\"sw-hy\">${ctx.marks.hyphen}</span>`;\n if (note.svara !== undefined) {\n const [octave, letter] = note.svara;\n const c = composeCluster(letter, {\n komal: note.komal,\n tivra: note.tivra,\n octave,\n withMatra: opts.withMatra,\n lang: ctx.lang,\n });\n inner += `<span class=\"${['sw-cl', ...c.classes].join(' ')}\">${c.text}</span>`;\n if (c.matraSeparate) inner += isoMatra(ctx);\n } else if (note.rest === true) {\n inner += restGlyph(ctx);\n } else if (note.sustain === true && opts.withMatra) {\n inner += isoMatra(ctx);\n }\n if (note.microtone !== undefined) {\n // Exact print glyph for অল্পকোমল/অতিকোমল is an open visual question\n // (fixtures-only feature); a lowered-arrow marker + tooltip for now.\n const mark = note.microtone === 'atikomal' ? '⇊' : '↓';\n inner += `<span class=\"sw-micro\" title=\"${note.microtone}\">${mark}</span>`;\n }\n const d = note.durationMatra ?? 1;\n if (isIntegral(d) && d > 1 + EPS) inner += isoMatra(ctx).repeat(Math.round(d) - 1);\n if (opts.cuts > 0) inner += `<span class=\"sw-cut\">${NBSP}${ctx.marks.cut}</span>`.repeat(opts.cuts);\n inner += bracketGlyphs(note, 'close');\n return inner;\n}\n\nconst BAR_STROKES = { dari: 1, single: 1, double: 2, quad: 4 } as const;\n\nfunction renderBarInner(note: Note): string {\n const strokes = '<i></i>'.repeat(BAR_STROKES[note.bar!]);\n return `${bracketGlyphs(note, 'open')}${strokes}${bracketGlyphs(note, 'close')}`;\n}\n\n/**\n * Render an annotation note list (above/below content) as inline mini\n * notation: beat labels, stop marks, bars, recursive note groups, raw\n * fallback. Reuses the same grouping as the main row.\n */\nfunction renderAnnotation(notes: Note[], ctx: Ctx): string {\n const parts: string[] = [];\n for (const cell of groupRowIntoCells(notes)) {\n if (cell.kind === 'bar') {\n const note = cell.notes[0]!;\n parts.push(`<span class=\"sw-bar sw-bar--${note.bar}\">${renderBarInner(note)}</span>`);\n continue;\n }\n if (cell.kind === 'group') {\n const cuts = cutMarkCount(cell.notes[0]!.raw);\n cell.notes.forEach((note, j) => {\n const last = j === cell.notes.length - 1;\n parts.push(\n `<span class=\"sw-n\">${renderPitchedInner(note, { withMatra: last, cuts: last ? cuts : 0 }, ctx)}</span>`,\n );\n });\n continue;\n }\n const note = cell.notes[0]!;\n const raw = rawDisplay(note);\n if (raw !== undefined) {\n const beat = parseBeatLabel(raw);\n if (beat) {\n parts.push(\n `<span class=\"sw-beat${beat.sam ? ' sw-sam' : ''}\">${localizeDigits(beat.digits, ctx.lang)}</span>`,\n );\n } else if (/^\\|+$/.test(raw)) {\n parts.push(`<span class=\"sw-stop\">${'<i></i>'.repeat(raw.length)}</span>`);\n } else {\n parts.push(`<span class=\"sw-raw\" title=\"${escapeHtml(raw)}\">${escapeHtml(raw)}</span>`);\n }\n continue;\n }\n const brackets = bracketGlyphs(note, 'open') + bracketGlyphs(note, 'close');\n if (brackets !== '') parts.push(`<span class=\"sw-carrier\">${brackets}</span>`);\n }\n return parts.join('');\n}\n\n/** Lyric cell text: the ৹ melisma mark is notation (not language text) —\n * swap it per-lang, transliterating only the linguistic remainder. */\nfunction lyricText(s: string, ctx: Ctx): string {\n return s\n .split('৹')\n .map((part) => (part === '' ? '' : ctx.tr(part)))\n .join(ctx.marks.melisma);\n}\n\n/* ------------------------------------------------------------------ */\n/* Row / header / document */\n/* ------------------------------------------------------------------ */\n\nfunction renderRow(row: Row, partIdx: number, rowIdx: number, ctx: Ctx): string {\n const cells = groupRowIntoCells(row.notes);\n const arcs = resolveArcs(cells, row.notes.length);\n const above: string[] = [];\n const notation: string[] = [];\n const below: string[] = [];\n const lyric: string[] = [];\n\n for (const cell of cells) {\n const firstCol = cell.start + 1;\n const lastCol = cell.start + cell.notes.length;\n const cellSpan =\n lastCol > firstCol ? `grid-column:${firstCol} / ${lastCol + 1}` : `grid-column:${firstCol}`;\n const cuts = cell.kind === 'group' ? cutMarkCount(cell.notes[0]!.raw) : 0;\n\n cell.notes.forEach((note, j) => {\n const col = cell.start + j + 1;\n const path = `${partIdx}.${rowIdx}.${cell.start + j}`;\n const cellEdges = `${j === 0 ? ' sw-cs' : ''}${j === cell.notes.length - 1 ? ' sw-ce' : ''}`;\n\n if (cell.kind === 'bar') {\n notation.push(\n `<span class=\"sw-bar sw-bar--${note.bar}${cellEdges}\" data-note=\"${path}\" style=\"grid-column:${col}\">${renderBarInner(note)}</span>`,\n );\n } else if (cell.kind === 'group') {\n const last = j === cell.notes.length - 1;\n notation.push(\n `<span class=\"sw-n${cellEdges}\" data-note=\"${path}\" style=\"grid-column:${col}\">${renderPitchedInner(note, { withMatra: last, cuts: last ? cuts : 0 }, ctx)}</span>`,\n );\n } else {\n const raw = rawDisplay(note);\n const inner =\n bracketGlyphs(note, 'open') +\n (raw !== undefined\n ? `<span class=\"sw-raw\" title=\"${escapeHtml(raw)}\">${escapeHtml(raw)}</span>`\n : '') +\n bracketGlyphs(note, 'close');\n if (inner !== '') {\n notation.push(\n `<span class=\"sw-n sw-carrier${cellEdges}\" data-note=\"${path}\" style=\"grid-column:${col}\">${inner}</span>`,\n );\n }\n }\n\n if (note.lyric !== undefined) {\n lyric.push(\n `<span class=\"sw-lyr\" style=\"grid-column:${col}\">${escapeHtml(lyricText(note.lyric, ctx))}</span>`,\n );\n }\n if (note.above !== undefined && note.above.length > 0) {\n above.push(`<span class=\"sw-above\" style=\"${cellSpan}\">${renderAnnotation(note.above, ctx)}</span>`);\n }\n const nonArc = (note.below ?? []).filter((b) => !isArcRaw(b.raw));\n if (nonArc.length > 0) {\n below.push(`<span class=\"sw-below\" style=\"${cellSpan}\">${renderAnnotation(nonArc, ctx)}</span>`);\n }\n });\n }\n\n for (const arc of arcs) {\n const cls = [\n 'sw-arc',\n arc.openLeft ? 'sw-arc--openl' : '',\n arc.openRight ? 'sw-arc--openr' : '',\n arc.line === true ? 'sw-arc--line' : '',\n ]\n .filter(Boolean)\n .join(' ');\n below.push(`<span class=\"${cls}\" style=\"grid-column:${arc.startCol} / ${arc.endCol + 1}\"></span>`);\n }\n\n const label =\n row.label !== undefined ? `<span class=\"sw-label\">${escapeHtml(ctx.tr(row.label))}</span>` : '';\n return `<div class=\"sw-row\">${label}<div class=\"sw-grid\">${above.join('')}${notation.join('')}${below.join('')}${lyric.join('')}</div></div>`;\n}\n\nfunction renderHeader(meta: Meta, ctx: Ctx): string {\n const L = LABELS[ctx.lang];\n const rows: string[] = [];\n const add = (label: string, value: string) =>\n rows.push(\n `<div class=\"sw-meta-row\"><span class=\"sw-meta-label\">${escapeHtml(label)}</span><span class=\"sw-meta-value\">${escapeHtml(value)}</span></div>`,\n );\n add(L.title, ctx.tr(meta.title));\n const taal = meta.taalName ?? meta.taal?.id;\n if (taal !== undefined) add(L.taal, ctx.tr(taal));\n if (meta.raag !== undefined) add(L.raag, ctx.tr(meta.raag));\n if (meta.avartan !== undefined) add(L.avartan, localizeDigits(String(meta.avartan), ctx.lang));\n if (meta.notationBy !== undefined) add(L.notationBy, ctx.tr(meta.notationBy));\n return `<header class=\"sw-header\">${rows.join('')}</header>`;\n}\n\n/** Render a complete swaralipi document to an HTML string. Pair with\n * SWARALIPI_CSS (shadow DOM does this automatically; SSR consumers emit a\n * `<style>` themselves). All source text is HTML-escaped. */\nexport function renderToHtml(doc: Swaralipi, opts: RenderOptions = {}): string {\n const lang: ViewerLang = opts.lang ?? 'bn';\n const tr = lang !== 'bn' && opts.transliterate ? opts.transliterate : (s: string) => s;\n const ctx: Ctx = { lang, marks: MARKS[lang], tr };\n\n const out: string[] = [`<div class=\"sw-sheet\" lang=\"${lang}\">`];\n if (opts.showHeader !== false) out.push(renderHeader(doc.meta, ctx));\n doc.parts.forEach((part, p) => {\n out.push('<section class=\"sw-part\">');\n if (part.name !== undefined)\n out.push(`<h3 class=\"sw-part-name\">${escapeHtml(ctx.tr(part.name))}</h3>`);\n part.rows.forEach((row, r) => out.push(renderRow(row, p, r, ctx)));\n out.push('</section>');\n });\n out.push('</div>');\n return out.join('');\n}\n","/**\n * Encapsulated stylesheet for the viewer. Injected into the\n * `<swaralipi-sheet>` shadow root automatically; SSR consumers emit it\n * themselves: `<style>${SWARALIPI_CSS}</style>` next to `renderToHtml()`.\n *\n * Theming hooks (CSS custom properties, all optional):\n * --sw-font font stack (default: Noto Sans Bengali + system Bengali)\n * --sw-size base font size\n * --sw-cell-gap horizontal gap between source cells\n * --sw-hl player-highlight background (P2.3)\n * --sw-rule header rule / muted line color\n *\n * All ink uses `currentColor`, so the sheet follows the host's text color\n * (dark mode included). Octave marks that Unicode cannot express in a valid\n * cluster (mandra understroke, ati dots, ঋ-reph, en octave dots) are drawn\n * with positioned pseudo-elements; offsets are em-based and tuned against\n * the NLTR reference rendering of song 4270.\n */\nexport const SWARALIPI_CSS = `\n.sw-sheet {\n font-family: var(--sw-font, 'Noto Sans Bengali', 'Kohinoor Bangla', 'Bangla Sangam MN', 'Nirmala UI', 'Noto Sans Devanagari', sans-serif);\n font-size: var(--sw-size, 1.125rem);\n line-height: 1.5;\n}\n\n/* ---- header ---- */\n.sw-header {\n margin: 0 0 0.75em;\n padding: 0 0 0.5em;\n border-bottom: 1px solid var(--sw-rule, rgba(128, 128, 128, 0.35));\n font-size: 0.95em;\n}\n.sw-meta-row { display: flex; gap: 0.3em; }\n.sw-meta-label { font-weight: 600; min-width: 4.5em; }\n.sw-meta-label::after { content: ':'; font-weight: 400; margin-left: 0.15em; }\n\n.sw-part-name { font-size: 0.85em; font-weight: 600; margin: 1em 0 0.2em; opacity: 0.85; }\n\n/* ---- row grid: above / notation / below(arcs) / lyric ---- */\n.sw-row {\n display: flex;\n align-items: flex-start;\n overflow-x: auto;\n padding: 0.4em 0;\n}\n.sw-label { flex: none; margin-right: 0.8em; font-weight: 600; }\n.sw-grid {\n display: grid;\n grid-template-rows: auto auto auto auto;\n grid-auto-columns: max-content;\n align-items: end;\n}\n.sw-above { grid-row: 1; font-size: 0.62em; justify-self: start; white-space: nowrap; padding-left: 0.2em; }\n.sw-n { grid-row: 2; white-space: nowrap; }\n.sw-arc,\n.sw-below { grid-row: 3; }\n.sw-lyr { grid-row: 4; white-space: nowrap; padding-top: 0.3em; }\n.sw-below { font-size: 0.62em; justify-self: start; white-space: nowrap; padding-left: 0.2em; }\n\n/* inter-cell gap as padding on each cell's first notation item, so arcs\n * and above-spans crossing cells stay continuous */\n.sw-cs { padding-left: var(--sw-cell-gap, 0.55em); }\n\n/* ---- notation clusters & marks ---- */\n.sw-cl { position: relative; display: inline-block; }\n\n/* mandra: hasanta-shaped understroke (a real ্ before া is invalid Unicode) */\n.sw-mandra::after {\n content: '';\n position: absolute;\n left: 0.1em;\n bottom: -0.08em;\n width: 0.45em;\n height: 0.09em;\n background: currentColor;\n transform: rotate(-32deg);\n}\n/* ati-mandra: an extra dot below */\n.sw-ati-mandra::before {\n content: '';\n position: absolute;\n left: 0.25em;\n bottom: -0.35em;\n width: 0.16em;\n height: 0.16em;\n border-radius: 50%;\n background: currentColor;\n}\n/* ati-taar (reph already in the text): an extra dot above */\n.sw-ati-taar::before {\n content: '';\n position: absolute;\n left: 0.25em;\n top: -0.3em;\n width: 0.16em;\n height: 0.16em;\n border-radius: 50%;\n background: currentColor;\n}\n/* CSS reph fallback for vowel letters ঋ/ऋ that reject a real reph */\n.sw-reph-css::before {\n content: '';\n position: absolute;\n top: -0.12em;\n left: 0.12em;\n width: 0.3em;\n height: 0.3em;\n border: 0.09em solid currentColor;\n border-right: none;\n border-bottom: none;\n border-top-left-radius: 0.3em;\n}\n/* en octave dots (Bhatkhande-style) */\n.sw-dot-above::before,\n.sw-dot-below::before {\n content: '';\n position: absolute;\n left: 50%;\n margin-left: -0.07em;\n width: 0.14em;\n height: 0.14em;\n border-radius: 50%;\n background: currentColor;\n}\n.sw-dot-above::before { top: -0.25em; }\n.sw-dot-below::before { bottom: -0.2em; }\n.sw-ati-taar.sw-dot-above::before,\n.sw-ati-mandra.sw-dot-below::before { box-shadow: 0.24em 0 0 currentColor; margin-left: -0.19em; }\n/* en accidentals (bn/hi use distinct letters instead) */\n.sw-komal { text-decoration: underline; text-underline-offset: 0.18em; }\n.sw-tivra::after { content: '\\\\2032'; font-size: 0.7em; vertical-align: super; }\n\n/* kan grace: small raised cluster left of the main note */\n.sw-kan {\n position: relative;\n display: inline-block;\n font-size: 0.58em;\n vertical-align: 0.75em;\n margin-right: 0.08em;\n}\n\n.sw-hy { padding-right: 0.02em; }\n.sw-iso { display: inline-block; margin-left: -0.18em; }\n.sw-cut { font-size: 0.8em; display: inline-block; margin-left: -0.15em; }\n.sw-br { opacity: 0.8; padding: 0 0.06em; }\n.sw-micro { font-size: 0.6em; vertical-align: super; opacity: 0.8; }\n\n/* raw fallback: never dropped, visibly non-notation */\n.sw-raw {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72em;\n opacity: 0.55;\n}\n\n/* ---- bars: dari (thin) and danda strokes, notation-row height ---- */\n/* horizontal gap before a bar comes from its own .sw-cs padding-left —\n * never reset it with a padding shorthand here */\n.sw-bar {\n grid-row: 2;\n align-self: stretch;\n display: inline-flex;\n align-items: stretch;\n gap: 0.16em;\n padding-right: 0.1em;\n}\n.sw-bar i { display: inline-block; width: 0.14em; min-height: 1.25em; background: currentColor; }\n.sw-bar--dari i { width: 0.05em; opacity: 0.9; }\n.sw-bar--quad i:nth-child(3) { margin-left: 0.18em; }\n.sw-above .sw-bar, .sw-below .sw-bar { display: inline-flex; vertical-align: baseline; }\n.sw-above .sw-bar i, .sw-below .sw-bar i { min-height: 1em; }\n\n/* ---- under-arcs (slurs decoded from w/x segments and meend) ---- */\n.sw-arc {\n align-self: start;\n height: 0.4em;\n margin: 0.05em 0.25em 0;\n border: 0.09em solid currentColor;\n border-top: none;\n border-bottom-left-radius: 0.6em;\n border-bottom-right-radius: 0.6em;\n opacity: 0.85;\n}\n.sw-arc--openl { border-left: none; border-bottom-left-radius: 0; }\n.sw-arc--openr { border-right: none; border-bottom-right-radius: 0; }\n.sw-arc--line { border-left: none; border-right: none; border-radius: 0; height: 0.22em; }\n\n/* ---- annotation content ---- */\n.sw-beat { position: relative; display: inline-block; padding: 0 0.1em; }\n.sw-sam::after {\n content: '';\n position: absolute;\n top: -0.45em;\n left: 50%;\n width: 0.1em;\n height: 0.4em;\n background: currentColor;\n transform: rotate(14deg);\n}\n.sw-stop i {\n display: inline-block;\n width: 0.07em;\n height: 1em;\n margin: 0 0.07em;\n background: currentColor;\n vertical-align: text-bottom;\n}\n\n/* ---- player sync (P2.3) ---- */\n.sw-hl { background: var(--sw-hl, rgba(255, 196, 64, 0.45)); border-radius: 0.15em; }\n\n/* ---- element error box ---- */\n.sw-error {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n padding: 0.6em 0.8em;\n border: 1px solid rgba(200, 64, 64, 0.6);\n border-radius: 0.3em;\n color: #b33;\n background: rgba(200, 64, 64, 0.08);\n}\n`;\n\n/**\n * Print stylesheet — pair with `SWARALIPI_CSS` (renderPrintDocument injects\n * both). Gated on `@media print`, so it also works if a consumer drops it into\n * a page and prints that page directly.\n *\n * - `print-color-adjust: exact` forces the marks that are drawn as tiny\n * `background: currentColor` pseudo-elements (octave dots, arcs, danda\n * strokes, sam tick) to actually print — browsers drop backgrounds by\n * default, which would silently strip the notation's diacritics.\n * - rows are un-clipped (no scrollbar on paper) and kept whole across page\n * breaks; part headings stay with their first row.\n */\nexport const SWARALIPI_PRINT_CSS = `\n@page { margin: 16mm; }\n@media print {\n .sw-sheet { -webkit-print-color-adjust: exact; print-color-adjust: exact; color: #000; }\n .sw-row { overflow: visible !important; break-inside: avoid; page-break-inside: avoid; }\n .sw-part { break-inside: auto; }\n .sw-part-name, .sw-header { break-after: avoid-page; page-break-after: avoid; }\n .sw-hl { background: none !important; }\n}\n`;\n","/**\n * Print / \"Save as PDF\" support.\n *\n * High-fidelity PDF of আকারমাত্রিক notation can only come from the browser's\n * own print engine — it reuses the exact HarfBuzz shaping (reph, conjuncts,\n * matra) and the CSS-drawn marks (octave dots, slur arcs, danda strokes) that\n * the viewer renders on screen. Rasterizers (html2canvas) and PDF-primitive\n * libraries (jsPDF/pdfmake) have no Indic shaping and drop pseudo-element\n * marks, so we deliberately avoid them.\n *\n * `renderPrintDocument` builds a self-contained HTML page from the pure\n * `renderToHtml` + `SWARALIPI_CSS` (so it sidesteps the shadow-DOM \"print drops\n * encapsulated styles\" gotcha); `printSwaralipi` prints it via a hidden iframe.\n * Both reuse the same renderer as the viewer, so the PDF matches the screen.\n */\nimport type { Swaralipi } from '../spec/index.js';\nimport type { ViewerLang } from './glyphs.js';\nimport { renderToHtml } from './render.js';\nimport { SWARALIPI_CSS, SWARALIPI_PRINT_CSS } from './styles.js';\n\nexport interface PrintOptions {\n /** Notation + UI language. Default `bn`. */\n lang?: ViewerLang;\n /** Render the নাম/তাল header block. Default true. */\n showHeader?: boolean;\n /** Lyric/title transliterator for hi/en (see loadLyricTransliterator). */\n transliterate?: (bengaliText: string) => string;\n /** Document `<title>` — the browser's default \"Save as PDF\" filename.\n * Defaults to the document's `meta.title`. */\n title?: string;\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/**\n * Build a complete, standalone HTML document for printing a swaralipi sheet:\n * the rendered notation plus `SWARALIPI_CSS` and the print stylesheet, on a\n * white page. Usable for a hidden-iframe print, a new browser tab, or\n * server-side headless-Chrome PDF generation.\n */\nexport function renderPrintDocument(doc: Swaralipi, opts: PrintOptions = {}): string {\n const lang: ViewerLang = opts.lang ?? 'bn';\n const tr = lang !== 'bn' && opts.transliterate ? opts.transliterate : (s: string) => s;\n const title = opts.title ?? tr(doc.meta.title);\n const body = renderToHtml(doc, {\n lang,\n showHeader: opts.showHeader,\n transliterate: opts.transliterate,\n });\n return `<!doctype html>\n<html lang=\"${escapeHtml(lang)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeHtml(title)}</title>\n<style>\n${SWARALIPI_CSS}\n${SWARALIPI_PRINT_CSS}\nhtml, body { margin: 0; }\nbody { color: #111; background: #fff; padding: 16px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }\n.sw-sheet { max-width: 100%; }\n</style>\n</head>\n<body>${body}</body>\n</html>`;\n}\n\n/**\n * Open the browser print dialog for a swaralipi document (the user picks a\n * printer or \"Save as PDF\"). Renders into an off-screen iframe so it prints\n * only the sheet — independent of the host page's chrome and CSS — then cleans\n * up. Browser-only; throws in a non-DOM environment (use renderPrintDocument\n * for SSR / headless-Chrome instead).\n */\nexport function printSwaralipi(doc: Swaralipi, opts: PrintOptions = {}): void {\n if (typeof document === 'undefined') {\n throw new Error('printSwaralipi requires a DOM; use renderPrintDocument() for server-side PDF');\n }\n const html = renderPrintDocument(doc, opts);\n const iframe = document.createElement('iframe');\n iframe.setAttribute('aria-hidden', 'true');\n // off-screen but rendered (display:none iframes print blank); a page-ish\n // width so rows lay out before the print stylesheet takes over.\n iframe.style.cssText = 'position:fixed; left:-10000px; top:0; width:800px; height:600px; border:0;';\n\n iframe.onload = () => {\n const win = iframe.contentWindow;\n if (win === null) {\n iframe.remove();\n return;\n }\n const cleanup = () => setTimeout(() => iframe.remove(), 1000);\n win.addEventListener('afterprint', cleanup, { once: true });\n const go = () => {\n try {\n win.focus();\n win.print();\n } catch {\n /* printing unavailable (e.g. headless) — leave cleanup to afterprint */\n }\n };\n // wait for fonts so the first print isn't unstyled\n const fonts = iframe.contentDocument?.fonts;\n if (fonts?.ready) void fonts.ready.then(go).catch(go);\n else setTimeout(go, 250);\n };\n\n iframe.srcdoc = html;\n document.body.appendChild(iframe);\n}\n","/**\n * Lazy lyric transliteration for `hi` / `en` renders.\n *\n * Swara glyphs come from the sync tables in glyphs.ts; only *linguistic*\n * text (lyrics, title, names) needs transliteration, so sanscript loads via\n * dynamic import — `bn`-only consumers (and their bundles) never touch it.\n */\nimport type { ViewerLang } from './glyphs.js';\n\nexport type Transliterator = (bengaliText: string) => string;\n\nconst TARGET: Record<Exclude<ViewerLang, 'bn'>, string> = {\n hi: 'devanagari',\n en: 'iast',\n};\n\n/**\n * Load a Bengali→target transliterator for the given viewer language.\n * Returns undefined for `bn` (no work to do). Pass the result as\n * `RenderOptions.transliterate`; the `<swaralipi-sheet>` element wires this\n * automatically when its `lang` attribute changes.\n */\nexport async function loadLyricTransliterator(lang: ViewerLang): Promise<Transliterator | undefined> {\n if (lang === 'bn') return undefined;\n const mod = (await import('@indic-transliteration/sanscript')) as {\n default?: { t(text: string, from: string, to: string): string };\n t?(text: string, from: string, to: string): string;\n };\n const sanscript = mod.default ?? mod;\n const target = TARGET[lang];\n return (text) => sanscript.t!(text, 'bengali', target);\n}\n","/**\n * The `<swaralipi-sheet>` custom element — a thin shadow-DOM shell around\n * the pure renderer.\n *\n * The element class is created lazily inside defineSwaralipiSheet():\n * a top-level `extends HTMLElement` would throw on import in Node, and this\n * module must stay importable for SSR (where only renderToHtml is used).\n * Nothing registers automatically — call defineSwaralipiSheet() once.\n *\n * Validation is off by default (converter output is pre-validated); setting\n * `validate = true` parses documents against the Zod schema via a dynamic\n * import, so the viewer bundle stays free of bare runtime imports (it can\n * be loaded directly from dist/ in a browser without a bundler).\n */\nimport type { Swaralipi } from '../spec/index.js';\nimport { renderToHtml } from './render.js';\nimport { SWARALIPI_CSS } from './styles.js';\nimport { printSwaralipi, type PrintOptions } from './print.js';\nimport { loadLyricTransliterator, type Transliterator } from './transliterate.js';\nimport type { ViewerLang } from './glyphs.js';\n\nexport interface SwaralipiSheetElement extends HTMLElement {\n /** The document to render (property only; renders on assignment). */\n doc: Swaralipi | undefined;\n /** Parse documents against the spec schema before rendering. */\n validate: boolean;\n /** Add the player-highlight class to the note at \"part.row.note\". */\n highlight(path: string): HTMLElement | null;\n clearHighlights(): void;\n /** Open the print dialog (→ \"Save as PDF\") for the current document. */\n print(options?: PrintOptions): void;\n}\n\nconst LANGS: ReadonlySet<string> = new Set(['bn', 'hi', 'en']);\n\nlet sharedSheet: CSSStyleSheet | undefined;\n\nfunction createElementClass(): CustomElementConstructor {\n return class SwaralipiSheet extends HTMLElement implements SwaralipiSheetElement {\n static observedAttributes = ['src', 'lang', 'hide-header'];\n\n #doc: Swaralipi | undefined;\n #root: ShadowRoot;\n #adopted = false;\n #abort: AbortController | undefined;\n #translit: Transliterator | undefined;\n #translitLang: ViewerLang | undefined;\n validate = false;\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n if (\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype &&\n 'adoptedStyleSheets' in this.#root\n ) {\n if (!sharedSheet) {\n sharedSheet = new CSSStyleSheet();\n sharedSheet.replaceSync(SWARALIPI_CSS);\n }\n this.#root.adoptedStyleSheets = [...this.#root.adoptedStyleSheets, sharedSheet];\n this.#adopted = true;\n }\n }\n\n get doc(): Swaralipi | undefined {\n return this.#doc;\n }\n\n set doc(value: Swaralipi | undefined) {\n this.#doc = value;\n if (value !== undefined && this.validate) {\n void import('../spec/index.js')\n .then(({ safeParseSwaralipi }) => {\n const result = safeParseSwaralipi(value);\n if (!result.success) this.#renderError(result.error.message);\n })\n .catch(() => undefined);\n }\n this.#render();\n }\n\n get #lang(): ViewerLang {\n const attr = this.getAttribute('lang');\n return attr !== null && LANGS.has(attr) ? (attr as ViewerLang) : 'bn';\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (name === 'src') {\n if (newValue !== null) void this.#load(newValue);\n return;\n }\n if (name === 'lang') this.#ensureTransliterator();\n this.#render();\n }\n\n connectedCallback(): void {\n this.#ensureTransliterator();\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.#abort?.abort();\n }\n\n async #load(url: string): Promise<void> {\n this.#abort?.abort();\n const abort = new AbortController();\n this.#abort = abort;\n try {\n const res = await fetch(url, { signal: abort.signal });\n if (!res.ok) throw new Error(`fetch ${url}: HTTP ${res.status}`);\n this.doc = (await res.json()) as Swaralipi;\n } catch (err) {\n if (abort.signal.aborted) return;\n this.#renderError(err instanceof Error ? err.message : String(err));\n this.dispatchEvent(new ErrorEvent('error', { error: err, message: String(err) }));\n }\n }\n\n /** Load (once per lang) the lyric transliterator, then re-render. */\n #ensureTransliterator(): void {\n const lang = this.#lang;\n if (lang === 'bn' || this.#translitLang === lang) return;\n void loadLyricTransliterator(lang)\n .then((t) => {\n if (t === undefined || this.#lang !== lang) return;\n this.#translit = t;\n this.#translitLang = lang;\n this.#render();\n })\n .catch(() => undefined); // graceful: lyrics stay Bengali\n }\n\n #styleFallback(): string {\n return this.#adopted ? '' : `<style>${SWARALIPI_CSS}</style>`;\n }\n\n #render(): void {\n if (this.#doc === undefined) {\n this.#root.innerHTML = this.#styleFallback();\n return;\n }\n const lang = this.#lang;\n const html = renderToHtml(this.#doc, {\n lang,\n showHeader: !this.hasAttribute('hide-header'),\n transliterate: this.#translitLang === lang ? this.#translit : undefined,\n });\n this.#root.innerHTML = this.#styleFallback() + html;\n }\n\n #renderError(message: string): void {\n const div = document.createElement('div');\n div.className = 'sw-error';\n div.textContent = message;\n this.#root.innerHTML = this.#styleFallback();\n this.#root.appendChild(div);\n }\n\n highlight(path: string): HTMLElement | null {\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(path)) return null;\n const el = this.#root.querySelector<HTMLElement>(`[data-note=\"${path}\"]`);\n el?.classList.add('sw-hl');\n return el;\n }\n\n clearHighlights(): void {\n for (const el of this.#root.querySelectorAll('.sw-hl')) el.classList.remove('sw-hl');\n }\n\n print(options: PrintOptions = {}): void {\n if (this.#doc === undefined) return;\n const lang = this.#lang;\n printSwaralipi(this.#doc, {\n lang,\n showHeader: !this.hasAttribute('hide-header'),\n transliterate: this.#translitLang === lang ? this.#translit : undefined,\n ...options,\n });\n }\n };\n}\n\n/** Per-tag constructors: a custom-element class can only be registered\n * under one name, so each tag gets its own. */\nconst registered = new Map<string, CustomElementConstructor>();\n\n/**\n * Register `<swaralipi-sheet>` (or a custom tag name). Idempotent. Throws\n * outside a DOM environment — use renderToHtml() for SSR.\n */\nexport function defineSwaralipiSheet(tagName = 'swaralipi-sheet'): CustomElementConstructor {\n if (typeof customElements === 'undefined' || typeof HTMLElement === 'undefined') {\n throw new Error('swaralipi-sheet requires a DOM; use renderToHtml() for server-side rendering');\n }\n const existing = customElements.get(tagName);\n if (existing) return existing;\n const ctor = registered.get(tagName) ?? createElementClass();\n registered.set(tagName, ctor);\n customElements.define(tagName, ctor);\n return ctor;\n}\n"]}
1
+ {"version":3,"sources":["../../src/viewer/glyphs.ts","../../src/viewer/render.ts","../../src/viewer/styles.ts","../../src/viewer/print.ts","../../src/viewer/transliterate.ts","../../src/viewer/element.ts"],"names":["note","escapeHtml"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Per-language notation encoding for the viewer.\n *\n * Every language renders its notation through a dedicated, purpose-built\n * font whose glyphs ARE the akarmatrik/Bhatkhande marks — so composeCluster\n * emits that font's ASCII encoding and the font does all the hard work\n * (komal/tivra forms, octave reph/dots, matra). This is why the viewer no\n * longer touches Unicode cluster composition at all: the old reph-over-\n * vowel, hasanta-before-matra and dotted-circle hazards simply don't exist\n * when the font supplies precomposed glyphs keyed by plain ASCII.\n *\n * - bn → NLTR's **Swarabitan** (the akarmatrik font this project decodes).\n * Letters s r g m p q n = স র গ ম প ধ ন (q=ধ); komal v t d u = ঋ জ্ঞ দ ণ;\n * tivra ma k = the authentic কড়ি-ম conjunct (ম-based — has NO Unicode\n * form, which is what forced this whole approach); suffix f = taar reph,\n * h = mandra hasanta; trailing a = the আ-কার matra carrier. See codec.ts.\n * - hi/en → **Ome Bhatkhande** Hindi/English (SIL OFL 1.1, © Omenad —\n * github.com/omenad/fonts). Same clean keymap for both: lowercase\n * s r g m p d n = the seven shuddha swaras, uppercase R G M D N = komal\n * Re/Ga, tivra Ma, komal Dha/Ni; octave suffix u/l = taar/mandra dot,\n * U/L = ati (two dots). Bhatkhande has no আ-কার, so no matra is appended.\n *\n * The font is applied by CSS keyed on `.sw-sheet`'s `lang` (see styles.ts);\n * composeCluster only chooses the ASCII. The single residual CSS mark is the\n * bn ati-octave extra dot (Swarabitan's f/h are single reph/hasanta only).\n */\nimport type { Octave, SvaraLetter } from '../spec/index.js';\n\nexport type ViewerLang = 'bn' | 'hi' | 'en';\n\n/** bn Swarabitan glyph keys (shuddha / komal / tivra). Missing komal/tivra\n * entries fall back to the shuddha key (those alterations don't occur). */\nconst SWARABITAN_SHUDDHA: Record<SvaraLetter, string> = {\n s: 's', r: 'r', g: 'g', m: 'm', p: 'p', d: 'q', n: 'n', // q = ধ\n};\nconst SWARABITAN_KOMAL: Partial<Record<SvaraLetter, string>> = {\n r: 'v', g: 't', d: 'd', n: 'u', // ঋ জ্ঞ দ ণ\n};\nconst SWARABITAN_TIVRA: Partial<Record<SvaraLetter, string>> = { m: 'k' }; // কড়ি-ম\n\n/** hi/en Ome Bhatkhande octave suffix (u/l single dot, U/L two dots). */\nconst BHATKHANDE_OCTAVE: Record<Octave, string> = {\n madhyam: '',\n taar: 'u',\n mandra: 'l',\n 'ati-taar': 'U',\n 'ati-mandra': 'L',\n};\n/** Letters that have a komal (flat) glyph in Bhatkhande = uppercase key. */\nconst BHATKHANDE_HAS_KOMAL = new Set<SvaraLetter>(['r', 'g', 'd', 'n']);\n\n/** Digits 0-9 in the target script (beat labels, avartan). */\nexport const DIGITS: Record<ViewerLang, string> = {\n bn: '০১২৩৪৫৬৭৮৯',\n hi: '०१२३४५६७८९',\n en: '0123456789',\n};\n\nexport interface LangMarks {\n /** Melisma / no-new-attack dash before a sustained cluster. */\n hyphen: string;\n /** Lyric continuation mark shown under sustains (the source uses ৹). */\n melisma: string;\n /** ছেদ cut/articulation mark (two stacked rings, ঃ-shaped). */\n cut: string;\n}\n\nexport const MARKS: Record<ViewerLang, LangMarks> = {\n bn: { hyphen: '-', melisma: '৹', cut: 'ঃ' },\n hi: { hyphen: '-', melisma: '॰', cut: 'ः' },\n en: { hyphen: '-', melisma: '·', cut: ':' },\n};\n\n/** Header labels (NLTR prints নাম / তাল / আবর্তন …). */\nexport const LABELS: Record<\n ViewerLang,\n { title: string; taal: string; raag: string; avartan: string; notationBy: string }\n> = {\n bn: { title: 'নাম', taal: 'তাল', raag: 'রাগ', avartan: 'আবর্তন', notationBy: 'স্বরলিপি' },\n hi: { title: 'नाम', taal: 'ताल', raag: 'राग', avartan: 'आवर्तन', notationBy: 'स्वरलिपि' },\n en: { title: 'Song', taal: 'Taal', raag: 'Raag', avartan: 'Avartan', notationBy: 'Notation' },\n};\n\n/** A composed notation cluster: the font's ASCII text plus any residual CSS\n * classes the font itself cannot express (only the bn ati-octave dot). */\nexport interface Cluster {\n text: string;\n classes: string[];\n}\n\nexport interface ComposeOptions {\n komal?: boolean;\n tivra?: boolean;\n octave: Octave;\n /** Append the আ-কার matra carrier (bn group-final notes only). */\n withMatra: boolean;\n lang: ViewerLang;\n}\n\n/**\n * Compose one svara into its notation-font ASCII. bn = Swarabitan\n * (letter + f/h octave + a matra); hi/en = Ome Bhatkhande (case-encoded\n * letter + u/l/U/L octave, no matra). The font renders the actual glyph.\n */\nexport function composeCluster(letter: SvaraLetter, opts: ComposeOptions): Cluster {\n const classes: string[] = [];\n\n if (opts.lang === 'bn') {\n let text =\n (opts.tivra && SWARABITAN_TIVRA[letter]) ||\n (opts.komal && SWARABITAN_KOMAL[letter]) ||\n SWARABITAN_SHUDDHA[letter];\n if (opts.octave === 'taar' || opts.octave === 'ati-taar') text += 'f';\n else if (opts.octave === 'mandra' || opts.octave === 'ati-mandra') text += 'h';\n // Swarabitan's f/h are single reph/hasanta; ati adds a CSS extra dot.\n if (opts.octave === 'ati-taar') classes.push('sw-ati-taar');\n if (opts.octave === 'ati-mandra') classes.push('sw-ati-mandra');\n if (opts.withMatra) text += 'a';\n return { text, classes };\n }\n\n // hi / en — Ome Bhatkhande.\n let base: string = letter;\n if (opts.tivra && letter === 'm') base = 'M';\n else if (opts.komal && BHATKHANDE_HAS_KOMAL.has(letter)) base = base.toUpperCase();\n return { text: base + BHATKHANDE_OCTAVE[opts.octave], classes };\n}\n\n/** Map ASCII digits in `s` to the target script's digits. */\nexport function localizeDigits(s: string, lang: ViewerLang): string {\n const digits = DIGITS[lang];\n return s.replace(/[0-9]/g, (d) => digits[d.charCodeAt(0) - 48]!);\n}\n","/**\n * Pure spec-JSON → HTML renderer. No DOM, no side effects: usable for SSR\n * (Astro/static sites emit `renderToHtml(doc)` next to a\n * `<style>${SWARALIPI_CSS}</style>`) and unit-testable in plain Node.\n *\n * Layout model (mirrors NLTR's 4-row systems): each spec `Row` becomes one\n * CSS grid with **one column per top-level note** and four grid rows —\n * above-annotations / notation / below (slur arcs, marks) / lyric. Source\n * cells (groups of sub-notes sharing one matra) become column *spans*, so\n * per-sub-note lyric alignment and P2.3's per-note highlight targets fall\n * out of the column model for free.\n *\n * Rendering is spec-driven (semantics, not `raw`): grouping derives from\n * `durationMatra` accumulation so hand-authored documents without `raw`\n * render identically. `raw` is consulted only for (a) raw-only fallback\n * notes (never dropped — dimmed, in Swarabitan when loaded), (b) the ছেদ\n * cut mark and beat labels, whose grammar lives in raw (see codec.ts).\n */\nimport type { Meta, Note, Row, Swaralipi } from '../spec/index.js';\nimport {\n composeCluster,\n LABELS,\n localizeDigits,\n MARKS,\n type LangMarks,\n type ViewerLang,\n} from './glyphs.js';\n\nexport interface RenderOptions {\n /** Notation + UI language. Default `bn`. */\n lang?: ViewerLang;\n /** Render the NLTR-style নাম/তাল/আবর্তন header block. Default true. */\n showHeader?: boolean;\n /**\n * Lyric/title transliterator for `hi`/`en` (see loadLyricTransliterator).\n * Without it, non-bn renders keep Bengali lyrics (graceful interim).\n */\n transliterate?: (bengaliText: string) => string;\n}\n\nconst NBSP = '\\u00A0';\nconst EPS = 1e-6;\n\nconst isIntegral = (x: number) => Math.abs(x - Math.round(x)) < EPS;\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/* ------------------------------------------------------------------ */\n/* Cell grouping */\n/* ------------------------------------------------------------------ */\n\nexport interface Cell {\n kind: 'bar' | 'group' | 'raw' | 'carrier';\n /** Index of the cell's first note within the row's notes array. */\n start: number;\n notes: Note[];\n}\n\nconst isPitched = (n: Note) => n.svara !== undefined || n.rest === true || n.sustain === true;\n\n/**\n * The raw text a raw-only note should display, or undefined when there is\n * nothing to show beyond what semantics already render (a bracket-only\n * chunk's raw is fully expressed by its bracket glyphs).\n */\nfunction rawDisplay(note: Note): string | undefined {\n if (note.raw === undefined) return undefined;\n if ((note.brackets?.length ?? 0) > 0 && /^[{}()[\\]]*$/.test(note.raw)) return undefined;\n return note.raw;\n}\n\n/**\n * Group a row's notes into rendered cells using a fractional-duration\n * accumulator (raw-independent — works for hand-authored docs):\n * - bar / raw-only / carrier notes force-close and form singleton cells;\n * - full-matra notes are singleton groups;\n * - fractional notes accumulate until the sum reaches an integer matra\n * boundary (epsilon for 1/3, 0.2 chains), then the group closes.\n * The converter emits k notes × 1/k per source cell, so groups coincide\n * with source cells; an incomplete trailing group still closes at row end\n * (the matra carrier lands on its last note).\n */\nexport function groupRowIntoCells(notes: Note[]): Cell[] {\n const cells: Cell[] = [];\n let cur: Cell | undefined;\n let acc = 0;\n const close = () => {\n if (cur) {\n cells.push(cur);\n cur = undefined;\n }\n acc = 0;\n };\n notes.forEach((note, i) => {\n if (note.bar !== undefined) {\n close();\n cells.push({ kind: 'bar', start: i, notes: [note] });\n return;\n }\n if (!isPitched(note)) {\n close();\n cells.push({ kind: rawDisplay(note) !== undefined ? 'raw' : 'carrier', start: i, notes: [note] });\n return;\n }\n const d = note.durationMatra ?? 1;\n if (isIntegral(d)) {\n close();\n cells.push({ kind: 'group', start: i, notes: [note] });\n return;\n }\n cur ??= { kind: 'group', start: i, notes: [] };\n cur.notes.push(note);\n acc += d;\n if (acc > EPS && isIntegral(acc)) close();\n });\n close();\n return cells;\n}\n\n/* ------------------------------------------------------------------ */\n/* Arc (slur) resolution */\n/* ------------------------------------------------------------------ */\n\nexport interface Arc {\n /** 1-based grid column of the arc's first / last note column. */\n startCol: number;\n endCol: number;\n /** True when the matching end lies on a previous / following system. */\n openLeft: boolean;\n openRight: boolean;\n /** Fill-segments-only row: render a straight underline, no curled ends. */\n line?: boolean;\n}\n\n/** Below-annotation raws that are arc drawing segments (codec known-raw):\n * w/x = left/right curled ends, the rest are straight fill pieces. */\nconst ARC_RAW_RE = /^[wWxXyYjJeEzZ$=_<>`\\\\]+$/;\nconst isArcRaw = (raw: string | undefined): raw is string =>\n raw !== undefined && ARC_RAW_RE.test(raw);\n\n/**\n * Resolve under-arcs for one row. Sources, scanned left→right:\n * - below-annotation raws: `w` opens at its cell's first column, `x`\n * closes at its cell's last column (\"xw\" in one cell = close-then-open);\n * - spec `meend: 'start' | 'end'` fields feed the same scan as synthetic\n * w/x at the note's own column.\n * Unmatched `x` → arc from column 1 with a squared-off (open) left end;\n * unclosed `w` → arc to the last column with an open right end — both\n * match the print's behavior when an arc continues across a system wrap.\n * A row with fill segments but no ends at all renders one straight line.\n */\nexport function resolveArcs(cells: Cell[], noteCount: number): Arc[] {\n const arcs: Arc[] = [];\n let openStart: number | undefined;\n let sawEnds = false;\n const fillCols: number[] = [];\n\n const openAt = (col: number) => {\n sawEnds = true;\n if (openStart === undefined) openStart = col;\n };\n const closeAt = (col: number) => {\n sawEnds = true;\n if (openStart !== undefined) {\n arcs.push({ startCol: openStart, endCol: col, openLeft: false, openRight: false });\n openStart = undefined;\n } else {\n arcs.push({ startCol: 1, endCol: col, openLeft: true, openRight: false });\n }\n };\n\n for (const cell of cells) {\n const firstCol = cell.start + 1;\n const lastCol = cell.start + cell.notes.length;\n cell.notes.forEach((note, j) => {\n const col = cell.start + j + 1;\n if (note.meend === 'start') openAt(col);\n else if (note.meend === 'end') closeAt(col);\n for (const b of note.below ?? []) {\n if (!isArcRaw(b.raw)) continue;\n for (const ch of b.raw) {\n if (ch === 'w' || ch === 'W') openAt(firstCol);\n else if (ch === 'x' || ch === 'X') closeAt(lastCol);\n else fillCols.push(firstCol, lastCol);\n }\n }\n });\n }\n\n if (openStart !== undefined) {\n arcs.push({ startCol: openStart, endCol: Math.max(noteCount, 1), openLeft: false, openRight: true });\n } else if (!sawEnds && fillCols.length > 0) {\n arcs.push({\n startCol: Math.min(...fillCols),\n endCol: Math.max(...fillCols),\n openLeft: true,\n openRight: true,\n line: true,\n });\n }\n return arcs;\n}\n\n/* ------------------------------------------------------------------ */\n/* Raw-derived marks (codec grammar: src/convert/codec.ts) */\n/* ------------------------------------------------------------------ */\n\n/** Count ছেদ cut marks in a decoded chunk's raw — every `i`/`:` in a chunk\n * that decoded to notes is a cut mark per the body grammar. Rendered as\n * group-trailing marks (positional approximation; raw keeps the truth). */\nfunction cutMarkCount(raw: string | undefined): number {\n if (raw === undefined) return 0;\n return (raw.match(/[i:]/g) ?? []).length;\n}\n\n/** Beat-number label (above rows): pure digits + optional sam tick. */\nfunction parseBeatLabel(raw: string): { digits: string; sam: boolean } | undefined {\n const m = raw.match(/^([0-9]{1,2})([fF])?:?$/);\n if (!m) return undefined;\n return { digits: m[1]!, sam: m[2] !== undefined };\n}\n\n/* ------------------------------------------------------------------ */\n/* Note / annotation fragments */\n/* ------------------------------------------------------------------ */\n\ninterface Ctx {\n lang: ViewerLang;\n marks: LangMarks;\n tr: (s: string) => string;\n}\n\nconst BRACKET_GLYPHS = {\n open: { repeat: '{', skip: '(', alt: '[' },\n close: { repeat: '}', skip: ')', alt: ']' },\n} as const;\n\nfunction bracketGlyphs(note: Note, edge: 'open' | 'close'): string {\n if (!note.brackets) return '';\n return note.brackets\n .filter((b) => b.edge === edge)\n .map((b) => `<span class=\"sw-br\">${BRACKET_GLYPHS[edge][b.kind]}</span>`)\n .join('');\n}\n\n/** A lone matra glyph: the note's own notation font supplies it — bn = the\n * Swarabitan আ-কার (`a`), hi/en = an en-dash (Bhatkhande has no matra sign).\n * Used for rests (বিরাম = detached matra), আ-কার holds and n>1 durations. */\nfunction matraGlyph(ctx: Ctx): string {\n return ctx.lang === 'bn' ? '<span class=\"sw-cl\">a</span>' : '<span class=\"sw-iso\">–</span>';\n}\n\nfunction renderKan(note: Note, ctx: Ctx): string {\n if (!note.kan) return '';\n const [octave, letter] = note.kan;\n const c = composeCluster(letter, { octave, withMatra: false, lang: ctx.lang });\n return `<span class=\"${['sw-kan', ...c.classes].join(' ')}\">${c.text}</span>`;\n}\n\ninterface PitchedOpts {\n /** This note ends its matra group → carries the আ-কার. */\n withMatra: boolean;\n /** ছেদ cut marks rendered after this (group-final) note. */\n cuts: number;\n}\n\n/** Inner HTML of one pitched/sustain/rest note: brackets, kan, melisma\n * hyphen, notation-font cluster, extra matras, cut marks, closing brackets.\n * The font (keyed on lang in styles.ts) renders komal/tivra/octave/matra —\n * composeCluster only picks the ASCII, so there is no Unicode hazard here. */\nfunction renderPitchedInner(note: Note, opts: PitchedOpts, ctx: Ctx): string {\n let inner = bracketGlyphs(note, 'open');\n inner += renderKan(note, ctx);\n if (note.sustain === true) inner += `<span class=\"sw-hy\">${ctx.marks.hyphen}</span>`;\n if (note.svara !== undefined) {\n const [octave, letter] = note.svara;\n const c = composeCluster(letter, {\n komal: note.komal,\n tivra: note.tivra,\n octave,\n withMatra: opts.withMatra,\n lang: ctx.lang,\n });\n inner += `<span class=\"${['sw-cl', ...c.classes].join(' ')}\">${c.text}</span>`;\n } else if (note.rest === true) {\n inner += matraGlyph(ctx);\n } else if (note.sustain === true && opts.withMatra) {\n inner += matraGlyph(ctx);\n }\n if (note.microtone !== undefined) {\n // Legend: অল্পকোমল = superscript ১ after the letter, অতিকোমল = ২.\n const mark = localizeDigits(note.microtone === 'atikomal' ? '2' : '1', ctx.lang);\n inner += `<span class=\"sw-micro\" title=\"${note.microtone}\">${mark}</span>`;\n }\n const d = note.durationMatra ?? 1;\n if (isIntegral(d) && d > 1 + EPS) inner += matraGlyph(ctx).repeat(Math.round(d) - 1);\n if (opts.cuts > 0) inner += `<span class=\"sw-cut\">${NBSP}${ctx.marks.cut}</span>`.repeat(opts.cuts);\n inner += bracketGlyphs(note, 'close');\n return inner;\n}\n\n/** Swarabitan glyphs (the .sw-bar font): A = vibhag dari, l = I cycle\n * danda, L = II section pair, song-end = II II. */\nconst BAR_GLYPHS = { dari: 'A', single: 'l', double: 'L', quad: 'LL' } as const;\n\nfunction renderBarInner(note: Note): string {\n return `${bracketGlyphs(note, 'open')}${BAR_GLYPHS[note.bar!]}${bracketGlyphs(note, 'close')}`;\n}\n\n/**\n * Render an annotation note list (above/below content) as inline mini\n * notation: beat labels, stop marks, bars, recursive note groups, raw\n * fallback. Reuses the same grouping as the main row.\n */\nfunction renderAnnotation(notes: Note[], ctx: Ctx): string {\n const parts: string[] = [];\n for (const cell of groupRowIntoCells(notes)) {\n if (cell.kind === 'bar') {\n const note = cell.notes[0]!;\n parts.push(`<span class=\"sw-bar sw-bar--${note.bar}\">${renderBarInner(note)}</span>`);\n continue;\n }\n if (cell.kind === 'group') {\n const cuts = cutMarkCount(cell.notes[0]!.raw);\n cell.notes.forEach((note, j) => {\n const last = j === cell.notes.length - 1;\n parts.push(\n `<span class=\"sw-n\">${renderPitchedInner(note, { withMatra: last, cuts: last ? cuts : 0 }, ctx)}</span>`,\n );\n });\n continue;\n }\n const note = cell.notes[0]!;\n const raw = rawDisplay(note);\n if (raw !== undefined) {\n const beat = parseBeatLabel(raw);\n if (beat) {\n parts.push(\n `<span class=\"sw-beat${beat.sam ? ' sw-sam' : ''}\">${localizeDigits(beat.digits, ctx.lang)}</span>`,\n );\n } else if (/^\\|+$/.test(raw)) {\n parts.push(`<span class=\"sw-stop\">${'<i></i>'.repeat(raw.length)}</span>`);\n } else {\n parts.push(`<span class=\"sw-raw\" title=\"${escapeHtml(raw)}\">${escapeHtml(raw)}</span>`);\n }\n continue;\n }\n const brackets = bracketGlyphs(note, 'open') + bracketGlyphs(note, 'close');\n if (brackets !== '') parts.push(`<span class=\"sw-carrier\">${brackets}</span>`);\n }\n return parts.join('');\n}\n\n/** Lyric cell text: the ৹ melisma mark is notation (not language text) —\n * swap it per-lang, transliterating only the linguistic remainder. */\nfunction lyricText(s: string, ctx: Ctx): string {\n return s\n .split('৹')\n .map((part) => (part === '' ? '' : ctx.tr(part)))\n .join(ctx.marks.melisma);\n}\n\n/* ------------------------------------------------------------------ */\n/* Row / header / document */\n/* ------------------------------------------------------------------ */\n\nfunction renderRow(row: Row, partIdx: number, rowIdx: number, ctx: Ctx): string {\n const cells = groupRowIntoCells(row.notes);\n const arcs = resolveArcs(cells, row.notes.length);\n const above: string[] = [];\n const notation: string[] = [];\n const below: string[] = [];\n const lyric: string[] = [];\n\n for (const cell of cells) {\n const firstCol = cell.start + 1;\n const lastCol = cell.start + cell.notes.length;\n const cellSpan =\n lastCol > firstCol ? `grid-column:${firstCol} / ${lastCol + 1}` : `grid-column:${firstCol}`;\n const cuts = cell.kind === 'group' ? cutMarkCount(cell.notes[0]!.raw) : 0;\n\n cell.notes.forEach((note, j) => {\n const col = cell.start + j + 1;\n const path = `${partIdx}.${rowIdx}.${cell.start + j}`;\n const cellEdges = `${j === 0 ? ' sw-cs' : ''}${j === cell.notes.length - 1 ? ' sw-ce' : ''}`;\n\n if (cell.kind === 'bar') {\n notation.push(\n `<span class=\"sw-bar sw-bar--${note.bar}${cellEdges}\" data-note=\"${path}\" style=\"grid-column:${col}\">${renderBarInner(note)}</span>`,\n );\n } else if (cell.kind === 'group') {\n const last = j === cell.notes.length - 1;\n notation.push(\n `<span class=\"sw-n${cellEdges}\" data-note=\"${path}\" style=\"grid-column:${col}\">${renderPitchedInner(note, { withMatra: last, cuts: last ? cuts : 0 }, ctx)}</span>`,\n );\n } else {\n const raw = rawDisplay(note);\n const inner =\n bracketGlyphs(note, 'open') +\n (raw !== undefined\n ? `<span class=\"sw-raw\" title=\"${escapeHtml(raw)}\">${escapeHtml(raw)}</span>`\n : '') +\n bracketGlyphs(note, 'close');\n if (inner !== '') {\n notation.push(\n `<span class=\"sw-n sw-carrier${cellEdges}\" data-note=\"${path}\" style=\"grid-column:${col}\">${inner}</span>`,\n );\n }\n }\n\n if (note.lyric !== undefined) {\n // Share the cell-gap inset (sw-cs) with the notation above, so the\n // lyric column-aligns with its note instead of drifting one gap left.\n lyric.push(\n `<span class=\"sw-lyr${j === 0 ? ' sw-cs' : ''}\" style=\"grid-column:${col}\">${escapeHtml(lyricText(note.lyric, ctx))}</span>`,\n );\n }\n if (note.above !== undefined && note.above.length > 0) {\n above.push(`<span class=\"sw-above\" style=\"${cellSpan}\">${renderAnnotation(note.above, ctx)}</span>`);\n }\n const nonArc = (note.below ?? []).filter((b) => !isArcRaw(b.raw));\n if (nonArc.length > 0) {\n below.push(`<span class=\"sw-below\" style=\"${cellSpan}\">${renderAnnotation(nonArc, ctx)}</span>`);\n }\n });\n }\n\n for (const arc of arcs) {\n const cls = [\n 'sw-arc',\n arc.openLeft ? 'sw-arc--openl' : '',\n arc.openRight ? 'sw-arc--openr' : '',\n arc.line === true ? 'sw-arc--line' : '',\n ]\n .filter(Boolean)\n .join(' ');\n below.push(`<span class=\"${cls}\" style=\"grid-column:${arc.startCol} / ${arc.endCol + 1}\"></span>`);\n }\n\n const label =\n row.label !== undefined ? `<span class=\"sw-label\">${escapeHtml(ctx.tr(row.label))}</span>` : '';\n return `<div class=\"sw-row\">${label}<div class=\"sw-grid\">${above.join('')}${notation.join('')}${below.join('')}${lyric.join('')}</div></div>`;\n}\n\nfunction renderHeader(meta: Meta, ctx: Ctx): string {\n const L = LABELS[ctx.lang];\n const rows: string[] = [];\n const add = (label: string, value: string) =>\n rows.push(\n `<div class=\"sw-meta-row\"><span class=\"sw-meta-label\">${escapeHtml(label)}</span><span class=\"sw-meta-value\">${escapeHtml(value)}</span></div>`,\n );\n add(L.title, ctx.tr(meta.title));\n const taal = meta.taalName ?? meta.taal?.id;\n if (taal !== undefined) add(L.taal, ctx.tr(taal));\n if (meta.raag !== undefined) add(L.raag, ctx.tr(meta.raag));\n if (meta.avartan !== undefined) add(L.avartan, localizeDigits(String(meta.avartan), ctx.lang));\n if (meta.notationBy !== undefined) add(L.notationBy, ctx.tr(meta.notationBy));\n return `<header class=\"sw-header\">${rows.join('')}</header>`;\n}\n\n/** Render a complete swaralipi document to an HTML string. Pair with\n * SWARALIPI_CSS (shadow DOM does this automatically; SSR consumers emit a\n * `<style>` themselves). All source text is HTML-escaped. */\nexport function renderToHtml(doc: Swaralipi, opts: RenderOptions = {}): string {\n const lang: ViewerLang = opts.lang ?? 'bn';\n const tr = lang !== 'bn' && opts.transliterate ? opts.transliterate : (s: string) => s;\n const ctx: Ctx = { lang, marks: MARKS[lang], tr };\n\n const out: string[] = [`<div class=\"sw-sheet\" lang=\"${lang}\">`];\n if (opts.showHeader !== false) out.push(renderHeader(doc.meta, ctx));\n doc.parts.forEach((part, p) => {\n out.push('<section class=\"sw-part\">');\n if (part.name !== undefined)\n out.push(`<h3 class=\"sw-part-name\">${escapeHtml(ctx.tr(part.name))}</h3>`);\n part.rows.forEach((row, r) => out.push(renderRow(row, p, r, ctx)));\n out.push('</section>');\n });\n out.push('</div>');\n return out.join('');\n}\n","/**\n * Encapsulated stylesheet for the viewer. Injected into the\n * `<swaralipi-sheet>` shadow root automatically; SSR consumers emit it\n * themselves: `<style>${SWARALIPI_CSS}</style>` next to `renderToHtml()`.\n *\n * Theming hooks (CSS custom properties, all optional):\n * --sw-font font stack (default: Noto Sans Bengali + system Bengali)\n * --sw-size base font size\n * --sw-cell-gap horizontal gap between source cells\n * --sw-hl player-highlight background (P2.3)\n * --sw-rule header rule / muted line color\n *\n * All ink uses `currentColor`, so the sheet follows the host's text color\n * (dark mode included). The only octave mark drawn as a pseudo-element is\n * the bn ati-octave extra dot (Swarabitan's f/h glyphs are a single\n * reph/hasanta); everything else is a real glyph in the notation font.\n */\n\n/** Notation fonts, self-hosted on the project CDN (CORS-enabled), keyed by\n * the CSS `font-family` this stylesheet uses. bn = NLTR's Swarabitan; hi/en\n * = Ome Bhatkhande (SIL OFL 1.1, © Omenad — github.com/omenad/fonts).\n * Self-hosters: declare your own \\`@font-face\\` for any of these families\n * before this stylesheet / before defineSwaralipiSheet() and it wins. */\nexport const NOTATION_FONT_URLS: Record<string, string> = {\n Swarabitan: 'https://cdn.daserve.in/webfonts/swarabitan/Swarabitan.ttf',\n ome_bhatkhande_hindi: 'https://cdn.daserve.in/webfonts/ome-bhatkhande/OmeBhatkhandeHindi.ttf',\n ome_bhatkhande_english:\n 'https://cdn.daserve.in/webfonts/ome-bhatkhande/OmeBhatkhandeEnglish.ttf',\n};\n\n/** @deprecated use NOTATION_FONT_URLS.Swarabitan */\nexport const SWARABITAN_FONT_URL = NOTATION_FONT_URLS.Swarabitan;\n\n/* Each language renders its notation through one dedicated font — the\n * glyphs ARE the akarmatrik/Bhatkhande marks, keyed by plain ASCII (see\n * glyphs.ts). @font-face covers document use (SSR, print); the element also\n * registers these via the FontFace API because @font-face inside a shadow\n * root's adopted sheet is ignored. display:block — a flash of the ASCII\n * fallback ('kfa', 'srgm') would read as content. */\nconst FONT_FACES = Object.entries(NOTATION_FONT_URLS)\n .map(\n ([family, url]) =>\n `@font-face { font-family: ${family}; src: url('${url}') format('truetype'); font-display: block; }`,\n )\n .join('\\n');\n\nexport const SWARALIPI_CSS = `\n${FONT_FACES}\n\n.sw-sheet {\n font-family: var(--sw-font, 'Noto Sans Bengali', 'Kohinoor Bangla', 'Bangla Sangam MN', 'Nirmala UI', 'Noto Sans Devanagari', sans-serif);\n font-size: var(--sw-size, 1.125rem);\n line-height: 1.5;\n}\n\n/* ---- notation font, per language (the note clusters + grace notes) ---- */\n.sw-sheet[lang=\"bn\"] .sw-cl, .sw-sheet[lang=\"bn\"] .sw-kan { font-family: Swarabitan, var(--sw-font, sans-serif); }\n.sw-sheet[lang=\"hi\"] .sw-cl, .sw-sheet[lang=\"hi\"] .sw-kan { font-family: ome_bhatkhande_hindi, var(--sw-font, sans-serif); }\n.sw-sheet[lang=\"en\"] .sw-cl, .sw-sheet[lang=\"en\"] .sw-kan { font-family: ome_bhatkhande_english, var(--sw-font, sans-serif); }\n\n/* ---- header ---- */\n.sw-header {\n margin: 0 0 0.75em;\n padding: 0 0 0.5em;\n border-bottom: 1px solid var(--sw-rule, rgba(128, 128, 128, 0.35));\n font-size: 0.95em;\n}\n.sw-meta-row { display: flex; gap: 0.3em; }\n.sw-meta-label { font-weight: 600; min-width: 4.5em; }\n.sw-meta-label::after { content: ':'; font-weight: 400; margin-left: 0.15em; }\n\n.sw-part-name { font-size: 0.85em; font-weight: 600; margin: 1em 0 0.2em; opacity: 0.85; }\n\n/* ---- row grid: above / notation / below(arcs) / lyric ---- */\n.sw-row {\n display: flex;\n align-items: flex-start;\n overflow-x: auto;\n padding: 0.4em 0;\n}\n.sw-label { flex: none; margin-right: 0.8em; font-weight: 600; }\n.sw-grid {\n display: grid;\n grid-template-rows: auto auto auto auto;\n grid-auto-columns: max-content;\n align-items: end;\n}\n.sw-above { grid-row: 1; font-size: 0.62em; justify-self: start; white-space: nowrap; padding-left: 0.2em; }\n.sw-n { grid-row: 2; justify-self: center; white-space: nowrap; }\n.sw-arc,\n.sw-below { grid-row: 3; }\n.sw-lyr { grid-row: 4; justify-self: center; white-space: nowrap; padding-top: 0.3em; }\n.sw-below { font-size: 0.62em; justify-self: start; white-space: nowrap; padding-left: 0.2em; }\n\n/* inter-cell gap as padding on each cell's first notation item, so arcs\n * and above-spans crossing cells stay continuous */\n.sw-cs { padding-left: var(--sw-cell-gap, 0.55em); }\n\n/* ---- notation clusters & marks ---- */\n.sw-cl { position: relative; display: inline-block; }\n\n/* bn ati-octave: Swarabitan's f/h give a single reph/hasanta, so ati adds\n * one extra dot above (ati-taar) / below (ati-mandra). bn-only — hi/en get\n * the two-dot glyph natively from the U/L octave suffix. */\n.sw-ati-taar::before,\n.sw-ati-mandra::before {\n content: '';\n position: absolute;\n left: 0.25em;\n width: 0.16em;\n height: 0.16em;\n border-radius: 50%;\n background: currentColor;\n}\n.sw-ati-taar::before { top: -0.3em; }\n.sw-ati-mandra::before { bottom: -0.35em; }\n\n/* kan grace: small raised cluster left of the main note */\n.sw-kan {\n position: relative;\n display: inline-block;\n font-size: 0.58em;\n vertical-align: 0.75em;\n margin-right: 0.08em;\n}\n\n.sw-hy { padding-right: 0.02em; }\n.sw-iso { display: inline-block; margin-left: -0.18em; }\n.sw-cut { font-size: 0.8em; display: inline-block; margin-left: -0.15em; }\n.sw-br { opacity: 0.8; padding: 0 0.06em; }\n.sw-micro { font-size: 0.6em; vertical-align: super; opacity: 0.8; }\n\n/* raw fallback: never dropped, visibly non-notation. Swarabitan first —\n * raw IS that font's encoding, so undecoded cells show NLTR's own glyphs\n * (dimmed: semantics unverified); monospace ASCII when the font is out. */\n.sw-raw {\n font-family: Swarabitan, ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72em;\n opacity: 0.55;\n}\n\n/* ---- bars: dari (A) and danda (l/L) Swarabitan glyphs ---- */\n/* horizontal gap before a bar comes from its own .sw-cs padding-left —\n * never reset it with a padding shorthand here */\n.sw-bar {\n grid-row: 2;\n font-family: Swarabitan, var(--sw-font, sans-serif);\n white-space: nowrap;\n padding-right: 0.1em;\n}\n.sw-bar--quad { letter-spacing: 0.15em; }\n\n/* ---- under-arcs (slurs decoded from w/x segments and meend) ---- */\n.sw-arc {\n align-self: start;\n height: 0.4em;\n margin: 0.05em 0.25em 0;\n border: 0.09em solid currentColor;\n border-top: none;\n border-bottom-left-radius: 0.6em;\n border-bottom-right-radius: 0.6em;\n opacity: 0.85;\n}\n.sw-arc--openl { border-left: none; border-bottom-left-radius: 0; }\n.sw-arc--openr { border-right: none; border-bottom-right-radius: 0; }\n.sw-arc--line { border-left: none; border-right: none; border-radius: 0; height: 0.22em; }\n\n/* ---- annotation content ---- */\n.sw-beat { position: relative; display: inline-block; padding: 0 0.1em; }\n.sw-sam::after {\n content: '';\n position: absolute;\n top: -0.45em;\n left: 50%;\n width: 0.1em;\n height: 0.4em;\n background: currentColor;\n transform: rotate(14deg);\n}\n.sw-stop i {\n display: inline-block;\n width: 0.07em;\n height: 1em;\n margin: 0 0.07em;\n background: currentColor;\n vertical-align: text-bottom;\n}\n\n/* ---- player sync (P2.3) ---- */\n.sw-hl { background: var(--sw-hl, rgba(255, 196, 64, 0.45)); border-radius: 0.15em; }\n\n/* ---- element error box ---- */\n.sw-error {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n padding: 0.6em 0.8em;\n border: 1px solid rgba(200, 64, 64, 0.6);\n border-radius: 0.3em;\n color: #b33;\n background: rgba(200, 64, 64, 0.08);\n}\n`;\n\n/**\n * Print stylesheet — pair with `SWARALIPI_CSS` (renderPrintDocument injects\n * both). Gated on `@media print`, so it also works if a consumer drops it into\n * a page and prints that page directly.\n *\n * - `print-color-adjust: exact` forces the marks that are drawn as tiny\n * `background: currentColor` pseudo-elements (octave dots, arcs, danda\n * strokes, sam tick) to actually print — browsers drop backgrounds by\n * default, which would silently strip the notation's diacritics.\n * - rows are un-clipped (no scrollbar on paper) and kept whole across page\n * breaks; part headings stay with their first row.\n */\nexport const SWARALIPI_PRINT_CSS = `\n@page { margin: 16mm; }\n@media print {\n .sw-sheet { -webkit-print-color-adjust: exact; print-color-adjust: exact; color: #000; }\n .sw-row { overflow: visible !important; break-inside: avoid; page-break-inside: avoid; }\n .sw-part { break-inside: auto; }\n .sw-part-name, .sw-header { break-after: avoid-page; page-break-after: avoid; }\n .sw-hl { background: none !important; }\n}\n`;\n","/**\n * Print / \"Save as PDF\" support.\n *\n * High-fidelity PDF of আকারমাত্রিক notation can only come from the browser's\n * own print engine — it reuses the exact HarfBuzz shaping (reph, conjuncts,\n * matra) and the CSS-drawn marks (octave dots, slur arcs, danda strokes) that\n * the viewer renders on screen. Rasterizers (html2canvas) and PDF-primitive\n * libraries (jsPDF/pdfmake) have no Indic shaping and drop pseudo-element\n * marks, so we deliberately avoid them.\n *\n * `renderPrintDocument` builds a self-contained HTML page from the pure\n * `renderToHtml` + `SWARALIPI_CSS` (so it sidesteps the shadow-DOM \"print drops\n * encapsulated styles\" gotcha); `printSwaralipi` prints it via a hidden iframe.\n * Both reuse the same renderer as the viewer, so the PDF matches the screen.\n */\nimport type { Swaralipi } from '../spec/index.js';\nimport type { ViewerLang } from './glyphs.js';\nimport { renderToHtml } from './render.js';\nimport { SWARALIPI_CSS, SWARALIPI_PRINT_CSS } from './styles.js';\n\nexport interface PrintOptions {\n /** Notation + UI language. Default `bn`. */\n lang?: ViewerLang;\n /** Render the নাম/তাল header block. Default true. */\n showHeader?: boolean;\n /** Lyric/title transliterator for hi/en (see loadLyricTransliterator). */\n transliterate?: (bengaliText: string) => string;\n /** Document `<title>` — the browser's default \"Save as PDF\" filename.\n * Defaults to the document's `meta.title`. */\n title?: string;\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/**\n * Build a complete, standalone HTML document for printing a swaralipi sheet:\n * the rendered notation plus `SWARALIPI_CSS` and the print stylesheet, on a\n * white page. Usable for a hidden-iframe print, a new browser tab, or\n * server-side headless-Chrome PDF generation.\n */\nexport function renderPrintDocument(doc: Swaralipi, opts: PrintOptions = {}): string {\n const lang: ViewerLang = opts.lang ?? 'bn';\n const tr = lang !== 'bn' && opts.transliterate ? opts.transliterate : (s: string) => s;\n const title = opts.title ?? tr(doc.meta.title);\n const body = renderToHtml(doc, {\n lang,\n showHeader: opts.showHeader,\n transliterate: opts.transliterate,\n });\n return `<!doctype html>\n<html lang=\"${escapeHtml(lang)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeHtml(title)}</title>\n<style>\n${SWARALIPI_CSS}\n${SWARALIPI_PRINT_CSS}\nhtml, body { margin: 0; }\nbody { color: #111; background: #fff; padding: 16px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }\n.sw-sheet { max-width: 100%; }\n</style>\n</head>\n<body>${body}</body>\n</html>`;\n}\n\n/**\n * Open the browser print dialog for a swaralipi document (the user picks a\n * printer or \"Save as PDF\"). Renders into an off-screen iframe so it prints\n * only the sheet — independent of the host page's chrome and CSS — then cleans\n * up. Browser-only; throws in a non-DOM environment (use renderPrintDocument\n * for SSR / headless-Chrome instead).\n */\nexport function printSwaralipi(doc: Swaralipi, opts: PrintOptions = {}): void {\n if (typeof document === 'undefined') {\n throw new Error('printSwaralipi requires a DOM; use renderPrintDocument() for server-side PDF');\n }\n const html = renderPrintDocument(doc, opts);\n const iframe = document.createElement('iframe');\n iframe.setAttribute('aria-hidden', 'true');\n // off-screen but rendered (display:none iframes print blank); a page-ish\n // width so rows lay out before the print stylesheet takes over.\n iframe.style.cssText = 'position:fixed; left:-10000px; top:0; width:800px; height:600px; border:0;';\n\n iframe.onload = () => {\n const win = iframe.contentWindow;\n if (win === null) {\n iframe.remove();\n return;\n }\n const cleanup = () => setTimeout(() => iframe.remove(), 1000);\n win.addEventListener('afterprint', cleanup, { once: true });\n let printed = false;\n const go = () => {\n if (printed) return;\n printed = true;\n try {\n win.focus();\n win.print();\n } catch {\n /* printing unavailable (e.g. headless) — leave cleanup to afterprint */\n }\n };\n // The notation is rendered ENTIRELY in the CDN notation fonts, so a\n // not-yet-downloaded face prints as raw ASCII — or blank, under\n // `font-display: block`. `fonts.ready` alone is not enough: it can resolve\n // before layout has even requested the faces. Force each declared face to\n // download, then print; a timeout prints anyway so a slow/unreachable font\n // (e.g. a lang whose CDN font isn't up yet) never blocks the dialog.\n const fonts = iframe.contentDocument?.fonts;\n if (fonts && typeof fonts.forEach === 'function') {\n const loads: Promise<unknown>[] = [Promise.resolve(fonts.ready)];\n fonts.forEach((face) => loads.push(face.load().catch(() => undefined)));\n void Promise.all(loads).then(go);\n setTimeout(go, 3000); // never let a slow/unreachable font block the dialog\n } else {\n setTimeout(go, 250);\n }\n };\n\n iframe.srcdoc = html;\n document.body.appendChild(iframe);\n}\n","/**\n * Lazy lyric transliteration for `hi` / `en` renders.\n *\n * Swara glyphs come from the sync tables in glyphs.ts; only *linguistic*\n * text (lyrics, title, names) needs transliteration, so sanscript loads via\n * dynamic import — `bn`-only consumers (and their bundles) never touch it.\n */\nimport type { ViewerLang } from './glyphs.js';\n\nexport type Transliterator = (bengaliText: string) => string;\n\nconst TARGET: Record<Exclude<ViewerLang, 'bn'>, string> = {\n hi: 'devanagari',\n en: 'iast',\n};\n\n/**\n * Load a Bengali→target transliterator for the given viewer language.\n * Returns undefined for `bn` (no work to do). Pass the result as\n * `RenderOptions.transliterate`; the `<swaralipi-sheet>` element wires this\n * automatically when its `lang` attribute changes.\n */\nexport async function loadLyricTransliterator(lang: ViewerLang): Promise<Transliterator | undefined> {\n if (lang === 'bn') return undefined;\n const mod = (await import('@indic-transliteration/sanscript')) as {\n default?: { t(text: string, from: string, to: string): string };\n t?(text: string, from: string, to: string): string;\n };\n const sanscript = mod.default ?? mod;\n const target = TARGET[lang];\n return (text) => sanscript.t!(text, 'bengali', target);\n}\n","/**\n * The `<swaralipi-sheet>` custom element — a thin shadow-DOM shell around\n * the pure renderer.\n *\n * The element class is created lazily inside defineSwaralipiSheet():\n * a top-level `extends HTMLElement` would throw on import in Node, and this\n * module must stay importable for SSR (where only renderToHtml is used).\n * Nothing registers automatically — call defineSwaralipiSheet() once.\n *\n * Validation is off by default (converter output is pre-validated); setting\n * `validate = true` parses documents against the Zod schema via a dynamic\n * import, so the viewer bundle stays free of bare runtime imports (it can\n * be loaded directly from dist/ in a browser without a bundler).\n */\nimport type { Swaralipi } from '../spec/index.js';\nimport { renderToHtml } from './render.js';\nimport { SWARALIPI_CSS, NOTATION_FONT_URLS } from './styles.js';\nimport { printSwaralipi, type PrintOptions } from './print.js';\nimport { loadLyricTransliterator, type Transliterator } from './transliterate.js';\nimport type { ViewerLang } from './glyphs.js';\n\nexport interface SwaralipiSheetElement extends HTMLElement {\n /** The document to render (property only; renders on assignment). */\n doc: Swaralipi | undefined;\n /** Parse documents against the spec schema before rendering. */\n validate: boolean;\n /** Add the player-highlight class to the note at \"part.row.note\". */\n highlight(path: string): HTMLElement | null;\n clearHighlights(): void;\n /** Open the print dialog (→ \"Save as PDF\") for the current document. */\n print(options?: PrintOptions): void;\n}\n\nconst LANGS: ReadonlySet<string> = new Set(['bn', 'hi', 'en']);\n\n/** Browsers ignore @font-face inside a shadow root's (adopted) stylesheet —\n * faces must live at document scope, so register the notation fonts there\n * via the FontFace API. No-op without FontFace (jsdom/SSR) or for any family\n * already present (SSR CSS on the page, or a self-hoster's own declaration). */\nfunction ensureNotationFonts(): void {\n if (typeof FontFace === 'undefined' || typeof document === 'undefined') return;\n const present = new Set<string>();\n for (const f of document.fonts) present.add(f.family.replace(/['\"]/g, ''));\n for (const [family, url] of Object.entries(NOTATION_FONT_URLS)) {\n if (present.has(family)) continue;\n document.fonts.add(new FontFace(family, `url(${url})`, { display: 'block' }));\n }\n}\n\nlet sharedSheet: CSSStyleSheet | undefined;\n\nfunction createElementClass(): CustomElementConstructor {\n return class SwaralipiSheet extends HTMLElement implements SwaralipiSheetElement {\n static observedAttributes = ['src', 'lang', 'hide-header'];\n\n #doc: Swaralipi | undefined;\n #root: ShadowRoot;\n #adopted = false;\n #abort: AbortController | undefined;\n #translit: Transliterator | undefined;\n #translitLang: ViewerLang | undefined;\n validate = false;\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n if (\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype &&\n 'adoptedStyleSheets' in this.#root\n ) {\n if (!sharedSheet) {\n sharedSheet = new CSSStyleSheet();\n sharedSheet.replaceSync(SWARALIPI_CSS);\n }\n this.#root.adoptedStyleSheets = [...this.#root.adoptedStyleSheets, sharedSheet];\n this.#adopted = true;\n }\n }\n\n get doc(): Swaralipi | undefined {\n return this.#doc;\n }\n\n set doc(value: Swaralipi | undefined) {\n this.#doc = value;\n if (value !== undefined && this.validate) {\n void import('../spec/index.js')\n .then(({ safeParseSwaralipi }) => {\n const result = safeParseSwaralipi(value);\n if (!result.success) this.#renderError(result.error.message);\n })\n .catch(() => undefined);\n }\n this.#render();\n }\n\n get #lang(): ViewerLang {\n const attr = this.getAttribute('lang');\n return attr !== null && LANGS.has(attr) ? (attr as ViewerLang) : 'bn';\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (name === 'src') {\n if (newValue !== null) void this.#load(newValue);\n return;\n }\n if (name === 'lang') this.#ensureTransliterator();\n this.#render();\n }\n\n connectedCallback(): void {\n this.#ensureTransliterator();\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.#abort?.abort();\n }\n\n async #load(url: string): Promise<void> {\n this.#abort?.abort();\n const abort = new AbortController();\n this.#abort = abort;\n try {\n const res = await fetch(url, { signal: abort.signal });\n if (!res.ok) throw new Error(`fetch ${url}: HTTP ${res.status}`);\n this.doc = (await res.json()) as Swaralipi;\n } catch (err) {\n if (abort.signal.aborted) return;\n this.#renderError(err instanceof Error ? err.message : String(err));\n this.dispatchEvent(new ErrorEvent('error', { error: err, message: String(err) }));\n }\n }\n\n /** Load (once per lang) the lyric transliterator, then re-render. */\n #ensureTransliterator(): void {\n const lang = this.#lang;\n if (lang === 'bn' || this.#translitLang === lang) return;\n void loadLyricTransliterator(lang)\n .then((t) => {\n if (t === undefined || this.#lang !== lang) return;\n this.#translit = t;\n this.#translitLang = lang;\n this.#render();\n })\n .catch(() => undefined); // graceful: lyrics stay Bengali\n }\n\n #styleFallback(): string {\n return this.#adopted ? '' : `<style>${SWARALIPI_CSS}</style>`;\n }\n\n #render(): void {\n if (this.#doc === undefined) {\n this.#root.innerHTML = this.#styleFallback();\n return;\n }\n const lang = this.#lang;\n const html = renderToHtml(this.#doc, {\n lang,\n showHeader: !this.hasAttribute('hide-header'),\n transliterate: this.#translitLang === lang ? this.#translit : undefined,\n });\n this.#root.innerHTML = this.#styleFallback() + html;\n }\n\n #renderError(message: string): void {\n const div = document.createElement('div');\n div.className = 'sw-error';\n div.textContent = message;\n this.#root.innerHTML = this.#styleFallback();\n this.#root.appendChild(div);\n }\n\n highlight(path: string): HTMLElement | null {\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(path)) return null;\n const el = this.#root.querySelector<HTMLElement>(`[data-note=\"${path}\"]`);\n el?.classList.add('sw-hl');\n return el;\n }\n\n clearHighlights(): void {\n for (const el of this.#root.querySelectorAll('.sw-hl')) el.classList.remove('sw-hl');\n }\n\n print(options: PrintOptions = {}): void {\n if (this.#doc === undefined) return;\n const lang = this.#lang;\n printSwaralipi(this.#doc, {\n lang,\n showHeader: !this.hasAttribute('hide-header'),\n transliterate: this.#translitLang === lang ? this.#translit : undefined,\n ...options,\n });\n }\n };\n}\n\n/** Per-tag constructors: a custom-element class can only be registered\n * under one name, so each tag gets its own. */\nconst registered = new Map<string, CustomElementConstructor>();\n\n/**\n * Register `<swaralipi-sheet>` (or a custom tag name). Idempotent. Throws\n * outside a DOM environment — use renderToHtml() for SSR.\n */\nexport function defineSwaralipiSheet(tagName = 'swaralipi-sheet'): CustomElementConstructor {\n if (typeof customElements === 'undefined' || typeof HTMLElement === 'undefined') {\n throw new Error('swaralipi-sheet requires a DOM; use renderToHtml() for server-side rendering');\n }\n const existing = customElements.get(tagName);\n if (existing) return existing;\n ensureNotationFonts();\n const ctor = registered.get(tagName) ?? createElementClass();\n registered.set(tagName, ctor);\n customElements.define(tagName, ctor);\n return ctor;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ugfoundation/swaralipi-js",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "JSON spec, Unicode-Bengali viewer, and Tone.js player for Rabindrasangeet swaralipi (আকারমাত্রিক notation).",
5
5
  "type": "module",
6
6
  "license": "GPL-2.0-only",
@@ -82,7 +82,16 @@
82
82
  "tone": "^15.0.4",
83
83
  "zod": "^3.25.76"
84
84
  },
85
+ "peerDependencies": {
86
+ "@breezystack/lamejs": ">=1.2.0"
87
+ },
88
+ "peerDependenciesMeta": {
89
+ "@breezystack/lamejs": {
90
+ "optional": true
91
+ }
92
+ },
85
93
  "devDependencies": {
94
+ "@breezystack/lamejs": "^1.2.7",
86
95
  "@types/node": "^22.10.0",
87
96
  "fontkit": "^2.0.4",
88
97
  "jsdom": "^29.0.0",